|
@@ -0,0 +1,443 @@
|
|
|
+package com.cooleshow.teacher.ui.web;
|
|
|
+
|
|
|
+import android.content.ActivityNotFoundException;
|
|
|
+import android.content.Intent;
|
|
|
+import android.graphics.Bitmap;
|
|
|
+import android.graphics.Color;
|
|
|
+import android.net.Uri;
|
|
|
+import android.os.Build;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.View;
|
|
|
+import android.webkit.GeolocationPermissions;
|
|
|
+import android.webkit.ValueCallback;
|
|
|
+import android.webkit.WebChromeClient;
|
|
|
+import android.webkit.WebResourceError;
|
|
|
+import android.webkit.WebResourceRequest;
|
|
|
+import android.webkit.WebSettings;
|
|
|
+import android.webkit.WebView;
|
|
|
+import android.webkit.WebViewClient;
|
|
|
+import android.widget.FrameLayout;
|
|
|
+
|
|
|
+
|
|
|
+import com.cooleshow.base.BuildConfig;
|
|
|
+import com.cooleshow.base.common.WebConstants;
|
|
|
+import com.cooleshow.base.constanst.ErrorConstants;
|
|
|
+import com.cooleshow.base.constanst.ErrorType;
|
|
|
+import com.cooleshow.base.constanst.LoginStatusConstants;
|
|
|
+import com.cooleshow.base.event.LoginStatusEvent;
|
|
|
+import com.cooleshow.base.ui.fragment.BaseFragment;
|
|
|
+import com.cooleshow.base.utils.LOG;
|
|
|
+import com.cooleshow.base.utils.ToastUtil;
|
|
|
+import com.cooleshow.base.utils.helper.LogUploadManager;
|
|
|
+import com.cooleshow.base.widgets.HttpsServerCertWebViewClient;
|
|
|
+import com.cooleshow.teacher.databinding.FgScHomeWebBinding;
|
|
|
+import com.cooleshow.teacher.widgets.LollipopFixedWebView;
|
|
|
+import com.cooleshow.teacher.widgets.helper.JsInterfaceUtils;
|
|
|
+import com.cooleshow.usercenter.helper.UserHelper;
|
|
|
+
|
|
|
+import org.greenrobot.eventbus.EventBus;
|
|
|
+import org.greenrobot.eventbus.Subscribe;
|
|
|
+import org.greenrobot.eventbus.ThreadMode;
|
|
|
+import org.json.JSONObject;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Author by pq, Date on 2024/12/30.
|
|
|
+ */
|
|
|
+public class ScHtmlFragment extends BaseFragment<FgScHomeWebBinding> implements JsInterfaceUtils.onGetMethodsListener {
|
|
|
+
|
|
|
+ private WebView webView;
|
|
|
+ private boolean isNeedRefresh = false;
|
|
|
+ private boolean isLoadError = false;
|
|
|
+ private boolean isLoadCompleted = false;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onCreate(Bundle savedInstanceState) {
|
|
|
+ super.onCreate(savedInstanceState);
|
|
|
+ EventBus.getDefault().register(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected FgScHomeWebBinding getLayoutView() {
|
|
|
+ return FgScHomeWebBinding.inflate(getLayoutInflater());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void initView(View rootView) {
|
|
|
+ try {
|
|
|
+ if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23) {
|
|
|
+ webView = new LollipopFixedWebView(getContext());
|
|
|
+ } else {
|
|
|
+ webView = new WebView(getContext());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ if (null == webView) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ webView.setBackgroundColor(Color.TRANSPARENT);
|
|
|
+ mViewBinding.viewParent.addView(webView, new FrameLayout.LayoutParams(
|
|
|
+ FrameLayout.LayoutParams.MATCH_PARENT,
|
|
|
+ FrameLayout.LayoutParams.MATCH_PARENT));
|
|
|
+ initWebView();
|
|
|
+ String webViewUrl = WebConstants.HOME_STATISTICS;
|
|
|
+ LOG.i("pq", "webViewUrl:" + webViewUrl);
|
|
|
+ webView.loadUrl(UserHelper.getSpliceTokenUrl(webViewUrl));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initWebView() {
|
|
|
+ //声明WebSettings子类
|
|
|
+ WebSettings webSettings = webView.getSettings();
|
|
|
+ webSettings.setUserAgentString(webSettings.getUserAgentString() + WebConstants.WEB_UA_PARAMS);
|
|
|
+ webSettings.setGeolocationDatabasePath(getContext().getFilesDir().getPath());
|
|
|
+ webSettings.setGeolocationEnabled(true);
|
|
|
+ webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
|
|
|
+ //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
|
|
|
+ webSettings.setJavaScriptEnabled(true);
|
|
|
+ webSettings.setMediaPlaybackRequiresUserGesture(false);//false允许自动播放音视频
|
|
|
+ //是否启用缓存
|
|
|
+ webSettings.setAppCacheEnabled(true);
|
|
|
+
|
|
|
+ // 开启DOM缓存,默认状态下是不支持LocalStorage的
|
|
|
+ webSettings.setDomStorageEnabled(true);
|
|
|
+ // 开启数据库缓存
|
|
|
+ webSettings.setDatabaseEnabled(true);
|
|
|
+ // 地址跨域导致视频预览图片加载不出来 无法播放:
|
|
|
+ webSettings.setAllowUniversalAccessFromFileURLs(false);
|
|
|
+ webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
|
|
+
|
|
|
+ //设置自适应屏幕,两者合用
|
|
|
+ webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
|
|
|
+ webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
|
|
|
+ //缩放操作
|
|
|
+ webSettings.setSupportZoom(false); //支持缩放,默认为true。是下面那个的前提。
|
|
|
+ // 设置允许JS弹窗
|
|
|
+ webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
|
|
|
+ //其他细节操作
|
|
|
+ webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); //关闭webview中缓存
|
|
|
+ webSettings.setAllowFileAccess(true); //设置可以访问文件
|
|
|
+ webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
|
|
|
+ webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
|
|
|
+ webSettings.setDefaultTextEncodingName("UTF-8");//设置编码格式
|
|
|
+
|
|
|
+ webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS); //富文本适配
|
|
|
+ webSettings.setAppCacheMaxSize(Long.MAX_VALUE);
|
|
|
+ webSettings.setAppCachePath(getContext().getDir("appcache", 0).getPath());
|
|
|
+ webSettings.setDatabasePath(getContext().getDir("databases", 0).getPath());
|
|
|
+ webSettings.setGeolocationDatabasePath(getContext().getDir("geolocation", 0)
|
|
|
+ .getPath());
|
|
|
+ webSettings.setPluginState(WebSettings.PluginState.ON_DEMAND);
|
|
|
+ if (BuildConfig.DEBUG) {
|
|
|
+ webView.setWebContentsDebuggingEnabled(true);
|
|
|
+ }
|
|
|
+ webSettings.setTextZoom(100);//设置字体默认的缩放比例,以避免手机系统的字体修改对页面字体及布局造成影响。
|
|
|
+ webView.setHorizontalScrollBarEnabled(false);
|
|
|
+ webView.setVerticalScrollBarEnabled(false);
|
|
|
+ JsInterfaceUtils jsInterfaceUtils = new JsInterfaceUtils(getActivity());
|
|
|
+ jsInterfaceUtils.setOnItemClickListener(this);
|
|
|
+ webView.setWebViewClient(new WebClient());
|
|
|
+ webView.setWebChromeClient(new MyWebChromeClient());
|
|
|
+ webView.addJavascriptInterface(jsInterfaceUtils, WebConstants.WEB_JS_INTERFACE);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void initData() {
|
|
|
+ mViewBinding.errorView.hideBack();
|
|
|
+ mViewBinding.errorView.setOnRefreshClickListener(new View.OnClickListener() {
|
|
|
+ @Override
|
|
|
+ public void onClick(View v) {
|
|
|
+ if (webView != null) {
|
|
|
+ reloadWeb();
|
|
|
+ hideErrorView();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void reloadWeb() {
|
|
|
+ if (webView != null) {
|
|
|
+ webView.reload();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onResume() {
|
|
|
+ super.onResume();
|
|
|
+ if (isNeedRefresh) {
|
|
|
+ isNeedRefresh = false;
|
|
|
+ reloadWeb();
|
|
|
+ } else {
|
|
|
+ refresh();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showWebView() {
|
|
|
+ mViewBinding.viewParent.setVisibility(View.VISIBLE);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void hideErrorView() {
|
|
|
+ mViewBinding.flError.setVisibility(View.GONE);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showLoadErrorView() {
|
|
|
+ isLoadError = true;
|
|
|
+ mViewBinding.viewParent.setVisibility(View.GONE);
|
|
|
+ mViewBinding.flError.setVisibility(View.VISIBLE);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void notifyWebViewOnResume() {
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ try {
|
|
|
+ jsonObject.put("api", "webViewOnResume");
|
|
|
+ onSendMessage(jsonObject.toString());
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendStickyTopMessage(int mode) {
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ try {
|
|
|
+ jsonObject.put("api", "stickyTop");
|
|
|
+ JSONObject contentJson = new JSONObject();
|
|
|
+ contentJson.put("status", mode);
|
|
|
+ jsonObject.put("content", contentJson);
|
|
|
+ onSendMessage(jsonObject.toString());
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onSendMessage(String message) {
|
|
|
+ Log.i("pq", "post message:" + message);
|
|
|
+ webView.evaluateJavascript("postMessage('" + message + "','*')", new ValueCallback<String>() {
|
|
|
+ @Override
|
|
|
+ public void onReceiveValue(String s) {
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onAccompanySelecResult(String id, String name) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void chooseFile(JSONObject message) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void createRightNavToShareButton(String image, String url) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void shareAchievements(JSONObject message) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void backIconChange(JSONObject message) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void getNavHeight(JSONObject message) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setBarStatus(JSONObject message) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void authToBack(JSONObject message) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void joinLiveRoom(String roomId, String teacherId) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void joinChatGroup(String type, String id) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void paymentOrder(String orderNo, String payChannel, String payInfo) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void savePicture(String base64, String uuid) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void shareTripartite(JSONObject jsonObject) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void videoCrop(JSONObject jsonObject) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void checkCoursewareCache(JSONObject jsonObject) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void downloadCourseware(String toString) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void cloudLoading(JSONObject jsonObject) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onBackPress() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void downloadFile(String url, String fileName) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setStatusBarTextColor(boolean statusBarTextColor) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void saveFile(JSONObject jsonObject) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void refresh() {
|
|
|
+ if (isLoadError) {
|
|
|
+ reloadWeb();
|
|
|
+ }
|
|
|
+ notifyWebViewOnResume();
|
|
|
+ }
|
|
|
+
|
|
|
+ private class WebClient extends HttpsServerCertWebViewClient {
|
|
|
+ //页面开始载入时调用
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
|
|
+ super.onPageStarted(view, url, favicon);
|
|
|
+ isLoadError = false;
|
|
|
+ isLoadCompleted = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //页面载入结束时调用
|
|
|
+ @Override
|
|
|
+ public void onPageFinished(WebView view, String url) {
|
|
|
+ super.onPageFinished(view, url);
|
|
|
+ if (!isLoadError) {
|
|
|
+ isLoadCompleted = true;
|
|
|
+ showWebView();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //截取url请求,在当前视图加载,避免在跳转到自带浏览器
|
|
|
+ @Override
|
|
|
+ public boolean shouldOverrideUrlLoading(WebView view, String request) {
|
|
|
+ if (!(request.startsWith("http://") || request.startsWith("https://"))) {
|
|
|
+ try {
|
|
|
+ Intent intent = new Intent();
|
|
|
+ intent.setAction(Intent.ACTION_VIEW);
|
|
|
+ intent.setData(Uri.parse(request));
|
|
|
+ startActivity(intent);
|
|
|
+ } catch (ActivityNotFoundException e) {
|
|
|
+ ToastUtil.getInstance().show(getContext().getApplicationContext(), "未安装该应用");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ view.loadUrl(request);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //处理报错信息
|
|
|
+ @Override
|
|
|
+ public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
|
|
+ super.onReceivedError(view, request, error);
|
|
|
+ if (error != null) {
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
+ LOG.i("onReceivedError:" + error.getErrorCode());
|
|
|
+ LOG.i("onReceivedError:" + error.getDescription());
|
|
|
+ int errorCode = error.getErrorCode();
|
|
|
+ if (errorCode == WebViewClient.ERROR_HOST_LOOKUP || errorCode == WebViewClient.ERROR_CONNECT || errorCode == WebViewClient.ERROR_PROXY_AUTHENTICATION) {
|
|
|
+ if (isLoadCompleted) {
|
|
|
+ //20240827同步加载完后的error不需要显示 错误页
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ showLoadErrorView();
|
|
|
+ } else {
|
|
|
+ if (error.getErrorCode() == WebViewClient.ERROR_UNKNOWN) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String errorMsg = "url:" + request.getUrl().toString() + " " + error.getDescription();
|
|
|
+ LogUploadManager.getInstance().uploadErrorLog(ErrorType.HTML_ERROR, ErrorConstants.getErrorMsg(error.getErrorCode(), errorMsg));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private class MyWebChromeClient extends WebChromeClient {
|
|
|
+ public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
|
|
|
+ callback.invoke(origin, true, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onProgressChanged(WebView view, int newProgress) {
|
|
|
+ LOG.e(newProgress + "");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onReceivedTitle(WebView view, String title) {
|
|
|
+ super.onReceivedTitle(view, title);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Android > 5.0.1
|
|
|
+ public boolean onShowFileChooser(
|
|
|
+ WebView webView, ValueCallback<Uri[]> filePathCallback,
|
|
|
+ FileChooserParams fileChooserParams) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private CustomViewCallback mCustomViewCallback;
|
|
|
+ // 横屏时,显示视频的view
|
|
|
+ private View mCustomView;
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
+ public void loadEventBus(LoginStatusEvent event) {
|
|
|
+ if (event != null && event.eventCode == LoginStatusConstants.LOGIN_OUT) {
|
|
|
+ isNeedRefresh = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onDestroy() {
|
|
|
+ super.onDestroy();
|
|
|
+ EventBus.getDefault().unregister(this);
|
|
|
+ }
|
|
|
+}
|