您的位置:首页 > 移动开发

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

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

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

1. 最基本的功能:

增加useragent以便HTML5判断出是哪个应用
设置webSetting缓存
拦截url并将相应网络资源替换成本地资源
javascript和android交互  
2. 增加用户体验的功能:

网络状态监听
HTML进度条替换成Android原生进度条,以及onPageFinished中遇到的坑
3. 我们的应用需要增加的额外功能:
口语评测打分
下载资源包并在本地解压,本地MP3的播放、暂停以及退出并返回当前的播放进度。
本地录音并存储为PCM格式,本地PCM的播放
消息推送功能

下面进行详细说明:

最基本的功能
增加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
消息推送功能,集成的是友盟的推送
暂时功能模块如上所述,如果有更新新功能,还会回头来补充这篇文章。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息