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

来源:互联网 发布:unity3d最全资源合集 编辑:程序博客网 时间:2024/06/06 18:17
  首先我先描述一下我遇到的问题,在我把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="";//记录上一次的urlString urlPreviousStart="";//记录上一次的url,//保存状态@Overrideprotected void onSaveInstanceState(Bundle outState) {    super.onSaveInstanceState(outState);    wv_webview.saveState(outState);}@SuppressLint("SetJavaScriptEnabled")@Overrideprotected 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);}@Overridepublic 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();    }}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {    if ((keyCode==KeyEvent.KEYCODE_BACK)&&wv_webview.canGoBack())    {        wv_webview.goBack();        return true;    }    return super.onKeyDown(keyCode, event);}@Overrideprotected 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")@Overrideprotected 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);}

}

阅读全文
0 0
原创粉丝点击