Android 中 WebView 交互

一充包、前言:

在 Android 中我們要給 js 傳遞參數(shù)娃善;js 也會給我們傳遞參數(shù)多柑;有時候也要拿到 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");
        //協(xié)議id
        agreementId = getIntent().getStringExtra("agreementId");
        //期數(shù)
        nper = getIntent().getIntExtra("nper", 0);
        //跳轉(zhuǎn)鏈接
        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);

        //設(shè)置是否支持變焦
        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);
        //設(shè)置緩存模式
        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);//利用反射機制去修改設(shè)置對象
                if (method != null) {
                    method.invoke(webview.getSettings(), true);//修改設(shè)置
                }
            }
        } 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);//加載完網(wǎng)頁進度條消失
                } else {
                    progressBar1.setVisibility(View.VISIBLE);//開始加載網(wǎng)頁時顯示進度條
                    progressBar1.setProgress(newProgress);//設(shè)置進度值
                }


            }
        });


        webview.loadUrl(url);

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

        //允許調(diào)試
        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) {
                    //按返回鍵操作并且能回退網(wǎng)頁
                    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("協(xié)議簽署成功");

        finish();

    }


    /**
     * 2.編寫一個提供給Web的Js接口類
     */


    public class JsInterface {
        private Context mContext;

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

        //在js中調(diào)用window.AndroidWebView.showInfoFromJs(name)竣灌,便會觸發(fā)此方法聂沙。
        @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);// 協(xié)議id
        map.put("nickname",jsBean.getNickname());//用戶姓名
        map.put("id_card_no",jsBean.getId_card_no());//身份證號

        map.put("mobile",jsBean.getMobile());//  聯(lián)系方式
        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());// 協(xié)議標題
        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));//協(xié)議類型 1:普通協(xié)議 2:隱私協(xié)議
        map.put("nper",String.valueOf(nper));//期數(shù)
        map.put("nper_upper",jsBean.getNper_upper());//大寫期數(shù)

        //本地網(wǎng)絡(luò)請求
        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;
    }
}

二、總結(jié):

1. 設(shè)置WebView屬性初嘹,能夠執(zhí)行Javascript腳本

mWebView.getSettings().setJavaScriptEnabled(true);//設(shè)置js可用

2. 設(shè)置加載進度條

 webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                // TODO 自動生成的方法存根
                if (newProgress == 100) {
                    progressBar1.setVisibility(View.GONE);//加載完網(wǎng)頁進度條消失
                } else {
                    progressBar1.setVisibility(View.VISIBLE);//開始加載網(wǎng)頁時顯示進度條
                    progressBar1.setProgress(newProgress);//設(shè)置進度值
                }


            }
        });

3. 瀏覽器內(nèi)部跳轉(zhuǎn):

  /**
         * 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) {
                    //按返回鍵操作并且能回退網(wǎng)頁
                    if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
                        //后退
                        webview.goBack();
                        return true;
                    }
                }
                return false;
            }
        });

5. webview 是否允許調(diào)試:

 //允許調(diào)試
        if (BuildConfig.DEBUG){
            WebView.setWebContentsDebuggingEnabled(true);
        }else {
            WebView.setWebContentsDebuggingEnabled(false);
        }

6. 接受 JS 給 Android 傳遞參數(shù):

在js中調(diào)用本地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 傳遞參數(shù)

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

頁面加載完成后及汉,給 JS 傳遞參數(shù):

        /**
         * 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 下是無法直接下載文件削樊,需要自己監(jiān)聽下載事件并對下載的動作進行處理豁生。

/**
* 當下載文件時打開系統(tǒng)自帶的瀏覽器進行下載,當然也可以對捕獲到的 url 進行處理在應(yīng)用內(nèi)下載漫贞。
**/
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
鏈接:http://www.reibang.com/p/fea5e829b30a

參考鏈接:https://blog.csdn.net/qq_21267961/article/details/79494829

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甸箱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子迅脐,更是在濱河造成了極大的恐慌芍殖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谴蔑,死亡現(xiàn)場離奇詭異豌骏,居然都是意外死亡龟梦,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門窃躲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來计贰,“玉大人,你說我怎么就攤上這事蒂窒≡甑梗” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵洒琢,是天一觀的道長秧秉。 經(jīng)常有香客問我,道長衰抑,這世上最難降的妖魔是什么象迎? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮呛踊,結(jié)果婚禮上砾淌,老公的妹妹穿的比我還像新娘。我一直安慰自己恋技,他們只是感情好拇舀,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布逻族。 她就那樣靜靜地躺著蜻底,像睡著了一般。 火紅的嫁衣襯著肌膚如雪聘鳞。 梳的紋絲不亂的頭發(fā)上薄辅,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機與錄音抠璃,去河邊找鬼站楚。 笑死,一個胖子當著我的面吹牛搏嗡,可吹牛的內(nèi)容都是我干的窿春。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼采盒,長吁一口氣:“原來是場噩夢啊……” “哼旧乞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起磅氨,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤尺栖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后烦租,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體延赌,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡除盏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挫以。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片者蠕。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖掐松,靈堂內(nèi)的尸體忽然破棺而出蠢棱,到底是詐尸還是另有隱情,我是刑警寧澤甩栈,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布泻仙,位于F島的核電站,受9級特大地震影響量没,放射性物質(zhì)發(fā)生泄漏玉转。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一殴蹄、第九天 我趴在偏房一處隱蔽的房頂上張望究抓。 院中可真熱鬧,春花似錦袭灯、人聲如沸刺下。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橘茉。三九已至,卻和暖如春姨丈,著一層夾襖步出監(jiān)牢的瞬間畅卓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工蟋恬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翁潘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓歼争,卻偏偏與公主長得像拜马,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沐绒,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載:https://blog.csdn.net/carson_ho/article/details/649046...
    隨心隨性_0a25閱讀 2,182評論 0 10
  • 這篇博客主要來介紹 WebView 的相關(guān)使用方法洒沦,常見的幾個漏洞豹绪,開發(fā)中可能遇到的坑和最后解決相應(yīng)漏洞的源碼,以...
    Shawn_Dut閱讀 7,229評論 3 55
  • WebView·開車指南 2016-08-31BugDev 北京市東城區(qū)首席Bug布道師開山之作,一整月交通事故血...
    53c021c38a1d閱讀 829評論 0 1
  • 我與你就是河的兩岸 深情只限于對望 看草兒綠了又黃 黃了又綠 年復一年 那平行線一直都沒有改變 我與你就是河...
    浪客詩心閱讀 313評論 0 1
  • 慈悲的荷花開始凋零 山坡上一簇簇鬼火 松林之間隱約一座古老的庭院 仿佛有人撥弄琴弦 螞蟻長出翅膀企圖迎風飛翔 何處...
    陌上冷閱讀 136評論 0 3