自定义webview与h5交互调起本地相册

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>

 

 

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页