美文网首页
WebView和JS的交互

WebView和JS的交互

作者: 小和尚恋红尘 | 来源:发表于2019-08-11 17:51 被阅读0次

    一,Android调用JS接口

    1,用到的HTML代码:
    //assets/web_js.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript">
        function javaCallJavascriptNoParam() {
             document.getElementById("content").innerHTML = "Android中的Java通过WebView调用了javaScript的无参构造<br\>";
        }
        function javaCallJavascript(param) {
             document.getElementById("content").innerHTML = param;
        }
        
        </script>
    </head>
    <body>
    <div id="content"></div>
    <br/><br/>
    </body>
    </html>
    
    2,在Activity中调用HTML中方法:

    在初始化WebView时加入webView.getSettings().setJavaScriptEnabled(true); 表示允许AndroidJS交互。接下来在需要交互的地方调用JS方法:

                case R.id.btn_web_js:
                    //wvWeb.loadUrl("javascript:javaCallJavascript('"+params+"')");
                    wvWeb.loadUrl("javascript:javaCallJavascript('Android中的Java通过WebView调用了javaScript的有参构造方法')");
                    break;
                case R.id.btn_web_js_01:
                    wvWeb.loadUrl("javascript:javaCallJavascriptNoParam()");
                    break;
    

    注意:在调用传参的方法时,如果传入的参数没有提前定义,而是直接传入的话。加上单引号(‘’)。具体写法参考上面的

    二,JS调用Android方法

    1,用到的HTML代码:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <h4>JS与Android(Java)的交互</h4>
        <input type="button" value="js调Java:方法一" onclick="ok()">
        <script type="text/javascript">
        function ok() {
            window.java_call_js.webMessage("JS与Android(Java)的交互");
        }
        </script>
    </head>
    <body>
    <div id="content"></div>
    <br/><br/>
    </body>
    </html>
    
    2,在JS中调用Android中方法:

    在初始化WebView时加入

    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().addJavascriptInterface(new JavaScriptUtil(), "java_call_js");//其中“java_call_js”为双方约定好的标记
    
    3,JavaScriptUtil中写交互的方法
        /*
         * 作为addJavascriptInterface()方法的第二个参数,该类将被映射为JavaScript对象
         */
        private final class JavaScriptUtil {
    
            JavaScriptUtil() {
            }
    
            @JavascriptInterface
            public void webMessage(String msg) {
                Log.e("LHC", "msg:" + msg);
                ToastUtil.show(msg);
            }
        }
    

    注意:方法必须加入"@JavascriptInterface",不然js无法调用;方法传入的参数类型为基本类型,无法接受对象

    三,JS调用Android方法,Android方法有调用JS方法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <h4>JS与Android(Java)的交互</h4>
        <script type="text/javascript">
        function javaCallJavascriptNoParam() {
             document.getElementById("content").innerHTML = "Android中的Java通过WebView调用了javaScript的无参构造<br\>";
        }
        function javaCallJavascript(param) {
             document.getElementById("content").innerHTML = param;
        }
        </script>
    </head>
    <body>
    <br/><br/>
    <input type="button" value="js调Android" onclick="java_call_js.javaCallJsMethod()">
    <div id="content"></div>
    <br/><br/>
    </body>
    </html>
    
    2,JavaScriptUtil中写交互的方法
    private final class JavaScriptUtil {
    
            JavaScriptUtil() {
            }
    
            @JavascriptInterface
            public void javaCallJsMethod() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        wvWeb.loadUrl("javascript:javaCallJavascriptNoParam()");
                    }
                });
            }
        }
    

    注意:JS调用的Android方法中在调用JS方法时,要写在主线程中,不然会报错

    四,调用Android相机,相册

        private ValueCallback<Uri> mUploadMessage;
        private ValueCallback<Uri[]> mUploadCallbackAboveL;
        private final static int PHOTO_REQUEST = 100;
        private final static int VIDEO_REQUEST = 120;
        private boolean videoFlag = false;
    
       //自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签】
        public class MyChromeWebClient extends WebChromeClient {
            // For Android 3.0-
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
                mUploadMessage = uploadMsg;
                if (videoFlag) {
                    recordVideo();
                } else {
                    takePhoto();
                }
    
            }
    
            // For Android 3.0+
            public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
                Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
                mUploadMessage = uploadMsg;
                if (videoFlag) {
                    recordVideo();
                } else {
                    takePhoto();
                }
            }
    
            //For Android 4.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
                mUploadMessage = uploadMsg;
                if (videoFlag) {
                    recordVideo();
                } else {
                    takePhoto();
                }
            }
    
            // For Android 5.0+
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                Log.d(TAG, "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
                mUploadCallbackAboveL = filePathCallback;
                if (videoFlag) {
                    recordVideo();
                } else {
                    takePhoto();
                }
                return true;
            }
        }
    
        /**
         * 拍照
         */
        private void takePhoto() {
            File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg");
            imageUri = Uri.fromFile(fileUri);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                imageUri = FileProvider.getUriForFile(WebViewNewActivity.this, getPackageName() + ".fileprovider", fileUri);//通过FileProvider
                // 创建一个content类型的Uri
            }
            PhotoUtils.takePicture(WebViewNewActivity.this, imageUri, PHOTO_REQUEST);
        }
    
        /**
         * 录像
         */
        private void recordVideo() {
            Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            //限制时长
            intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);
            //开启摄像机
            startActivityForResult(intent, VIDEO_REQUEST);
        }
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == PHOTO_REQUEST) {
                if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (mUploadCallbackAboveL != null) {
                    onActivityResultAboveL(requestCode, resultCode, data);
                } else if (mUploadMessage != null) {
                    mUploadMessage.onReceiveValue(result);
                    mUploadMessage = null;
                }
            } else if (requestCode == VIDEO_REQUEST) {
                if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
    
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (mUploadCallbackAboveL != null) {
                    if (resultCode == RESULT_OK) {
                        mUploadCallbackAboveL.onReceiveValue(new Uri[]{result});
                        mUploadCallbackAboveL = null;
                    } else {
                        mUploadCallbackAboveL.onReceiveValue(new Uri[]{});
                        mUploadCallbackAboveL = null;
                    }
    
                } else if (mUploadMessage != null) {
                    if (resultCode == RESULT_OK) {
                        mUploadMessage.onReceiveValue(result);
                        mUploadMessage = null;
                    } else {
                        mUploadMessage.onReceiveValue(Uri.EMPTY);
                        mUploadMessage = null;
                    }
    
                }
            }
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
            if (requestCode != PHOTO_REQUEST || mUploadCallbackAboveL == null) {
                return;
            }
            Uri[] results = null;
            if (resultCode == Activity.RESULT_OK) {
                if (data == null) {
                    results = new Uri[]{imageUri};
                } else {
                    String dataString = data.getDataString();
                    ClipData clipData = data.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
    
                    if (dataString != null)
                        results = new Uri[]{Uri.parse(dataString)};
                }
            }
            mUploadCallbackAboveL.onReceiveValue(results);
            mUploadCallbackAboveL = null;
        }
    
    

    四,WebView中打开下载链接

     @Override
                public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {//8.0以上
                    Uri url = request.getUrl();
                    String strUrl = url.toString();
                    if (!TextUtils.isEmpty(strUrl)) {
                       if (strUrl.endsWith(".pdf")) {//打开一个pdf文件的下载链接
                           //                    openBrowsable(strUrl);
                        downloadBySystem(strUrl, "inline", "application/pdf");
                        }else{
                            view.loadUrl(strUrl);
                        }
                    }
                    return true;
                }
    
        /**
         * 直接用浏览器打开
         * @param strUrl 文件下载路径
         */
        private void openBrowsable(String strUrl) {
            Uri uri = Uri.parse(strUrl);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            intent.addCategory(Intent.CATEGORY_BROWSABLE);
            startActivity(intent);
        }
    
        /**
         * 系统下载
         * @param url 文件下载路径
         * @param contentDisposition 描述
         * @param mimeType 类型
         */
        private void downloadBySystem(String url, String contentDisposition, String mimeType){
            if (TextUtils.isEmpty(url)) return;
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));//指定下载地址
            request.allowScanningByMediaScanner();//允许媒体扫描,根据下载的文件类型被加入相册,音乐等媒体库
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);//设置通知的显示类型,下载进行时和完成后进行通知
            String[] split = url.split("/");
            request.setTitle(split[split.length -1]);//设置通知栏的标题,默认使用文件名
            request.setDescription("Description");//设置通知栏的描述
            request.setAllowedOverMetered(false);//设置是否允许在计费流量下下载
            request.setVisibleInDownloadsUi(false);//设置是否允许记录在下载管理界面可见
            request.setAllowedOverRoaming(true);//设置是否允许在漫游时下载
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);//设置允许下载的网络类型
    
            String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
            Log.e("LHC", "fileName:"+ fileName);
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);//
            DownloadManager downloadManager = (DownloadManager) getSystemService(Activity.DOWNLOAD_SERVICE);
            long downloadId = downloadManager.enqueue(request);
            Log.e("LHC", "downloadId:"+ downloadId);
    
        }
    
        private class DownloadCompleteReceiver extends BroadcastReceiver{
    
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null){
                    if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())){
                        long downloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
                        Log.e("LHC", "downloadID:"+downloadID);
                        DownloadManager downloadManager = (DownloadManager) getSystemService(Activity.DOWNLOAD_SERVICE);
                        String mimeTypeForDownloadedFile = downloadManager.getMimeTypeForDownloadedFile(downloadID);
                        Log.e("LHC", "mimeTypeForDownloadedFile:"+mimeTypeForDownloadedFile);
                        if (TextUtils.isEmpty(mimeTypeForDownloadedFile)){
                            mimeTypeForDownloadedFile = "*/*";
                        }
                        Uri uriForDownloadedFile = downloadManager.getUriForDownloadedFile(downloadID);
                        Log.e("LHC", "uriForDownloadedFile:"+uriForDownloadedFile);
                        if (uriForDownloadedFile != null){
                            Intent handlerIntent = new Intent(Intent.ACTION_VIEW);
                            handlerIntent.setDataAndType(uriForDownloadedFile, mimeTypeForDownloadedFile);
                            context.startActivity(handlerIntent);
                        }
                    }
                }
            }
        }
    
    protected void initData() {
            downloadCompleteReceiver = new DownloadCompleteReceiver();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
            registerReceiver(downloadCompleteReceiver, intentFilter);
        }
    

    五,WebView中长按图片保存

            webView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    final WebView.HitTestResult hitTestResult = webView.getHitTestResult();
                    // 如果是图片类型或者是带有图片链接的类型
                    if (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE ||
                            hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
                        // 弹出保存图片的对话框
                        AlertDialog.Builder builder = new AlertDialog.Builder(WebActivity.this);
                        builder.setTitle("提示");
                        builder.setMessage("保存图片到本地");
                        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                picUrl = hitTestResult.getExtra();//获取图片链接
                                //保存图片到相册
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        new SaveImage().execute();
                                    }
                                }).start();
                            }
                        });
                        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            // 自动dismiss
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                            }
                        });
                        AlertDialog dialog = builder.create();
                        dialog.show();
                        return true;
                    }
                    return false;//保持长按可以复制文字
                }
            });
    
        /***
         * 功能:用线程保存图片
         *
         * @author wangyp
         */
        private class SaveImage extends AsyncTask<String, Void, String> {
            @Override
            protected String doInBackground(String... params) {
                String result = "";
                try {
                    String sdcard = Environment.getExternalStorageDirectory().toString();
                    File file = new File(sdcard + "/Download");
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    int idx = picUrl.lastIndexOf(".");
                    file = new File(sdcard + "/Download/" + new Date().getTime() + System.currentTimeMillis()+ ".png");
                    InputStream inputStream = null;
                    URL url = new URL(picUrl);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(20000);
                    if (conn.getResponseCode() == 200) {
                        inputStream = conn.getInputStream();
                    }
                    byte[] buffer = new byte[4096];
                    int len = 0;
                    FileOutputStream outStream = new FileOutputStream(file);
                    while ((len = inputStream.read(buffer)) != -1) {
                        outStream.write(buffer, 0, len);
                    }
                    outStream.close();
                    result = "保存成功";
                } catch (Exception e) {
                    result = "保存失败!";
                }
                return result;
            }
    
            @Override
            protected void onPostExecute(String result) {
                showToast(result);
            }
        }
    

    相关文章

      网友评论

          本文标题:WebView和JS的交互

          本文链接:https://www.haomeiwen.com/subject/egcxwqtx.html