Webview兼容h5的localstorage以及input file标签

  首先我先描述一下我遇到的问题,在我把h5的项目嵌入安卓原生的外壳时,由于h5的

代码涉及到他们自己本地的存储,所以在我点击h5页面上的按钮后,页面没有任何响应,
在排查一顿之后,发像是因为没有兼容他们的localstorage,要实现兼容其实很简单

 //兼容h5的localStorage
        settings.setDomStorageEnabled(true);
        settings.setAppCacheMaxSize(1024*1024*8);
        String path = getApplicationContext().getCacheDir().getAbsolutePath();//把内部私有缓存目录'/data/data/包名/cache/'作为webview的appcache的缓存路径
        settings.setAppCachePath(path);
        settings.setAllowFileAccess(true);
        settings.setAppCacheEnabled(true);
  还有一个就是h5的项目中利用inputfile标签实现了调用系统相机以及图库的功能,而我们

安卓如果不做任何处理,原生的webview其实不能支持这样的功能,要支持这样的功能,主要
需要重写WebChromeClient,自己实现几个方法:

// For Android 3.0+
        @SuppressWarnings({"rawtypes"})
        public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
            vCbFileChooser = uploadMsg;
            /*Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i,"文件选择"),
                    FILECHOOSER_RESULTCODE
            );*/
            selPic();
        }

        // For Android 3.0+
        @SuppressWarnings({"unused", "rawtypes"})
        public void openFileChooser(ValueCallback uploadMsg) {
            openFileChooser(uploadMsg, "");
        }

        //For Android 4.1
        @SuppressWarnings({"unused", "rawtypes"})
        public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
            openFileChooser(uploadMsg, acceptType);
        }

        // For Lollipop 5.0+ Devices
        @SuppressWarnings("unchecked")
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public boolean onShowFileChooser(
                WebView mWebView, ValueCallback<Uri[]> filePathCallback,
                WebChromeClient.FileChooserParams fileChooserParams
        ) {
            if (vCbFileChooser != null) {
                vCbFileChooser.onReceiveValue(null);
                vCbFileChooser = null;
            }

            vCbFileChooser = filePathCallback;

            selPic();

            return true;
        }

完整代码如下,我也尽量做了一些优化,提高加载h5时的渲染速度
public class MainActivity extends AppCompatActivity {

WebView wv_webview;
ImageView iv_start;

//String url="http://wxtest.51hbx.com/wap/FQcarInfo.html";//服务器
//String url="http://10.1.100.121/wap/FQcarInfo.html";//庆庆
String url="http://test.51hbx.com:2043/wap/FQcarInfo.html";//小飞
//String url="http://test.51hbx.com:2043/wap/adultrisks.html?productId=7";//小飞

WebSettings settings;
AlertDialog loadingDialog;

boolean hasTouch=true;
boolean hasRequest=false;
boolean firstTime=true;//记录是否是首次加载,避免显示空白页

String urlPrevious="";//记录上一次的url
String urlPreviousStart="";//记录上一次的url,

//保存状态
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    wv_webview.saveState(outState);
}

@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    wv_webview= (WebView) findViewById(R.id.wv_webview);
    iv_start= (ImageView) findViewById(R.id.iv_start);

    settings = wv_webview.getSettings();
    //js交互
    wv_webview.setVerticalScrollbarOverlay(true);
    //设置webview支持js
    settings.setJavaScriptEnabled(true);
    settings.setAllowFileAccess(true);
    settings.setAllowContentAccess(true);
    settings.setDefaultTextEncodingName("UTF -8");//设置默认为utf-8

    initCacheStrategies(settings);//配置缓存
    initMyConfiguration(settings);//初始化部分配置,优化
    if (null!=savedInstanceState)
    {
        wv_webview.restoreState(savedInstanceState);
    }
    else
    {
        // contain_wv.loadData(list.get(0).getContent(), "text/html;charset=UTF-8", null);
        wv_webview.loadUrl(url);
    }
    wv_webview.addJavascriptInterface(new JsInterface(this),"AndroidWebView");
    //添加客户端支持
    wv_webview.setWebChromeClient(new MyWebChromeClient());
    wv_webview.setWebViewClient(new WebViewClient(){
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.equals(urlPrevious))
            {
                urlPrevious=url;
                return false;
            }
            else
            {
                urlPrevious=url;
                view.loadUrl(url);
                Log.e("==shouldOverride=","======="+url);
                return super.shouldOverrideUrlLoading(view, url);
                //return false;
            }
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            Log.e("===0====","===onPageStarted==="+url+":"+GapsTimes.effectiveTime(400));
            if (!firstTime)
            {
                /*if (!url.equals(urlPreviousStart))
                {*/
                    LoadingUtils.showDialogMethod(MainActivity.this);
                /*}*/
            }
            else
            {
                firstTime=false;
            }
            urlPreviousStart=url;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (!wv_webview.getSettings().getLoadsImagesAutomatically()){
                wv_webview.getSettings().setLoadsImagesAutomatically(true);
            }
            LoadingUtils.displayLoadingDialog();
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
            LoadingUtils.displayLoadingDialog();
        }

        //加载页面资源会调用,每加载一次就会调用一次
        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
            Log.e("===1====","===onLoadResource===");
        }
    });

}

private void initMyConfiguration(WebSettings settings) {
    //解决webview加载网页不显示图片
    if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
    {
        settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    }
    if (Build.VERSION.SDK_INT>=19)
    {
        wv_webview.getSettings().setLoadsImagesAutomatically(true);
    }
    else
    {
        wv_webview.getSettings().setLoadsImagesAutomatically(false);
    }
    //提高渲染的优先级
    settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
    settings.setBlockNetworkImage(true);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

//配置webview的缓存
private void initCacheStrategies(WebSettings settings) {
    //配置浏览器的缓存
    /*settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    //配置h5的缓存
    settings.setAppCacheEnabled(true);
    String path = getApplicationContext().getCacheDir().getPath();//把内部私有缓存目录'/data/data/包名/cache/'作为webview的appcache的缓存路径
    settings.setAppCachePath(path);
    settings.setAppCacheMaxSize(5*1024*1024);*/

    //另一种组合
    //设置缓存模式
    /*settings.setCacheMode(WebSettings.LOAD_DEFAULT);
    //开启 DOM storage API 功能
    settings.setDomStorageEnabled(true);*/

    //兼容h5的localStorage
    settings.setDomStorageEnabled(true);
    settings.setAppCacheMaxSize(1024*1024*8);
    String path = getApplicationContext().getCacheDir().getAbsolutePath();//把内部私有缓存目录'/data/data/包名/cache/'作为webview的appcache的缓存路径
    settings.setAppCachePath(path);
    settings.setAllowFileAccess(true);
    settings.setAppCacheEnabled(true);
}

private class JsInterface {
    private Context mContext;

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

    //在js中调用window.AndroidWebView.showInfoFromJs(name),便会触发此方法。
    @JavascriptInterface
    public void showInfoFromJs(String name) {
        Toast.makeText(mContext, name, Toast.LENGTH_SHORT).show();
    }
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode==KeyEvent.KEYCODE_BACK)&&wv_webview.canGoBack())
    {
        wv_webview.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    wv_webview.stopLoading();
    wv_webview.destroy();
    wv_webview=null;
}

private final static int FILECHOOSER_RESULTCODE = 2;


private final static int TAKEPHOTO_RESULTCODE = 1;
private ValueCallback<Uri[]> vCbFileChooser;
String pathTakePhoto="";
Uri uriTakePhoto;

public class MyWebChromeClient extends WebChromeClient {

    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        Log.e("==onProgressChanged==", "======" + newProgress);
        if (newProgress >= 100) {
            iv_start.setVisibility(View.GONE);
            //解除数据阻止
            settings.setBlockNetworkImage(false);
        }
    }

    // For Android 3.0+
    @SuppressWarnings({"rawtypes"})
    public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
        vCbFileChooser = uploadMsg;
        /*Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        MainActivity.this.startActivityForResult(
                Intent.createChooser(i,"文件选择"),
                FILECHOOSER_RESULTCODE
        );*/
        selPic();
    }

    // For Android 3.0+
    @SuppressWarnings({"unused", "rawtypes"})
    public void openFileChooser(ValueCallback uploadMsg) {
        openFileChooser(uploadMsg, "");
    }

    //For Android 4.1
    @SuppressWarnings({"unused", "rawtypes"})
    public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
        openFileChooser(uploadMsg, acceptType);
    }

    // For Lollipop 5.0+ Devices
    @SuppressWarnings("unchecked")
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public boolean onShowFileChooser(
            WebView mWebView, ValueCallback<Uri[]> filePathCallback,
            WebChromeClient.FileChooserParams fileChooserParams
    ) {
        if (vCbFileChooser != null) {
            vCbFileChooser.onReceiveValue(null);
            vCbFileChooser = null;
        }

        vCbFileChooser = filePathCallback;

        selPic();

        return true;
    }


}

@SuppressWarnings("unused")
private void selPic() {
    if (!checkSDcard()){return;}
    String[] selectPicTypeStr = { "拍照","选择照片" };
    AlertDialog alertDialog = new AlertDialog.Builder(this)
            .setItems(
                    selectPicTypeStr,
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            switch (which) {
                                case 0://拍照
                                    chkPrivBeforeTakePhoto();
                                    break;
                                case 1://选择图片文件
                                    choosePicFile();
                                    break;
                                default:
                                    break;
                            }

                        }
                    }
            ).setOnCancelListener(
                    new DialogInterface.OnCancelListener() {

                        @SuppressWarnings("unchecked")
                        @Override
                        public void onCancel(DialogInterface dialog) {
                            if (null != vCbFileChooser) {
                                vCbFileChooser.onReceiveValue(null);
                                vCbFileChooser = null;
                            }
                        }
                    }
            ).show();
}

private static final int PERMISSIONS_REQUEST_CODE_TAKE_PHOTO = 1;
@SuppressWarnings("unchecked")
private void chkPrivBeforeTakePhoto() {
    if(
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
            ) {
        if (null != vCbFileChooser) {
            vCbFileChooser.onReceiveValue(null);
            vCbFileChooser = null;
        }
        new AlertDialog
                .Builder(this)
                .setTitle("提示信息")
                .setMessage("该功能需要您接受应用对一些关键权限(拍照)的申请,如之前拒绝过,可到手机系统的应用管理授权设置界面再次设置。")
                .setPositiveButton("确认", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCompat.requestPermissions(MainActivity.this, new String[]{
                                Manifest.permission.CAMERA,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE
                        }, PERMISSIONS_REQUEST_CODE_TAKE_PHOTO);
                    }
                })
                .show();
    } else {
        chooseTakePhoto();
    }
}

private void chooseTakePhoto() {
    pathTakePhoto = Environment.getExternalStorageDirectory().getPath()
            + "/mbossclient/camera/temp/"
            + (System.currentTimeMillis() + ".jpg");
    File vFile = new File(pathTakePhoto);
    if (!vFile.exists()) {//必须确保文件夹路径存在,否则拍照后无法完成回调
        File vDirPath = vFile.getParentFile();
        vDirPath.mkdirs();
    } else {
        if (vFile.exists()) {
            vFile.delete();
        }
    }

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    uriTakePhoto = Uri.fromFile(vFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uriTakePhoto);
    startActivityForResult(intent, TAKEPHOTO_RESULTCODE);
}

private boolean checkSDcard() {
    boolean flag = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    if(!flag){Toast.makeText(this, "请插入手机存储卡再使用本功能", Toast.LENGTH_SHORT).show();}
    return flag;
}

/**
 * 选择文件
 */
private void choosePicFile(){
    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
    i.addCategory(Intent.CATEGORY_OPENABLE);
    i.setType("image/*");
    MainActivity.this.startActivityForResult(
            Intent.createChooser(i,"文件选择"),
            FILECHOOSER_RESULTCODE
    );
}

@SuppressLint("NewApi")
@SuppressWarnings("unchecked")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == FILECHOOSER_RESULTCODE) {//从文件选择器选择照片
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if(null == vCbFileChooser) {return;}
            vCbFileChooser.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
            vCbFileChooser = null;
        } else {
            if(null == vCbFileChooser) {return;}
            Uri result = (intent == null || resultCode != RESULT_OK)? null:intent.getData();
            vCbFileChooser.onReceiveValue(new Uri[]{result});
            vCbFileChooser = null;
        }
    } else if(requestCode == TAKEPHOTO_RESULTCODE){
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if(null == vCbFileChooser) {return;}
            if(null == uriTakePhoto) {
                vCbFileChooser.onReceiveValue(null);
                vCbFileChooser = null;
                return;
            }
            addImageGallery(pathTakePhoto);
            Uri[] uris = new Uri[1];
            uris[0] = uriTakePhoto;
            vCbFileChooser.onReceiveValue(uris);
            vCbFileChooser = null;
            uriTakePhoto = null;
            pathTakePhoto = null;
        } else {
            if(null == vCbFileChooser) {return;}
            if(null == uriTakePhoto) {
                vCbFileChooser.onReceiveValue(null);
                vCbFileChooser = null;
                return;
            }
            addImageGallery(pathTakePhoto);
            vCbFileChooser.onReceiveValue(new Uri[]{uriTakePhoto});
            vCbFileChooser = null;
            uriTakePhoto = null;
            pathTakePhoto = null;
        }
    }
    super.onActivityResult(requestCode, resultCode, intent);

}

/**
 * 解决拍照后在相册中找不到的问题
 */
private void addImageGallery(String path) {
    if (null == path || "".equals(path)) {
        return;
    }
    File file = new File(pathTakePhoto);
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值