webview 开发常用点介绍

作者: 老夫掐指一算z | 来源:发表于2017-10-10 15:04 被阅读0次

    1.基本适配设置

    settings =getSettings();
    settings.setJavaScriptEnabled(true);//支持js
    settings.setUseWideViewPort(true); 
    settings.setLoadWithOverviewMode(true);
    

    2.硬件加速 提高webview加载速度

    if (Build.VERSION.SDK_INT >= 21) {
        settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    } else if (Build.VERSION.SDK_INT >= 19) {
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    } else if (Build.VERSION.SDK_INT < 19) {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }
    

    3.设置webview 安全性 一般上传应用会对apk进行安全扫描,有关webview的安全问题,可通过该方法解决

    private void setWebViewSecurity(){
        try {
            removeJavascriptInterface("searchBoxJavaBridge_");
            removeJavascriptInterface("accessibility");
            removeJavascriptInterface("accessibilityTraversal");   
            getSettings().setSavePassword(false);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
            }
          } catch (Exception e) {
        }
    }
    

    4.支持视频全屏播放方法,重写webChromeClient getVideoLoadingProgressView,onShowCustomView,onHideCustomView
    三个方法。
    原理是获取视频播放的view 然后创建父类容器view 加载到根view上显示出来

     public class CommonWebChromeClient extends WebChromeClient{
     /*** 视频播放相关的方法 **/
            @Override
            public View getVideoLoadingProgressView() {
                if(videoWebFactory!=null){
                    return videoWebFactory.getVideoLoadingProgressView();
                }
                return null;
            }
            @Override
            public void onShowCustomView(View view, CustomViewCallback callback) {
                if(videoWebFactory!=null){
                    videoWebFactory.showCustomView(view, callback);
                }
            }
            @Override
            public void onHideCustomView() {
                if(videoWebFactory!=null){
                    videoWebFactory.hideCustomView();
                }
            }
    }
    

    VideoWebFactory代码

    public class VideoWebFactory {
          /** 视频全屏参数 */
        protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        private View customView;
        private FrameLayout fullscreenContainer;
        private WebChromeClient.CustomViewCallback customViewCallback;
        private Context context;
        private Window window;
        private WebView webView;
     
        public  VideoWebFactory (Context context,WebView webView){
            this.context =context;
            this.window =  ((Activity)context).getWindow();
            this.webView = webView;
        }
        public View getVideoLoadingProgressView(){
            FrameLayout frameLayout = new FrameLayout(context);
            frameLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            return frameLayout;
        }
        /** 视频播放全屏 **/
        public void showCustomView(View view, CustomViewCallback callback) {
            // if a view already exists then immediately terminate the new one
            if (customView != null) {
                callback.onCustomViewHidden();
                return;
            }
           window.getDecorView();
            FrameLayout decor = (FrameLayout) window.getDecorView();
            fullscreenContainer = new FullscreenHolder(context);
            fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
            decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
            customView = view;
            setStatusBarVisibility(false);
            customViewCallback = callback;
        }
        
        /** 隐藏视频全屏 */
        public void hideCustomView() {
            if (customView == null) {
                return;
            }
            setStatusBarVisibility(true);
            FrameLayout decor = (FrameLayout) window.getDecorView();
            decor.removeView(fullscreenContainer);
            fullscreenContainer = null;
            customView = null;
            customViewCallback.onCustomViewHidden();
            webView.setVisibility(View.VISIBLE);
        }
        /** 全屏容器界面 */
       private static class FullscreenHolder extends FrameLayout {
    
            public FullscreenHolder(Context ctx) {
                super(ctx);
                setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
            }
            @Override
            public boolean onTouchEvent(MotionEvent evt) {
                return true;
            }
        }
        private void setStatusBarVisibility(boolean visible) {
            int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
            window.setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        public View getCustomView() {
            return customView;
        }
    }
    
    

    4.支持文件上传
    webview支持file文件上传,不过,对应有版本的区别,5.0以下的版本只能每次选择一个文件,5.0以上的版本支持多文件选择
    (1)当触发上传文件选择的时候,webview会回调openFileChooser 方法并提供ValueCallback<Uri> mUM 作为文件上传提交对象(文件选择可以调用相关的库)
    (2)最后在选择完文件之后,设置uri 对象,通过mUM.onReceiveValue(uri);进行文件提交。注意,如果没有选择文件,请设置mUM.onReceiveValue(null); 作为取消选择文件的操作,不然,webview将处于文件选择状态,web页面不能点击响应。

     public class CommonWebChromeClient extends WebChromeClient{
    /**
             * 文件上传
             * */
            //For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg){
                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                ((Activity)context).startActivityForResult(Intent.createChooser(i,"File Chooser"), WebFileFactory.SELECT_PHOTO);
            }
            // For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
            public void openFileChooser(ValueCallback uploadMsg, String acceptType){
                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                ((Activity)context).startActivityForResult(Intent.createChooser(i, "File Browser"),WebFileFactory.SELECT_PHOTO);
            }
            //For Android 4.1+ 只能选择一个文件
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
                mUM = uploadMsg;
                if(onFileSelected!=null){
                    onFileSelected.onSelectOne(mUM,mUMA);
                }
                if(webFileFactory!=null){
                    webFileFactory.setmUM(mUM);
                    webFileFactory.showPhotoSelectForOne();
                }
            }
           //For Android 5.0+ 多个文件选择
            public boolean onShowFileChooser(
                    WebView webView, ValueCallback<Uri[]> filePathCallback,
                    WebChromeClient.FileChooserParams fileChooserParams){
                mUMA = filePathCallback;
                if(onFileSelected!=null){
                    onFileSelected.onSelect(mUM,mUMA);
                }
                if(webFileFactory!=null){
                    webFileFactory.setmUMA(mUMA);
                    webFileFactory.showPhotoSelect();
                }
                return true;
    }
    

    webFileFactory为 图片选择 处理类

    public class WebFileFactory {
        private Context context;
        private ValueCallback<Uri> mUM;
        private ValueCallback<Uri[]> mUMA;
        private Uri uri;
        public static final int TAKE_PICTURE = 102;
        public static final int SELECT_PHOTO = 103;
        public static final int TAKE_VIDEO = 107;
        public static final int SELECT_VIDEO = 106;
        public static final int TAKE_PICTURE_ONE = 104;
        public static final int SELECT_PHOTO_ONE = 105;
        public static final int TAKE_VIDEO_ONE = 108;
        public static final int SELECT_VIDEO_ONE = 109;
    
        public WebFileFactory(Context context) {
            this.context = context;
        }
    
        public void setmUM(ValueCallback<Uri> mUM) {
            this.mUM = mUM;
        }
    
        public void setmUMA(ValueCallback<Uri[]> mUMA) {
            this.mUMA = mUMA;
        }
    
        public void showPhotoSelectForOne() {
            String[] datas = new String[] { "拍照", "录像", "相册", "视频" };
            SheetView sheetView = new SheetView(context, datas);
            sheetView.setLisenter(new SheetView.Lisenter() {
                @Override
                public void onSelect(int position) {
                    if (position == 1) {
                        uri = Uri.fromFile(new File(
                                FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".png"));
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
                        intent.putExtra("return-data", true);
                        ((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_PICTURE_ONE);
                    } else if (position == 2) {
                        uri = Uri.fromFile(new File(
                                FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".mp4"));
                        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);// 创建一个请求视频的意图
                        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);// 设置视频的质量,值为0-1,
                        intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 60);// 设置视频的录制长度,s为单位
                        intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20 * 1024 * 1024L);// 设置视频文件大小,字节为单位
                        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
                        ((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_VIDEO_ONE);
                    } else if (position == 3) {
                        Intent intent = new Intent(context, SelectPhotoActivity.class);
                        intent.putExtra("max", 1);
                        ((Activity) context).startActivityForResult(intent, WebFileFactory.SELECT_PHOTO_ONE);
                    } else if (position == 4) {
                        Intent i = new Intent(Intent.ACTION_PICK,
                                android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                        ((Activity) context).startActivityForResult(i, WebFileFactory.SELECT_VIDEO_ONE);
                    }
                }
            });
            sheetView.show();
        }
    
        public void showPhotoSelect() {
            String[] datas = new String[] { "拍照", "录像", "相册", "视频" };
            SheetView sheetView = new SheetView(context, datas);
            sheetView.setLisenter(new SheetView.Lisenter() {
                @Override
                public void onSelect(int position) {
                    if (position == 1) {
                        uri = Uri.fromFile(new File(
                                FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".png"));
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
                        intent.putExtra("return-data", true);
                        ((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_PICTURE);
                    } else if (position == 2) {
                        uri = Uri.fromFile(new File(
                                FileUtils.getAppImageFilePath(context) + "/" + System.currentTimeMillis() + ".mp4"));
                        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);// 创建一个请求视频的意图
                        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);// 设置视频的质量,值为0-1,
                        intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 60);// 设置视频的录制长度,s为单位
                        intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20 * 1024 * 1024L);// 设置视频文件大小,字节为单位
                        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
                        ((Activity) context).startActivityForResult(intent, WebFileFactory.TAKE_VIDEO);
                    } else if (position == 3) {
                        Intent intent = new Intent(context, SelectPhotoActivity.class);
                        intent.putExtra("max", 9);
                        ((Activity) context).startActivityForResult(intent, WebFileFactory.SELECT_PHOTO);
                    } else if (position == 4) {
                        Intent i = new Intent(Intent.ACTION_PICK,
                                android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                        ((Activity) context).startActivityForResult(i, WebFileFactory.SELECT_VIDEO);
                    } else {
                        if (mUMA != null) {
                            mUMA.onReceiveValue(null);
                        } else if (mUM != null) {
                            mUM.onReceiveValue(null);
                        }
                    }
                }
            });
            sheetView.show();
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == TAKE_PICTURE_ONE || requestCode == TAKE_VIDEO_ONE) {
                if (uri != null) {
                    mUM.onReceiveValue(uri);
                }
            } else if (requestCode == SELECT_PHOTO_ONE) {
                if (data != null) {
                    Bundle bundle = data.getBundleExtra("bundle");
                    List<PhotoInfo> imgs = bundle.getParcelableArrayList("imgs");
                    Uri uri = Uri.parse(imgs.get(0).getPath_file());
                    mUM.onReceiveValue(uri);
                } else {
                    if (mUMA != null) {
                        mUMA.onReceiveValue(null);
                    } else if (mUM != null) {
                        mUM.onReceiveValue(null);
                    }
                }
            } else if (requestCode == SELECT_VIDEO_ONE) {
                if (data != null) {
                    Uri uri = data.getData();
                    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
                    cursor.moveToFirst();
                    String path = "file://" + cursor.getString(1); // 视频文件路径
                    Uri uri_video = Uri.parse(path);
                    mUM.onReceiveValue(uri_video);
                } else {
                    if (mUMA != null) {
                        mUMA.onReceiveValue(null);
                    } else if (mUM != null) {
                        mUM.onReceiveValue(null);
                    }
                }
            }
    
            if (requestCode == TAKE_PICTURE || requestCode == TAKE_VIDEO) {
                if (uri != null) {
                    Uri[] uris = new Uri[] { uri };
                    mUMA.onReceiveValue(uris);
                }
            } else if (requestCode == SELECT_PHOTO) {
                if (data != null) {
                    Bundle bundle = data.getBundleExtra("bundle");
                    List<PhotoInfo> imgs = bundle.getParcelableArrayList("imgs");
                    Uri[] uris = new Uri[imgs.size()];
                    for (int i = 0; i < imgs.size(); i++) {
                        PhotoInfo photoInfo = imgs.get(i);
                        Uri uri = Uri.parse(photoInfo.getPath_file());
                        uris[i] = uri;
                    }
                    mUMA.onReceiveValue(uris);
                } else {
                    if (mUMA != null) {
                        mUMA.onReceiveValue(null);
                    } else if (mUM != null) {
                        mUM.onReceiveValue(null);
                    }
                }
            } else if (requestCode == SELECT_VIDEO) {
                if (data != null) {
                    Uri uri = data.getData();
                    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
                    cursor.moveToFirst();
                    String path = "file://" + cursor.getString(1); // 视频文件路径
                    Uri uri_video = Uri.parse(path);
                    mUMA.onReceiveValue(new Uri[] { uri_video });
                } else {
                    if (mUMA != null) {
                        mUMA.onReceiveValue(null);
                    } else if (mUM != null) {
                        mUM.onReceiveValue(null);
                    }
                }
            }
        }
    }
    

    5.附上本人封装的CommonWebView以及使用方式

    public class CommonWebView extends WebView{
        private Context context;
        private WebSettings settings;
        private VideoWebFactory videoWebFactory;
        private WebFileFactory webFileFactory;
        private ValueCallback<Uri> mUM;
        private ValueCallback<Uri[]> mUMA;
        private OnFileSelected onFileSelected;
        public CommonWebView(Context context) {
            super(context);
            this.context =context;
            init();
        }
        public CommonWebView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context =context;
            init();
        }
        public CommonWebView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            this.context =context;
            init();
        }
     
        private void init(){
            //基础设置
            settings =getSettings();
            settings.setJavaScriptEnabled(true);
            settings.setUseWideViewPort(true); // 关键点
            settings.setLoadWithOverviewMode(true);
            if (Build.VERSION.SDK_INT >= 21) {
                settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
                setLayerType(View.LAYER_TYPE_HARDWARE, null);
            } else if (Build.VERSION.SDK_INT >= 19) {
                setLayerType(View.LAYER_TYPE_HARDWARE, null);
            } else if (Build.VERSION.SDK_INT < 19) {
                setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            }
            //设置webview安全性
            setWebViewSecurity();
            setWebViewClient();
        }
        
        private void setWebViewClient(){
            setWebViewClient(new CommonWebViewClient());
        }
        //支持视频播放
        public void setSupportVideo(CommonWebChromeClient webChromeClient){
            videoWebFactory = new VideoWebFactory(context,this);
            setWebChromeClient(webChromeClient);
        }
        //文件上传
        public CommonWebView setSupportFile(CommonWebChromeClient webChromeClient){
            webFileFactory = new WebFileFactory(context);
            settings.setAllowFileAccess(true);
            setSupportVideo(webChromeClient);
            return this;
        }
       public void setOnFileSelected(OnFileSelected onFileSelected) {
           this.onFileSelected = onFileSelected;
       }
       public WebFileFactory getWebFileFactory() {
           return webFileFactory;
       }
       public class CommonWebViewClient extends WebViewClient{
           @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                 loadUrl(url);
                return true;
            }
       }
       
       public class CommonWebChromeClient extends WebChromeClient{
           /*** 视频播放相关的方法 **/
            @Override
            public View getVideoLoadingProgressView() {
                if(videoWebFactory!=null){
                    return videoWebFactory.getVideoLoadingProgressView();
                }
                return null;
            }
            @Override
            public void onShowCustomView(View view, CustomViewCallback callback) {
                if(videoWebFactory!=null){
                    videoWebFactory.showCustomView(view, callback);
                }
            }
            @Override
            public void onHideCustomView() {
                if(videoWebFactory!=null){
                    videoWebFactory.hideCustomView();
                }
            }
            /**
             * 文件上传
             * */
            //For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg){
                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                ((Activity)context).startActivityForResult(Intent.createChooser(i,"File Chooser"), WebFileFactory.SELECT_PHOTO);
            }
            // For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
            public void openFileChooser(ValueCallback uploadMsg, String acceptType){
                mUM = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                ((Activity)context).startActivityForResult(Intent.createChooser(i, "File Browser"),WebFileFactory.SELECT_PHOTO);
            }
            //For Android 4.1+ 只能选择一个文件
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
                mUM = uploadMsg;
                if(onFileSelected!=null){
                    onFileSelected.onSelectOne(mUM,mUMA);
                }
                if(webFileFactory!=null){
                    webFileFactory.setmUM(mUM);
                    webFileFactory.showPhotoSelectForOne();
                }
            }
           //For Android 5.0+ 多个文件选择
            public boolean onShowFileChooser(
                    WebView webView, ValueCallback<Uri[]> filePathCallback,
                    WebChromeClient.FileChooserParams fileChooserParams){
                mUMA = filePathCallback;
                if(onFileSelected!=null){
                    onFileSelected.onSelect(mUM,mUMA);
                }
                if(webFileFactory!=null){
                    webFileFactory.setmUMA(mUMA);
                    webFileFactory.showPhotoSelect();
                }
                return true;
            }
       } 
        /**
         * 设置webview安全性
         */
        private void setWebViewSecurity(){
            try {
                removeJavascriptInterface("searchBoxJavaBridge_");
                removeJavascriptInterface("accessibility");
                removeJavascriptInterface("accessibilityTraversal");   
                getSettings().setSavePassword(false);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
                }
            } catch (Exception e) {
            }
        }
        
        public interface OnFileSelected{
            void onSelectOne(ValueCallback<Uri> mUM,   ValueCallback<Uri[]> mUMA);
            void onSelect(ValueCallback<Uri> mUM,   ValueCallback<Uri[]> mUMA);
        }
    }
    
    支持视频播放
    webView.setSupportVideo(webView.new CommonWebChromeClient());
    支持文件上传
    webView.setSupportFile(wbw_web.new CommonWebChromeClient());
    

    相关文章

      网友评论

        本文标题:webview 开发常用点介绍

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