webview 使用详解

webview 版本差异:
在Android 4.4以下(不包含4.4)系统WebView底层实现是采用WebKit内核,而在Android 4.4及其以上采用了chromium作为系统WebView的底层内核支持。在API上5.0以上和4.4以下也有一些差别,下面会介绍我在开发中遇到的一些问题和解决方法。

基本配置:
settings.setJavaScriptEnabled(true); //允许执行js脚本
settings.setSupportZoom(true);
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true); //和上面两个设置webview适配
settings.setDomStorageEnabled(true); //允许dom存储
settings.setCacheMode(WebSettings.LOAD_NO_CACHE); //无缓存
settings.setAllowFileAccess(true);// 允许访问文件数据
settings.setBlockNetworkImage(false);//同步请求图片

关于webSettings详细api可参考:http://blog.csdn.net/a2241076850/article/details/52983939

在开发中遇到的问题:
1、webview不能播放音乐:
在android4.2(17)后需要默认需要用户的手势进行媒体播放:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
           contentWebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
    }
2、webview 切换后台依然执行,需要添加webview生命周期
webview.pause
webview.resume
webview.stop
webview.destroy

3、webview不能加载图片:
设置 settings.setBlockNetworkImage(false);后还不能显示,则是因为5.0后webview不知混合模式,
也就是不允许webview在https的请求中请求http,或者反过来

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}    

4、 内容错乱问题:
可能是因为开启了硬加速,需要把其关闭,或者因为修改了系统字体的大小,需要给webview设置固定的字体大小settings.setTextZoom(100), 或者没有做适配

settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true); 

,又或者h5同学没做适配,可放到系统浏览器打开测试,如果正常则是自身配置问题

5、webview js 无法打开窗口:

settings.setJavaScriptCanOpenWindowsAutomatically(true);

6、webview设置背景透明:

mWebView.setBackgroundColor(Color.parseColor("#00000000"));

7、横竖屏滚动条:

mWebView.setVerticalScrollBarEnabled(true);
mWebView.setHorizontalScrollBarEnabled(true);

8、webview 无法上传:

chromeClient=new WebViewUpload(null,mActivity);
webView.setWebChromeClient(chromeClient);

选择图片会回调到Activity的

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        WebViewUpload.uploadImgFromSysPhotos(resultCode,data);//上传图片
        super.onActivityResult(requestCode, resultCode, data);
    }

WebViewUpload代码:

package com.cs.csgamesdk.utils;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.ProgressBar;

import java.io.File;


/**
 * Created by Administrator on 2018/1/22.
 */

public class WebViewUpload extends WebChromeClient{

    private ValueCallback<Uri> mUploadMessage;//5.0以下
    private ValueCallback<Uri[]> mValueCallback;//5.0以上返回对象不同
    private Activity mActivity;

    public WebViewUpload(ProgressBar pbar,Activity activity){

        mActivity=activity;
    }


    public void openFileChooser(ValueCallback uploadMsg) {
        mUploadMessage=uploadMsg;
        mValueCallback=null;
        goToPhotos();
    }
    //3.0--版本
    public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
        L.e("tag","openFileChooser3.0--版本");
        mUploadMessage=uploadMsg;
        mValueCallback=null;
        goToPhotos();
    }

    // For Android 4.1
    public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
        L.e("tag","openFileChooser4.1");
        mUploadMessage=uploadMsg;
        mValueCallback=null;
        goToPhotos();
    }


    public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
        L.e("tag","openFileChoose5.0");
        mValueCallback=filePathCallback;//5.0
        mUploadMessage=null;
        goToPhotos();
        return true;
    }


public void goToPhotos() {
        Intent intent;
        intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        mActivity.startActivityForResult(Intent.createChooser(intent, "选择操作"), REQUEST_CODE);
    }

    public void uploadImgFromSysPhotos(int resultCode, Intent intent) {
        if (mUploadMessage != null) {//5.0以下
            Uri result = intent == null || resultCode != -1 ? null
                    : intent.getData();
            mUploadMessage.onReceiveValue(result);
            mUploadMessage=null;

        } else if (mValueCallback != null) {//5.0+
            Uri[] uris = new Uri[1];
            uris[0] = intent == null || resultCode != -1 ? null
                    : intent.getData();
            if (uris[0]!=null){
                mValueCallback.onReceiveValue(uris);
            }
            mValueCallback = null;
        }

    }

}

9、webview 图片下载:
webview中长按图片会返回一个url:
webView.setOnLongClickListener(new ImageDowload(mActivity,webView));

ImageDowload代码:

package com.cs.csgamesdk.imageloader;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.view.View;
import android.webkit.WebView;
import android.widget.Toast;

import com.cs.csgamesdk.utils.L;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * Created by Administrator on 2018/1/26.
 */

public class ImageDowload implements View.OnLongClickListener {
    private Activity mActivity;
    private WebView mWebview;
    private String SAVE_PIC_PATH;
    private String SAVE_REAL_PATH;

    public ImageDowload(Activity activity, WebView webView){
        mActivity=activity;
        mWebview=webView;
    }

    @Override
    public boolean onLongClick(View v) {
        WebView.HitTestResult htr = mWebview.getHitTestResult();//获取所点击的内容
        if (htr.getType() == WebView.HitTestResult.IMAGE_TYPE) {//判断被点击的类型为图片
            if(htr.getExtra().contains("cs_wechat_qrcode.jpg")){
                //下载保存二位码
                getBitmap(htr.getExtra());
            }
        }
        return false;
    }


    private void getBitmap(final String sUrl){
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                try {
                    URL url = new URL(sUrl);
                    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    conn.connect();
                    if(conn.getResponseCode() == 200){
                        InputStream inputStream = conn.getInputStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                        if(bitmap==null){
                            L.e("tag","请求失败");
                        }else{
                            saveForCamera(bitmap,getFileName()+".png", "");
                        }

                    }else{
                        L.e("tag","请求失败");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    L.e("tag",e.toString());
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
                Toast.makeText(mActivity,"保存成功", Toast.LENGTH_SHORT).show();
            }
        }.execute();
    }

    private String getFileName() {
        String fileNameRandom = getCharacterAndNumber();
        return fileNameRandom;
    }

    private String getCharacterAndNumber() {
        String rel = "";
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        Date curDate = new Date(System.currentTimeMillis());
        rel = formatter.format(curDate);
        return rel;
    }

    private void saveForCamera(Bitmap paramBitmap, String fileName, String path){
        SAVE_PIC_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
        SAVE_REAL_PATH = SAVE_PIC_PATH + "/DCIM/Camera/";
        path = SAVE_REAL_PATH + path;
        File localFile = new File(path);
        if (!localFile.exists()) {
            localFile.mkdirs();
        }
        File file = new File(path, fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            BufferedOutputStream bf = new BufferedOutputStream(new FileOutputStream(file));
            paramBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bf);
            bf.flush();
            bf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Intent localIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
        localIntent.setData(Uri.fromFile(file));
        mActivity.sendBroadcast(localIntent);
        L.e("tag","保存成功");
    }

}

10、无法请求https 、在webview中跳转url 、获取url的cookie

webView.setWebViewClient(webViewClient);

webViewClient代码:

  private WebViewClient webViewClient=new WebViewClient() {
        //在webview中跳转url
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
           //处理微信和支付宝支付
            if(url.startsWith("alipays:") || url.startsWith("alipay")||url.startsWith("qq")|| url.startsWith("mqqapi:")||url.startsWith("weixin://wap/pay?")) {
                try {
                    mActivity.startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url)));
                } catch (Exception e) {

                }
                return true;
            }
            view.loadUrl(url);
            return true;
        }

        //重写此方法可以让webview处理https请求。
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();

        }

        //在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onPageFinished(WebView view, final String url) {
        //获取cookie
            CookieManager cookieManager = CookieManager.getInstance();
            String CookieStr = cookieManager.getCookie(url);
            if (CookieStr != null) {
                String[] cookies=CookieStr.split(";");
                for (int i=0;i<cookies.length;i++){
                 Log.e("tag","cookie:"+cookies[i].trim());
                }
            }
            super.onPageFinished(view, url);
        }
    };

11、使用本地资源,如果希望不请求网络获取资源,可把资源存放在assets中,通过重写
WebViewClient 的shouldInterceptRequest方法(该方法会在天天模拟器上存在问题,具体解释在代码中,手机不会)

             @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        WebResourceResponse response = null;
        response =  super.shouldInterceptRequest(view, url);
        return getWebResourceResponse(response,url);
    }
如果获取到本地资源将不会请求网络,直接使用本地资源,getWebResourceResponse方法代码:
    private WebResourceResponse getWebResourceResponse(WebResourceResponse response,String url){
    //根据实际情况截取文件名,从而获取存放在assets的资源
        L.d("tag","URL:"+url);
        int index= url.indexOf("/",7);
        String str=url.substring(index+1);
        if(url.contains(".png")){
            try {
                response = new WebResourceResponse("image/png","UTF-8",context.getAssets().open(str));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(url.contains(".jpg")){
            try {
                response = new WebResourceResponse("image/jpeg","UTF-8",context.getAssets().open(str));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(url.contains(".gif")){
            try {
                response = new WebResourceResponse("image/gif","UTF-8",context.getAssets().open(str));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(url.contains(".js")){
            try {
                response = new WebResourceResponse("application/x-javascript","UTF-8",context.getAssets().open(str));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(url.contains(".css")){
            try {
                response = new WebResourceResponse("text/css","UTF-8",context.getAssets().open(str));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else{
            try {
            //天天模拟器出现闪退,由于context.getAssets().open(str)方法中的str有字符大小限制
                response = new WebResourceResponse(null,"UTF-8",context.getAssets().open(str));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return response;
    }

12、webview设置cookie

        CookieSyncManager.createInstance(context);
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeAllCookie();
        cookieManager.removeSessionCookie();//移除
        cookieManager.setCookie(url,"test=123456");
        cookieManager.setCookie(url,"token=sfsfsf123");//有几个添加几个
//        L.e("tag","cookie:"+cookieManager.getCookie(url));//查看cookie
        CookieSyncManager.getInstance().sync();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值