Android 中 WebView 交互

一、前言:

在 Android 中我们要给 js 传递参数;js 也会给我们传递参数;有时候也要拿到 js 的点击事件,来完成 app 本地操作。

WebView 常见的坑: 点击查看:

1. Activity中的使用:

public class MyAgreementDetailsActivity extends BaseDaggerActivity<MyAgreementDetailsPresenter> implements MyAgreementDetailsContract.View {


    @Inject
    MyAgreementDetailsPresenter myAgreementPresenter;
    @BindView(R.id.iv_main_back)
    ImageView ivMainBack;
    @BindView(R.id.tv_main_title)
    TextView tvMainTitle;
    @BindView(R.id.iv_main_clock)
    ImageView ivMainClock;
    @BindView(R.id.rl_title)
    RelativeLayout rlTitle;
    @BindView(R.id.progressBar1)
    ProgressBar progressBar1;
    @BindView(R.id.webview)
    CustWebView webview;


    private String agreementName;
    private String agreementId;
    private String url;
    private int nper;
    private int agrType;
    private int isChange;
    private String token;
    private boolean isFirst = false;


    public static void launch(Context context, String agreement_id, String agreement_name, int nper, String url, int agr_type, int is_change) {

        Intent intent = new Intent(context, MyAgreementDetailsActivity.class);
        intent.putExtra("agreementName", agreement_name);
        intent.putExtra("agreementId", agreement_id);
        intent.putExtra("url", url);
        intent.putExtra("nper", nper);
        intent.putExtra("agrType", agr_type);
        intent.putExtra("isChange", is_change);

        context.startActivity(intent);
    }

    @Override
    public MyAgreementDetailsPresenter createPresent() {
        return myAgreementPresenter;
    }


    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_agreement_view);
        ButterKnife.bind(this);
        initEvent();
        initData();
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @SuppressLint("JavascriptInterface")
    private void initData() {
        token = SPUtils.getInstance(SPConstant.TOKEN).getString(SPConstant.TOKEN);
        agreementName = getIntent().getStringExtra("agreementName");
        //协议id
        agreementId = getIntent().getStringExtra("agreementId");
        //期数
        nper = getIntent().getIntExtra("nper", 0);
        //跳转链接
        url = getIntent().getStringExtra("url");

        agrType = getIntent().getIntExtra("agrType", 0);

        isChange = getIntent().getIntExtra("isChange", 0);

        tvMainTitle.setText(agreementName);

        final WebSettings webSettings = webview.getSettings();
        //启用JS
        webSettings.setJavaScriptEnabled(true);

        //设置是否支持变焦
        webSettings.setSupportZoom(true);
        //缩放
        webSettings.setBuiltInZoomControls(true);
        webSettings.setDisplayZoomControls(false);
        //多窗口
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setSupportMultipleWindows(true);
        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        webSettings.setDefaultFontSize(18);

        webSettings.setAllowFileAccess(true);
        webSettings.setAllowFileAccessFromFileURLs(true);

        //启用缓存
        webSettings.setAppCacheEnabled(true);
        webSettings.setAllowFileAccess(true);
        //
        webSettings.setDomStorageEnabled(true);
        //设置缓存模式
        webSettings.setBlockNetworkImage(false);
        //解决图片不显示
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }


        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setUseWideViewPort(true);
        webSettings.setLoadWithOverviewMode(true);

 try {
            if (Build.VERSION.SDK_INT >= 16) {
                Class<?> clazz = webview.getSettings().getClass();
                Method method = clazz.getMethod(
                        "setAllowUniversalAccessFromFileURLs", boolean.class);//利用反射机制去修改设置对象
                if (method != null) {
                    method.invoke(webview.getSettings(), true);//修改设置
                }
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }


        webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                // TODO 自动生成的方法存根
                if (newProgress == 100) {
                    progressBar1.setVisibility(View.GONE);//加载完网页进度条消失
                } else {
                    progressBar1.setVisibility(View.VISIBLE);//开始加载网页时显示进度条
                    progressBar1.setProgress(newProgress);//设置进度值
                }


            }
        });


        webview.loadUrl(url);

        //在js中调用本地java方法  callAndroid
        webview.addJavascriptInterface(new JsInterface(this), "click");

        //允许调试
        if (BuildConfig.DEBUG){
            WebView.setWebContentsDebuggingEnabled(true);
        }else {
            WebView.setWebContentsDebuggingEnabled(false);
        }


        /**
         * webView 加载的时候  会跳到手机自带的浏览器
         * 给自己定义个webview添加客户端
         */
        webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                // webview.loadUrl("javascript:loadingDate('  " + mLoginSMSBean.getToken() + " ' ,'" + mAgreementBean.getAgreement_id() + "' ,'" + "2" + "','" + mAgreementBean.getAgr_type() + "','" + mAgreementBean.getNper() + "'  ,'" + mAgreementBean.getIs_change() + "'     )");

                if (!isFirst) {
                    isFirst = true;
                    webview.loadUrl("javascript:loadingDate('" + token + "','" + agreementId + "','" + "2" + "','" + agrType + "','" + nper + "','" + isChange + "' )");

                   // LogUtils.d("LUO", "===" + token);
                }

            }

        });

        webview.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    //按返回键操作并且能回退网页
                    if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
                        //后退
                        webview.goBack();
                        return true;
                    }
                }
                return false;
            }
        });
    }

    private void initEvent() {
        //返回
        ivMainBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });


    }


    @Override
    public void onError(String error) {
        ToastUtils.showShort(error);
    }


    @Override
    public void AgreementDetailsSuccess(BaseHttpResponse<ResponseEmptyDataBean> data) {

        ToastUtils.showShort("协议签署成功");

        finish();

    }


    /**
     * 2.编写一个提供给Web的Js接口类
     */


    public class JsInterface {
        private Context mContext;

        public JsInterface(Context context) {
            this.mContext = context;
        }

        //在js中调用window.AndroidWebView.showInfoFromJs(name),便会触发此方法。
        @JavascriptInterface
        public void clickAction(String json, String flag) {

            if(!TextUtils.isEmpty(json)){
                JsBean jsBean = JSON.parseObject(json, JsBean.class);
                submitData(jsBean);
            }
//            LogUtils.d("LUO", json + "==========" + flag);
//            ToastUtils.showShort("点击了按钮");


        }
    }

    private void submitData(JsBean jsBean) {

        HashMap map = new HashMap();
        map.put("agreement_id",agreementId);// 协议id
        map.put("nickname",jsBean.getNickname());//用户姓名
        map.put("id_card_no",jsBean.getId_card_no());//身份证号

        map.put("mobile",jsBean.getMobile());//  联系方式
        map.put("province",jsBean.getProvince());//  省
        map.put("city",jsBean.getCity());// 市
        map.put("country",jsBean.getCountry());// 县
        map.put("address",jsBean.getAddress());//详细地址
        map.put("email",jsBean.getEmail());//邮箱地址
        map.put("title",jsBean.getTitle());// 协议标题
        map.put("signed",jsBean.getSigned());
        map.put("signed_time",jsBean.getSigned_time());//签署时间
//        map.put("front_id_card",);//身份证正面照链接
//        map.put("back_id_card",);//身份证反面照链接
        map.put("agr_type",String.valueOf(agrType));//协议类型 1:普通协议 2:隐私协议
        map.put("nper",String.valueOf(nper));//期数
        map.put("nper_upper",jsBean.getNper_upper());//大写期数

        //本地网络请求
        myAgreementPresenter.getAgreementDetails(map);
    }
}

2. activity_agreement_view.xml 布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    android:background="@color/color_FFFFFF"
   >


   <include layout="@layout/layout_title_bar"/>


    <ProgressBar
        android:id="@+id/progressBar1"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_2"
        android:progressDrawable="@color/color_FFF96857"
        android:visibility="gone"

        />

    <com.sumansoul.teacher.widget.custom.CustWebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </com.sumansoul.teacher.widget.custom.CustWebView>
</LinearLayout>

3. 自定义CustWebView:

public class CustWebView extends WebView {
    private OnTouchScreenListener onTouchScreenListener;

    public CustWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    public CustWebView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public CustWebView(Context context) {
        super(context);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (onTouchScreenListener != null)
                onTouchScreenListener.onTouchScreen();
        }
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (onTouchScreenListener != null) {
                onTouchScreenListener.onReleaseScreen();
            }
        }

        return super.onTouchEvent(event);
    }

    public interface OnTouchScreenListener {
        void onTouchScreen();

        void onReleaseScreen();
    }

    public void setOnTouchScreenListener(OnTouchScreenListener onTouchScreenListener) {
        this.onTouchScreenListener = onTouchScreenListener;
    }
}

二、总结:

1. 设置WebView属性,能够执行Javascript脚本

mWebView.getSettings().setJavaScriptEnabled(true);//设置js可用

2. 设置加载进度条

 webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                // TODO 自动生成的方法存根
                if (newProgress == 100) {
                    progressBar1.setVisibility(View.GONE);//加载完网页进度条消失
                } else {
                    progressBar1.setVisibility(View.VISIBLE);//开始加载网页时显示进度条
                    progressBar1.setProgress(newProgress);//设置进度值
                }


            }
        });

3. 浏览器内部跳转:

  /**
         * webView 加载的时候  会跳到手机自带的浏览器
         * 给自己定义个webview添加客户端
         */
        webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
             
          

            }

        });

4. webview 显示点击返回键:

webview.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    //按返回键操作并且能回退网页
                    if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
                        //后退
                        webview.goBack();
                        return true;
                    }
                }
                return false;
            }
        });

5. webview 是否允许调试:

 //允许调试
        if (BuildConfig.DEBUG){
            WebView.setWebContentsDebuggingEnabled(true);
        }else {
            WebView.setWebContentsDebuggingEnabled(false);
        }

6. 接受 JS 给 Android 传递参数:

在js中调用本地java方法
webview.addJavascriptInterface(new JsInterface(this), "click");

  /**
     * 2.编写一个提供给Web的Js接口类
     */

    public class JsInterface {
        private Context mContext;

        public JsInterface(Context context) {
            this.mContext = context;
        }

      // @JavascriptInterface一定要写
        @JavascriptInterface
        public void clickAction(String json, String flag) {
            LogUtils.d("LUO", json + "==========" + flag);
            ToastUtils.showShort("点击了按钮");

        }
    }

7. Android 给 JS 传递参数

mWebView.loadUrl("javascript:javaCall('fasff')");

页面加载完成后,给 JS 传递参数:

        /**
         * webView 加载的时候  会跳到手机自带的浏览器
         * 给自己定义个webview添加客户端
         */
        webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                // webview.loadUrl("javascript:loadingDate('  " + mLoginSMSBean.getToken() + " ' ,'" + mAgreementBean.getAgreement_id() + "' ,'" + "2" + "','" + mAgreementBean.getAgr_type() + "','" + mAgreementBean.getNper() + "'  ,'" + mAgreementBean.getIs_change() + "'     )");

                if (!isFirst) {
                    isFirst = true;
                    webview.loadUrl("javascript:loadingDate('" + token + "','" + agreementId + "','" + "2" + "','" + agrType + "','" + nper + "','" + isChange + "' )");

                   // LogUtils.d("LUO", "===" + token);
                }

            }

        });

8. 无法下载文件?

在自己写的 WebView 下是无法直接下载文件,需要自己监听下载事件并对下载的动作进行处理。

/**
* 当下载文件时打开系统自带的浏览器进行下载,当然也可以对捕获到的 url 进行处理在应用内下载。
**/
webView.setDownloadListener(new FileDownLoadListener());

private class FileDownLoadListener implements DownloadListener {
    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
        Uri uri = Uri.parse(url);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
    }
}


作者:cpacm
链接:https://www.jianshu.com/p/fea5e829b30a

参考链接:https://blog.csdn.net/qq_21267961/article/details/79494829

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 转载:https://blog.csdn.net/carson_ho/article/details/649046...
    随心随性_0a25阅读 2,171评论 0 10
  • 这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以...
    Shawn_Dut阅读 7,202评论 3 55
  • WebView·开车指南 2016-08-31BugDev 北京市东城区首席Bug布道师开山之作,一整月交通事故血...
    53c021c38a1d阅读 825评论 0 1
  • 我与你就是河的两岸 深情只限于对望 看草儿绿了又黄 黄了又绿 年复一年 那平行线一直都没有改变 我与你就是河...
    浪客诗心阅读 301评论 0 1
  • 慈悲的荷花开始凋零 山坡上一簇簇鬼火 松林之间隐约一座古老的庭院 仿佛有人拨弄琴弦 蚂蚁长出翅膀企图迎风飞翔 何处...
    陌上冷阅读 134评论 0 3