WebView详解及使用说明;(android外壳项目总结版)

最近做了一个关于webview写安卓的壳,套HTML5的应用,虽然整个写下来后,到了目前的进度,代码量不多,共有1000多行,但是整个壳的设计思想和实现思路还是当初查了很久的。所以写下来,以备后续查看和分享。

这个webview的壳目前实现的功能我将从三方面说明并总结。

1. 最基本的功能:
  • 增加useragent以便HTML5判断出是哪个应用
  • 设置webSetting缓存
  • 拦截url并将相应网络资源替换成本地资源
  • javascript和android交互  
2. 增加用户体验的功能:
  • 网络状态监听
  • HTML进度条替换成Android原生进度条,以及onPageFinished中遇到的坑
3. 我们的应用需要增加的额外功能:
  • 口语评测打分
  • 下载资源包并在本地解压,本地MP3的播放、暂停以及退出并返回当前的播放进度。
  • 本地录音并存储为PCM格式,本地PCM的播放
  • 消息推送功能


下面进行详细说明:


  1. 最基本的功能
  • 增加useragent以便HTML5判断出是哪个应用(android或者ios)(这里的android_agent和HTML商量好就可以)
WebSettings webSettings = webView.getSettings();
String ua = webSettings.getUserAgentString();
webSettings.setUserAgentString(ua + getString(R.string.android_agent));
  • 设置webSettting缓存
我们原来的想法是将图片、css、js、son、plain、vtt等一些不变的文件下载到本地,然后通过拦截替换url进行网络资源替换成本地资源,但是后来发现webSetting缓存其实webView这个控件自己以及做的比较完善了,所以就用了webSetting自带的缓存,我们只需要进行一些webSetting的函数设置就可以了。
  • 拦截url并将相应网络资源替换成本地资源
我们将一些固定不变的图片放到工程的assets文件下,然后拦截网络的url进行替换,这样用户在第一次进入界面时,就不会因为加载图片而花费较长时间,造成用户体验不好,但是如果拦截到相应的的url时间长了,页面依旧会加载比较长的时间,但这个Android就无能为力了。
拦截替换函数如下:
webView.setWebViewClient(new WebViewClient() {

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        Log.d("start", url);

    }

    @Override
    public void onLoadResource(WebView view, String url) {
        Log.e("cache", "onLoadResource-url=" + url);
        super.onLoadResource(view, url);
    }


    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        WebResourceResponse response = null;
        Log.d("Webview", "shouldInterceptRequest url=" + url);

        if (url.contains("ajax.php") && !Validate.isNetworkConnected(Webview.this)) {
            //网络连接不可用时并且拦截到ajax时

        }

        if (url.contains("http://emodou.com/resource/be")) {
            //三种中的第一种,替换资源文件
            String path = url.substring(17, url.length());
            File file = new File(Constants.STORAGE_URL_START + path);//path: /resource/be/e_Res/BF1/22101/res/1.jpg
            Log.d("path", path);
            FileInputStream fin = null;
            try {
                fin = new FileInputStream(file);
                //进行"/"分割
                String[] urlArray = url.split("/");
                int urlCount = urlArray.length;
                Log.d("count", urlCount + "");

                //进行"."分割
                String suffixes = urlArray[urlCount - 1];
                String[] suffixesArray = suffixes.split("\\.");
                int suCount = suffixesArray.length;

                //如果遇到后缀名符合的,进行拦截替换
                if (suffixesArray[suCount - 1].equals("jpg") ||
                        suffixesArray[suCount - 1].equals("png") ||
                        suffixesArray[suCount - 1].equals("jpeg") ||
                        suffixesArray[suCount - 1].equals("JPG") ||
                        suffixesArray[suCount - 1].equals("PNG") ||
                        suffixesArray[suCount - 1].equals("JPEG")) {
                    response = new WebResourceResponse("image/png", "UTF-8", fin);
                } else if (suffixesArray[suCount - 1].equals("mp3") ||
                        suffixesArray[suCount - 1].equals("MP3")) {
                    response = new WebResourceResponse("audio/mpeg", "UTF-8", fin);//mp3替换不到
                } else if (suffixesArray[suCount - 1].equals("JSON") ||
                        suffixesArray[suCount - 1].equals("json")) {
                    response = new WebResourceResponse("application/json", "UTF-8", fin);
                } else if (suffixesArray[suCount - 1].equals("lrc") ||
                        suffixesArray[suCount - 1].equals("LRC")) {
                    response = new WebResourceResponse("text/plain", "UTF-8", fin);
                } else if (suffixesArray[suCount - 1].equals("mp4") ||
                        suffixesArray[suCount - 1].equals("MP4")) {
                    response = new WebResourceResponse("video/mp4", "UTF-8", fin);
                } else if (suffixesArray[suCount - 1].equals("vtt") ||
                        suffixesArray[suCount - 1].equals("VTT")) {
                    response = new WebResourceResponse("text/vtt", "UTF-8", fin);
                }
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            }
        }


        return response;

    }

   
});
虽然看着代码很多,但是其实有用的只有   WebResourceResponse response = null;以及response = new WebResourceResponse("text/vtt", "UTF-8", fin);这两句
  • js和android交互
android调用js的代码
webView.loadUrl("javascript:DM.progress("+percent+")");

其中DM.progress是HTML的方法,percent是android需要传过去的参数,其他为固定内容。

js调用android的代码方法:

webView.addJavascriptInterface(new JsToJava(), "record");

JsToJava()是android里面自己写的类,这个类中所有的函数都可以被JS以window.record.XX(); 方式调用,其中XX是函数名。需要特别注意的是XX函数上要添加@SuppressLint("JavascriptInterface"),否则调用会无响应

@SuppressLint("JavascriptInterface")
public void initWebView() {
}

2.增加用户体验的功能

  • 网络状态的监听
这个功能用了一个广播监听,动态注册或解绑广播,提示信息显示方式用了SnackBar(Material Design中的控件)

  • HTML进度条替换成Android原生进度条,以及onPageFinished中遇到的坑
由于android将资源替换成本地的了,因此相应的进度条也要替换成android的,由android端来控制什么时候加载完成,按正常来说,onPageFinished在被调用时,该界面就已经加载完成了,但是实际操作中发现,onPageFinished被调用的时候,界面并没有被加载完成,还有一部分web的进度条会显示,因此我们在onPageFinished函数中执行了延迟函数

public class TimeControlTask extends AsyncTask {

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        av.setVisibility(View.GONE);
        webView.setVisibility(View.VISIBLE);
    }

    @Override
    protected String doInBackground(Integer... params) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
然后在onPageFinished函数中进行调用即可
new TimeControlTask().execute();
3.我们的应用需要增加的额外功能

  • 口语评测打分,采用的科大讯飞语音打分的技术,具体请点开超链接,参考文档。
  • 下载资源包并在本地解压,本地MP3的播放、暂停以及退出并返回当前的播放进度。这里需要说明的是,下载资源包使用的是OKHttpUtils
  • 消息推送功能,集成的是友盟的推送。
暂时功能模块如上所述,如果有更新新功能,还会回头来补充这篇文章。

你可能感兴趣的:(android原创)