package cn.mutils.app.ui.web; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.RelativeLayout; import cn.mutils.app.event.listener.OnActivityResultListener; import cn.mutils.app.ui.StateView; /** * Implements {@link IWebFrame} */ @SuppressLint({"AddJavascriptInterface", "NewApi", "SetJavaScriptEnabled"}) @SuppressWarnings({"serial", "StringBufferReplaceableByString"}) public class WebFrame extends StateView implements IWebFrame { protected WebView mWebView; protected WebFrameChromeClient mWebFrameChromeClient; protected IWebJSInterface mWebJSInterface; protected IWebMessageManager mWebMessageManager; public WebFrame(Context context) { super(context); init(context, null); } public WebFrame(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public WebFrame(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs); } protected void init(Context context, AttributeSet attrs) { WebFrameDownloadListener dListener = new WebFrameDownloadListener(); dListener.setContext(context); mWebFrameChromeClient = new WebFrameChromeClient(); mWebFrameChromeClient.setContext(context); mWebView = new WebView(context); mWebView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)); mWebView.setWebViewClient(new WebFrameClient()); mWebView.setDownloadListener(dListener); mWebView.setWebChromeClient(mWebFrameChromeClient); WebSettings settings = mWebView.getSettings(); settings.setJavaScriptEnabled(true); settings.setCacheMode(WebSettings.LOAD_NO_CACHE); this.addView(mWebView); this.setWebJSInterface(new WebJSInterface()); this.setWebMessageManager(new WebMessageManager()); this.addOnActivityResultListener(new OnWebActivityResultListener()); } public String getLogs() { return mWebFrameChromeClient.getLogs(); } public void setDebug(boolean debug) { mWebFrameChromeClient.setDebug(debug); } public void setFileChooserRequestCode(int requestCode) { mWebFrameChromeClient.setFileChooserRequestCode(requestCode); } @Override public void onDestroy() { if (mWebMessageManager != null) { mWebMessageManager.clear(); } super.onDestroy(); } public void add(Class<? extends IWebMessageDispatcher<?>> dispatcherClass) { if (mWebMessageManager != null) { mWebMessageManager.add(dispatcherClass); } } @Override public void sendMessage(String json) { getMainHandler().post(new DispatchMessageRunnable(json)); } @Override public void postMessage(String json) { getMainHandler().post(new DispatchMessageRunnable(json)); } @Override public void onMessage(String json) { if (mWebJSInterface == null) { return; } StringBuilder sb = new StringBuilder(); sb.append("javascript:"); sb.append(mWebJSInterface.name()); sb.append("."); sb.append(mWebJSInterface.onMessageName()); sb.append("('"); sb.append(json); sb.append("');"); getMainHandler().post(new LoadUrlRunnable(sb.toString())); } public WebView getWebView() { return mWebView; } @Override public IWebMessageManager getWebMessageManager() { return mWebMessageManager; } @Override public void setWebMessageManager(IWebMessageManager webMessageManager) { if (mWebMessageManager != null) { mWebMessageManager.clear(); } mWebMessageManager = webMessageManager; if (mWebMessageManager == null) { return; } mWebMessageManager.setWebFrame(this); } @Override public IWebJSInterface getWebJSInterface(IWebJSInterface webJSInterface) { return mWebJSInterface; } @Override public void setWebJSInterface(IWebJSInterface webJSInterface) { if (mWebJSInterface != null) { mWebJSInterface.setWebFrame(null); } mWebJSInterface = webJSInterface; if (mWebJSInterface == null) { return; } mWebJSInterface.setWebFrame(this); mWebView.addJavascriptInterface(mWebJSInterface, mWebJSInterface.name()); } @Override public boolean onInterceptBackPressed() { if (mWebView.canGoBack()) { mWebView.goBack(); return true; } return super.onInterceptBackPressed(); } class WebJSInterface implements IWebJSInterface { @Override public String name() { return "app"; } @Override @JavascriptInterface public void sendMessage(String json) { WebFrame.this.sendMessage(json); } @Override @JavascriptInterface public void postMessage(String json) { WebFrame.this.postMessage(json); } @Override public String onMessageName() { return "onMessage"; } @Override public IWebFrame getWebFrame() { return WebFrame.this; } @Override public void setWebFrame(IWebFrame webFrame) { } } class LoadUrlRunnable implements Runnable { protected String mUrl; public LoadUrlRunnable(String url) { mUrl = url; } @Override public void run() { try { mWebView.loadUrl(mUrl); } catch (Exception e) { // Exception } } } class DispatchMessageRunnable implements Runnable { protected String mMesssage; public DispatchMessageRunnable(String message) { mMesssage = message; } @Override public void run() { if (mWebMessageManager != null) { mWebMessageManager.dispatchMessage(mMesssage); } } } class OnWebActivityResultListener implements OnActivityResultListener { @Override public void onActivityResult(Context context, int requestCode, int resultCode, Intent data) { if (requestCode == mWebFrameChromeClient.getFileChooserRequestCode()) { if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ValueCallback<Uri[]> msgs = mWebFrameChromeClient.getUploadMessages(); if (msgs == null) { return; } Uri[] results = null; if (resultCode == Activity.RESULT_OK) { ClipData clipData = null; if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { clipData = data.getClipData(); } if (clipData != null) { int size = clipData.getItemCount(); results = new Uri[size]; for (int i = 0; i < size; i++) { ClipData.Item item = clipData.getItemAt(i); results[i] = item.getUri(); } } String dataString = data.getDataString(); if (dataString != null) { results = new Uri[]{Uri.parse(dataString)}; } } msgs.onReceiveValue(results); mWebFrameChromeClient.setUploadMessages(null); } else { ValueCallback<Uri> msg = mWebFrameChromeClient.getUploadMessage(); if (msg == null) { return; } Uri result = (data == null || resultCode != Activity.RESULT_OK) ? null : data.getData(); msg.onReceiveValue(result); mWebFrameChromeClient.setUploadMessage(null); } } } } }