import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; import android.net.http.SslError; import android.os.Build; import android.os.Looper; import android.os.SystemClock; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.webkit.GeolocationPermissions; import android.webkit.JsResult; import android.webkit.SslErrorHandler; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.TextView; //<--下面删掉重新生成--> import com.gc.app.common.log.LogUtil; import com.gc.app.common.util.FileUtil; import com.gc.app.common.util.NetWorkUtil; import com.gc.app.jsk.common.util.MyJsBridgeHandler; import com.gc.app.jsk.constant.JsBridgeConstant; import com.github.lzyzsd.jsbridge.BridgeHandler; import com.github.lzyzsd.jsbridge.BridgeUtil; import com.github.lzyzsd.jsbridge.BridgeWebView; import com.github.lzyzsd.jsbridge.CallBackFunction; import com.github.lzyzsd.jsbridge.DefaultHandler; import com.github.lzyzsd.jsbridge.Message; import com.github.lzyzsd.jsbridge.WebViewJavascriptBridge; import com.hy.app.client.R; //</--下面删掉重新生成--> import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 自定义 * 单纯的加载页面做缓存,不做js交互 * @author boli * created at 2016/3/22 16:00 */ public class MyWebView extends WebView implements WebViewJavascriptBridge { private ScreenInterface mt; /** 请求入口拦截:装载 url 时提供的额外参数、header: 2018-8-27 */ private WebResourceRequestListener mRequestListener; /** 重定向监听: shouldOverrideUrlLoading */ private WebViewOtherInterface mInterfaceOther; private LoadErroInterface mLoadErrorInterface; private WebViewFinishInterface mFinishInterface; private OnOpenFileChooserListerner openFileChooserListerner; private OnOpenFileChooserForAndroid5Listerner onOpenFileChooserForAndroid5Listerner; private Activity context; private ProgressBar progressBar; private View failView; private TextView tvFail; private boolean needOverrind; private boolean showFailView;//设置是否显示加载错误页面 private boolean isLoadSuccess;//是否加载成功 private boolean needFinishListener; /** 静态文件 */ private String[] staticFiles = null; /** jsbridge相关 ***/ private final String TAG = "BridgeWebView"; public static final String toLoadJs = "WebViewJavascriptBridge.js"; Map<String, CallBackFunction> responseCallbacks = new HashMap<String, CallBackFunction>(); Map<String, BridgeHandler> messageHandlers = new HashMap<String, BridgeHandler>(); BridgeHandler defaultHandler = new DefaultHandler(); private List<Message> startupMessage = new ArrayList<Message>(); public List<Message> getStartupMessage() { return startupMessage; } public void setStartupMessage(List<Message> startupMessage) { this.startupMessage = startupMessage; } private long uniqueId = 0; final static String CALLBACK_ID_FORMAT = "JAVA_CB_%s"; final static String UNDERLINE_STR = "_"; final static String JS_HANDLE_MESSAGE_FROM_JAVA = "javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');"; final static String JS_FETCH_QUEUE_FROM_JAVA = "javascript:WebViewJavascriptBridge._fetchQueue();"; final static String YY_OVERRIDE_SCHEMA = "yy://"; final static String YY_RETURN_DATA = YY_OVERRIDE_SCHEMA + "return/";//格式为 yy://return/{function}/returncontent //主要用于自定义历史栈 private List<String> urlList = new ArrayList<>(); private String curUrl; public MyWebView(Context context) { super(context); init(context); } public MyWebView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public MyWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context){ this.context = (Activity)context; initProgressBar(context); initWebView(context); initfailView(context); registerHandler(context); } public void setDefaultHandler(BridgeHandler handler) { this.defaultHandler = handler; } //加载进度条 private void initProgressBar(Context context) { progressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal); progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 8, 0, 0)); Drawable drawable = context.getResources().getDrawable(R.drawable.progressbar_drawable); progressBar.setProgressDrawable(drawable); addView(progressBar); } //加载WebView private void initWebView(Context context){ WebSettings webseting = this.getSettings(); webseting.setJavaScriptEnabled(true); webseting.setAllowFileAccess(true); webseting.setGeolocationEnabled(true);//启用地理定位 webseting.setDomStorageEnabled(true);//h5缓存机制->Dom Storage 存储机制 适合存储比较简单的数据 webseting.setDatabaseEnabled(true);//h5缓存机制->web SQLite Database存储机制 webseting.setAppCacheEnabled(true);// //适配h5页 webseting.setUseWideViewPort(true); webseting.setTextZoom(100); webseting.setLoadWithOverviewMode(true); webseting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); webseting.setDefaultTextEncodingName("utf-8"); if(NetWorkUtil.isNetworkAvailable(context)){ webseting.setCacheMode(WebSettings.LOAD_DEFAULT); //有网络从网络上取 }else{ webseting.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //无网络,有缓存取缓存 } String cachePath = FileUtil.getWebViewCacheDir(context).getPath(); webseting.setDatabasePath(cachePath); webseting.setAppCachePath(cachePath); webseting.setAppCacheMaxSize(1024*1024*20); setWebChromeClient(new MyWebChromeClient()); setWebViewClient(new MyWebViewClient(this)); String userAgent = webseting.getUserAgentString(); Log.i("WebView:","initWebView(): userAgent = " + userAgent); int versionCode = 0; try { versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); versionCode = 0; } String newUserAgent = new StringBuilder().append("app/jsk365/android/").append(versionCode).append(";").append(userAgent).toString(); webseting.setUserAgentString(newUserAgent); LogUtil.i("WebView:","initWebView(): newUserAgent = " + newUserAgent); // 静态文件头 staticFiles = context.getString(R.string.web_staticFile).split("[,]"); //Log.d("+++++++tou1",staticFiles.toString()); /*注意 下面这行是strings.xml文件里的,这样它staticFiles = context.getString(R.string.web_staticFile).split("[,]");就不会报错了 <string name="web_staticFile">.css,.js,.png,.jpg,.gif,.jpeg,.bmp,.ico,.swf,.psd,.htc,.htm,.html,.crx,.xpi,.exe,.ipa,.apk</string> <!-- 系统配置参数 --> */ } //加载错误显示页面 private void initfailView(Context context){ failView = LayoutInflater.from(context).inflate(R.layout.umeng_socialize_failed_load_page,null); failView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 0, 0)); addView(failView, 0); failView.setVisibility(GONE); tvFail = (TextView)failView.findViewById(R.id.tv_fail_webview); tvFail.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showFailView = false; failView.setVisibility(GONE); mLoadErrorInterface.onClickReload(); } }); } /** 是否自定义拦截、处理超链接? */ public void setShouldOverrideUrl(boolean needOverrind){ this.needOverrind = needOverrind; } // 自动添加头部 @Override public void loadUrl(String url, Map<String, String> additionalHttpHeaders) { if (mRequestListener != null) { Map<String, String> headers = mRequestListener.getHeaders(); if (headers != null && headers.size() > 0 && headers != additionalHttpHeaders) { if (additionalHttpHeaders == null) additionalHttpHeaders = new HashMap<>(); //Log.d("+++++++tou2",additionalHttpHeaders.toString()); additionalHttpHeaders.putAll(headers); } } super.loadUrl(url, additionalHttpHeaders); } // 自动添加头部 @Override public void loadUrl(String url) { if (mRequestListener != null && url.startsWith("http")) { Map<String, String> headers = mRequestListener.getHeaders(); if (headers != null && headers.size() > 0) { headers = new HashMap<>(headers); super.loadUrl(url, headers); return; } } //Log.d("+++++++tou3",url); super.loadUrl(url); } /** 判断请求是否静态资源文件? */ public boolean isStaticFiles(String url) { int pos = url.indexOf('?'); if (pos > 0) url = url.substring(0, pos); if (url.equals(".jsp")) return false; for (String suffix : staticFiles) { if (url.endsWith(suffix)) return true; } return false; } public class MyWebViewClient extends WebViewClient { private MyWebView webView; public MyWebViewClient(MyWebView webView){ this.webView = webView; } @TargetApi(21) // Android 5.0 @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { LogUtil.i("WebView", "shouldInterceptRequest request: " + request); return shouldInterceptRequest(view, request.getUrl().toString()); } // 老版本:低于 21 - Android 5.0 @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { LogUtil.i("WebView","shouldInterceptRequest: " + url); if (mRequestListener != null) { // 登录、注销 if (mRequestListener.shouldOverrideUrlLoading(view, url)) return null; // 已另行处理、并转向? return mRequestListener.shouldInterceptRequest(view, url); } return super.shouldInterceptRequest(view, url); } @TargetApi(21) // Android 5.0 @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if (Build.VERSION.SDK_INT >= 24) return shouldOverrideUrlLoading24(view, request); LogUtil.i("WebView","shouldOverrideUrlLoading request: " + request); //return super.shouldOverrideUrlLoading(view, request); return shouldOverrideUrlLoading(view, request.getUrl().toString()); } @TargetApi(24) // Android 7.0 public boolean shouldOverrideUrlLoading24(WebView view, WebResourceRequest request) { LogUtil.i("WebView","shouldOverrideUrlLoading24 request: " + request.getUrl().getPath() + ", " + request); if (request.isRedirect()) return false; // return super.shouldOverrideUrlLoading(view, request); return shouldOverrideUrlLoading(view, request.getUrl().toString()); } // 兼容 Android 4 及以下版本 @Override public boolean shouldOverrideUrlLoading(WebView webView, String url) { LogUtil.i("WebView","shouldOverrideUrlLoading: " + url); if(url.contains("javacript:void(0)")){ return true; } curUrl = url; urlList.add(url); String decodeUrl = ""; try { decodeUrl = URLDecoder.decode(url, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } if (decodeUrl.startsWith(YY_RETURN_DATA)) { // 如果是返回数据 handlerReturnData(decodeUrl); } else if (decodeUrl.startsWith(YY_OVERRIDE_SCHEMA)) { // flushMessageQueue(); } else { // 判断 是否登录/注销页面、且拦截之? if (mRequestListener != null && mRequestListener.shouldOverrideUrlLoading(webView, url)) { return true; } if(needOverrind && mInterfaceOther != null) { return mInterfaceOther.shouldOverrideUrlLoading(webView, url); } else { if (mRequestListener != null) { String newUrl = mRequestListener.getUrl(url); if (!newUrl.equals(url)) { webView.stopLoading(); webView.loadUrl(newUrl, mRequestListener.getHeaders()); Log.i(TAG, "跳转的url:" + newUrl); return true; } } //webView.loadUrl(url); return super.shouldOverrideUrlLoading(webView, url); // 由浏览器自动处理 2018-8-28 } } return true; } public void onLoadResource(WebView view, String url) { LogUtil.i("WebView","onLoadResource: " + url); super.onLoadResource(view, url); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { LogUtil.i("WebView","onPageStarted: " + url); super.onPageStarted(view, url, favicon); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); LogUtil.i("WebView","onPageFinished: " + url); if (BridgeWebView.toLoadJs != null) { BridgeUtil.webViewLoadLocalJs(view, BridgeWebView.toLoadJs); } if (webView.getStartupMessage() != null) { for (Message m : webView.getStartupMessage()) { webView.dispatchMessage(m); } webView.setStartupMessage(null); } if(needFinishListener){ mFinishInterface.onPageFinished(view); } if(showFailView){ failView.setVisibility(VISIBLE); tvFail.setVisibility(VISIBLE); }else{ failView.setVisibility(GONE); tvFail.setVisibility(GONE); } } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); LogUtil.e("WebView","onReceivedError"); showFailView = true; } @Override public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) { LogUtil.e("WebView","onReceivedSslError"); super.onReceivedSslError(view, handler, error); //handler.proceed(); // 忽略该证书错误 } } public class MyWebChromeClient extends WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress == 100) { progressBar.setVisibility(GONE); } else { if (progressBar.getVisibility() == GONE) progressBar.setVisibility(VISIBLE); progressBar.setProgress(newProgress); } super.onProgressChanged(view, newProgress); } @Override public void onShowCustomView(View view, CustomViewCallback callback) { mt.fullScreen(view, callback); } @Override public void onHideCustomView() { mt.exitFullScreen(); } @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); } @Override public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { return super.onJsConfirm(view, url, message, result); } @Override public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false); super.onGeolocationPermissionsShowPrompt(origin, callback); } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); } @Override public void onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater) { quotaUpdater.updateQuota(requiredStorage*2); } //扩展浏览器上传文件 //3.0++版本 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { openFileChooserListerner.openFileChooserImpl(uploadMsg); } //3.0--版本 public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooserListerner.openFileChooserImpl(uploadMsg); } public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileChooserListerner.openFileChooserImpl(uploadMsg); } // For Android > 5.0 public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> uploadMsg, FileChooserParams fileChooserParams) { onOpenFileChooserForAndroid5Listerner.openFileChooserImplForAndroid5(uploadMsg); return true; } } public void setWebViewListener(ScreenInterface t) { this.mt = t; } public void setWebResourceRequestListener(WebResourceRequestListener listener) { this.mRequestListener = listener; } public void setOtherListener(WebViewOtherInterface ontherInterface) { this.mInterfaceOther = ontherInterface; } public void setFailReloadListener(LoadErroInterface loadErrorInterface){ this.mLoadErrorInterface = loadErrorInterface; } public void setNeedFinishListener(boolean needFinishListener){ this.needFinishListener = needFinishListener; } public void setOnPageFinishedListener(WebViewFinishInterface finishInterface) { this.mFinishInterface = finishInterface; } public void setOnOpenFileChooserListerner(OnOpenFileChooserListerner listerner){ this.openFileChooserListerner = listerner; } public void setOnOpenFileChooserForAndroid5Listerner(OnOpenFileChooserForAndroid5Listerner listerner){ this.onOpenFileChooserForAndroid5Listerner = listerner; } //全屏监听 public interface ScreenInterface { void fullScreen(View view, WebChromeClient.CustomViewCallback callback); void exitFullScreen(); } //设置重定向监听 public interface WebViewOtherInterface { /** * 重定向监听 * @param view * @param url * @return 是否已处理完成? true-由本监听器处理完成,webView 中断本次处理; false-由 webView 继续处理,即装载 url、通知各监听器... */ boolean shouldOverrideUrlLoading(WebView view, String url); } //加载错误点击TextView重新加载监听 public interface LoadErroInterface{ void onClickReload(); } //设置标题 public interface WebViewFinishInterface { void onPageFinished(WebView view); } //webView调取android本地图片 public interface OnOpenFileChooserListerner{ void openFileChooserImpl(ValueCallback<Uri> uploadMsg); } //webView调取android本地图片(版本大于5.0) public interface OnOpenFileChooserForAndroid5Listerner{ void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg); } // 请求入口拦截:装载 url 时提供的额外参数、header;监听登录、注销请求: 2018-8-27 public interface WebResourceRequestListener { /** * 返回额外的请求参数 * @param url 准备装载的 url * @return 返回实际装载的 url */ public String getUrl(String url); /** * 返回额外的头部 header 参数 * @return */ public Map<String, String> getHeaders(); /** 是否登录请求 url? */ public boolean isLoginRequest(String url); /** 是否注销请求 url? */ public boolean isLogoutRequest(String url); /** 装载之前的预拦截:是否为登录、或注销请求、或其它需拦截转向的请求? 如果是,则拦截之、并返回 true * <p>与 shouldInterceptRequest 配合拦截 * @param view * @param url * @return 是否已拦截、并处理完成;true-已处理完成;false-由 webview 继续后续处理 */ public boolean shouldOverrideUrlLoading(WebView view, String url); /** * 拦截请求 * @param view * @param url * @return 返回处理结果。如果不做任何处理,可简单返回 null; 如果自定义处理,可调用 view.stopLoading() */ public WebResourceResponse shouldInterceptRequest(WebView view, String url); } /********************************** 一下是jsbridge的方法 ******************************************************************************/ private void registerHandler(Context context){ /** 获取数据 */ this.registerHandler(JsBridgeConstant.GETDATA_METHOD,new MyJsBridgeHandler(context,JsBridgeConstant.GETDATA_METHOD)); /** 跳转界面 */ this.registerHandler(JsBridgeConstant.GOTO_METHOD,new MyJsBridgeHandler(context,JsBridgeConstant.GOTO_METHOD)); /** doAction */ this.registerHandler(JsBridgeConstant.DOACTION_METHOD,new MyJsBridgeHandler(context,JsBridgeConstant.DOACTION_METHOD)); } void handlerReturnData(String url) { String functionName = BridgeUtil.getFunctionFromReturnUrl(url); CallBackFunction f = responseCallbacks.get(functionName); String data = BridgeUtil.getDataFromReturnUrl(url); if (f != null) { f.onCallBack(data); responseCallbacks.remove(functionName); return; } } @Override public void send(String data) { send(data, null); } @Override public void send(String data, CallBackFunction responseCallback) { doSend(null, data, responseCallback); } private void doSend(String handlerName, String data, CallBackFunction responseCallback) { Message m = new Message(); if (!TextUtils.isEmpty(data)) { m.setData(data); } if (responseCallback != null) { String callbackStr = String.format(CALLBACK_ID_FORMAT, ++uniqueId + (UNDERLINE_STR + SystemClock.currentThreadTimeMillis())); responseCallbacks.put(callbackStr, responseCallback); m.setCallbackId(callbackStr); } if (!TextUtils.isEmpty(handlerName)) { m.setHandlerName(handlerName); } queueMessage(m); } private void queueMessage(Message m) { if (startupMessage != null) { startupMessage.add(m); } else { dispatchMessage(m); } } void dispatchMessage(Message m) { String messageJson = m.toJson(); //escape special characters for json string messageJson = messageJson.replaceAll("(\\\\)([^utrn])", "\\\\\\\\$1$2"); messageJson = messageJson.replaceAll("(?<=[^\\\\])(\")", "\\\\\""); String javascriptCommand = String.format(JS_HANDLE_MESSAGE_FROM_JAVA, messageJson); if (Thread.currentThread() == Looper.getMainLooper().getThread()) { this.loadUrl(javascriptCommand); } } void flushMessageQueue() { if (Thread.currentThread() == Looper.getMainLooper().getThread()) { loadUrl(JS_FETCH_QUEUE_FROM_JAVA, new CallBackFunction() { @Override public void onCallBack(String data) { // deserializeMessage List<Message> list = null; try { list = Message.toArrayList(data); } catch (Exception e) { e.printStackTrace(); return; } if (list == null || list.size() == 0) { return; } for (int i = 0; i < list.size(); i++) { Message m = list.get(i); String responseId = m.getResponseId(); // 是否是response if (!TextUtils.isEmpty(responseId)) { CallBackFunction function = responseCallbacks.get(responseId); String responseData = m.getResponseData(); function.onCallBack(responseData); responseCallbacks.remove(responseId); } else { CallBackFunction responseFunction = null; // if had callbackId final String callbackId = m.getCallbackId(); if (!TextUtils.isEmpty(callbackId)) { responseFunction = new CallBackFunction() { @Override public void onCallBack(String data) { Message responseMsg = new Message(); responseMsg.setResponseId(callbackId); responseMsg.setResponseData(data); queueMessage(responseMsg); } }; } else { responseFunction = new CallBackFunction() { @Override public void onCallBack(String data) { // do nothing } }; } BridgeHandler handler; if (!TextUtils.isEmpty(m.getHandlerName())) { handler = messageHandlers.get(m.getHandlerName()); } else { handler = defaultHandler; } if (handler != null){ handler.handler(m.getData(), responseFunction); } } } } }); } } public void loadUrl(String jsUrl, CallBackFunction returnCallback) { this.loadUrl(jsUrl); responseCallbacks.put(BridgeUtil.parseFunctionName(jsUrl), returnCallback); } /** * register handler,so that javascript can call it * * @param handlerName * @param handler */ public void registerHandler(String handlerName, BridgeHandler handler) { if (handler != null) { messageHandlers.put(handlerName, handler); } } /** * 设置是否加载成功 * @param flag */ public void setLoadSuccess(boolean flag){ this.isLoadSuccess = flag; } /** * call javascript registered handler * * @param handlerName * @param data * @param callBack */ public void callHandler(String handlerName, String data, CallBackFunction callBack) { doSend(handlerName, data, callBack); } @Override public void goBack() { super.goBack(); //自定义的webView回退栈 暂时先屏蔽 // if(urlList.size() > 0 ){ // int hasLoadPosition = -1; // //先判断当前的url在list中是否存在过 // for(int i=0;i<urlList.size();i++){ // String url = urlList.get(i); // if(curUrl.equals(url)){ // //证明当前的url已被加载过 // hasLoadPosition = i; // urlList = urlList.subList(0,hasLoadPosition + 1); // break; // } // } // // //当前list的长度 // int length = urlList.size(); // //上一个url的下标 // int lastStep = length - 2; // if(lastStep < 0){ // //证明当前是第一个url界面,不能再后退,结束activity。 // context.finish(); // return; // } // //上一个界面的url // String lastUrl = urlList.get(lastStep); // if(urlList.contains(curUrl)){ // urlList.remove(curUrl); // } // curUrl = lastUrl; // loadUrl(lastUrl); // } } }
import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Parcelable; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.gc.app.jsk.common.baseapp.BaseActivity; import com.gc.app.jsk.common.customview.MyWebView; import com.gc.app.jsk.common.util.LoginUtil; import com.google.gson.Gson; import com.hy.app.doctor.R; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Locale; import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class NewWebViewActivity extends BaseActivity { private int REQUEST_CODE = 1234; private ValueCallback<Uri[]> mUploadCallbackAboveL; private ValueCallback<Uri> mUploadCallbackBelow; private Uri imageUri; private ImageView mBtnBack; private TextView mTextTitle; private Button mBtnRight; private List<String> list=new ArrayList<>(); private String url; private MyWebView web_xieyi; //private WebView web_xieyi; @Override protected void initWidget() { setContentView(R.layout.activity_new_web_view); initView(); } @SuppressLint("SetJavaScriptEnabled") @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void initView() { mBtnBack = (ImageView) findViewById(R.id.btn_back); mTextTitle = (TextView) findViewById(R.id.text_title); mBtnRight = (Button) findViewById(R.id.btn_right); web_xieyi = findViewById(R.id.web_xieyi); url = getIntent().getStringExtra("url"); String nametile = getIntent().getStringExtra("nametile"); //mTextTitle.setText(nametile); //web_xieyi.addJavascriptInterface(this, "AndroidFunction");//AndroidtoJS类对象映射到js的test对象 //web_xieyi.addJavascriptInterface(this,"AndroidFunction"); /*WebSettings webseting = web_xieyi.getSettings(); webseting.setJavaScriptEnabled(true); webseting.setJavaScriptCanOpenWindowsAutomatically(true); webseting.setAllowFileAccess(true); webseting.setGeolocationEnabled(true);//启用地理定位 webseting.setDomStorageEnabled(true);//h5缓存机制->Dom Storage 存储机制 适合存储比较简单的数据 webseting.setDatabaseEnabled(true);//h5缓存机制->web SQLite Database存储机制 webseting.setAppCacheEnabled(true);// //适配h5页 webseting.setUseWideViewPort(true); webseting.setTextZoom(100); webseting.setLoadWithOverviewMode(true); webseting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); webseting.setDefaultTextEncodingName("utf-8");*/ web_xieyi.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //只有跳转才会触发这个方法 System.out.println("跳转Sort1:" + url); list.add(url); view.loadUrl(url); // 在本WebView打开新的url请求 return true; // 标记新请求已经被处理笑话 // 上边2行合起来,标识所有新链接都在本页面处理,不跳转别的浏览器 } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } @Override public void onLoadResource(WebView view, String url) { //获取h5的标题 一上来就会走这个方法 //System.out.println("跳转Sort2:" + url); String title = view.getTitle(); //Log.d("+++++++++title", title); if(!TextUtils.isEmpty(title)){ setTitle(title.contains("/") ? "省直三院" : title); } } }); web_xieyi.setWebChromeClient(new WebChromeClient() { /** * 8(Android 2.2) <= API <= 10(Android 2.3)回调此方法 */ public void openFileChooser(ValueCallback<Uri> uploadMsg) { Log.e("WangJ", "运行方法 openFileChooser-1"); // (2)该方法回调时说明版本API < 21,此时将结果赋值给 mUploadCallbackBelow,使之 != null mUploadCallbackBelow = uploadMsg; takePhoto(); } /** * 11(Android 3.0) <= API <= 15(Android 4.0.3)回调此方法 */ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { Log.e("WangJ", "运行方法 openFileChooser-2 (acceptType: " + acceptType + ")"); // 这里我们就不区分input的参数了,直接用拍照 openFileChooser(uploadMsg); } /** * 16(Android 4.1.2) <= API <= 20(Android 4.4W.2)回调此方法 */ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { Log.e("WangJ", "运行方法 openFileChooser-3 (acceptType: " + acceptType + "; capture: " + capture + ")"); // 这里我们就不区分input的参数了,直接用拍照 openFileChooser(uploadMsg); } /** * API >= 21(Android 5.0.1)回调此方法 */ @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { Log.e("WangJ", "运行方法 onShowFileChooser"); // (1)该方法回调时说明版本API >= 21,此时将结果赋值给 mUploadCallbackAboveL,使之 != null mUploadCallbackAboveL = filePathCallback; takePhoto(); return true; } }); web_xieyi.loadUrl(url); mBtnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (list.size()>=2){ web_xieyi.loadUrl(list.get(list.size()-2)); list.remove(list.get(list.size()-1)); }else { if (list.size()<=0){ finish(); return; } list.remove(list.get(list.size()-1)); } } }); } /** * 设置标题 * * @param title 标题文本 */ public void setTitle(String title) { mTextTitle.setText(title); } /** * 事件回调: 页面装载完成 * @param view */ protected void onHomePageFinished(WebView view) { } @Override protected void initData() { } @Override protected void registerListener() { } /*交互 @JavascriptInterface public void gotoPage() { } */ /** * 调用相机 */ private void takePhoto() { // 指定拍照存储位置的方式调起相机 String filePath = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES + File.separator; String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg"; imageUri = Uri.fromFile(new File(filePath + fileName)); Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); Intent Photo = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); Intent chooserIntent = Intent.createChooser(Photo, "Image Chooser"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent}); startActivityForResult(chooserIntent, REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE) { // 经过上边(1)、(2)两个赋值操作,此处即可根据其值是否为空来决定采用哪种处理方法 if (mUploadCallbackBelow != null) { chooseBelow(resultCode, data); } else if (mUploadCallbackAboveL != null) { chooseAbove(resultCode, data); } else { Toast.makeText(this, "发生错误", Toast.LENGTH_SHORT).show(); } } } /** * Android API < 21(Android 5.0)版本的回调处理 * @param resultCode 选取文件或拍照的返回码 * @param data 选取文件或拍照的返回结果 */ private void chooseBelow(int resultCode, Intent data) { Log.e("WangJ", "返回调用方法--chooseBelow"); if (RESULT_OK == resultCode) { updatePhotos(); if (data != null) { // 这里是针对文件路径处理 Uri uri = data.getData(); if (uri != null) { Log.e("WangJ", "系统返回URI:" + uri.toString()); mUploadCallbackBelow.onReceiveValue(uri); } else { mUploadCallbackBelow.onReceiveValue(null); } } else { // 以指定图像存储路径的方式调起相机,成功后返回data为空 Log.e("WangJ", "自定义结果:" + imageUri.toString()); mUploadCallbackBelow.onReceiveValue(imageUri); } } else { mUploadCallbackBelow.onReceiveValue(null); } mUploadCallbackBelow = null; } /** * Android API >= 21(Android 5.0) 版本的回调处理 * @param resultCode 选取文件或拍照的返回码 * @param data 选取文件或拍照的返回结果 */ private void chooseAbove(int resultCode, Intent data) { Log.e("WangJ", "返回调用方法--chooseAbove"); if (RESULT_OK == resultCode) { updatePhotos(); if (data != null) { // 这里是针对从文件中选图片的处理 Uri[] results; Uri uriData = data.getData(); if (uriData != null) { results = new Uri[]{uriData}; for (Uri uri : results) { Log.e("WangJ", "系统返回URI:" + uri.toString()); } mUploadCallbackAboveL.onReceiveValue(results); } else { mUploadCallbackAboveL.onReceiveValue(null); } } else { Log.e("WangJ", "自定义结果:" + imageUri.toString()); mUploadCallbackAboveL.onReceiveValue(new Uri[]{imageUri}); } } else { mUploadCallbackAboveL.onReceiveValue(null); } mUploadCallbackAboveL = null; } private void updatePhotos() { // 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(imageUri); sendBroadcast(intent); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".NewWebViewActivity"> <include layout="@layout/new_title_include" /> <com.gc.app.jsk.common.customview.MyWebView android:id="@+id/web_xieyi" android:layout_width="match_parent" android:layout_height="match_parent"> </com.gc.app.jsk.common.customview.MyWebView> </LinearLayout>
new_title_include.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="@dimen/dp_70" android:background="@color/bg_blue"> <ImageView android:id="@+id/btn_back" android:layout_width="@dimen/dp_40" android:layout_height="match_parent" android:paddingLeft="@dimen/dp_10" android:paddingRight="@dimen/dp_10" android:paddingTop="@dimen/dp_20" android:scaleType="center" android:src="@drawable/arrow_left" /> <!--android:src="@drawable/arrow_back_green"--> <!-- 标题 --> <TextView android:id="@id/text_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerHorizontal="true" android:gravity="center" android:paddingTop="@dimen/dp_20" android:textSize="@dimen/sp_18" android:textColor="@color/white" android:text=""/> </RelativeLayout>