目前很多android app都内置了可以显示web页面的界面,会发现这个界面一般都是由一个叫做WebView的组件渲染出来的,学习该组件可以为你的app开发提升扩展性。

先说下WebView的一些优点:

    可以直接显示和渲染web页面,直接显示网页
webview可以直接用html文件(网络上或本地assets中)作布局
和JavaScript交互调用 一、基本使用 首先layout中即为一个基本的简单控件: <WebView
android:id="@+id/webView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp" /> 同时,因为要房访问网络,所以manifest中必须要加uses-permission: <uses-permission android:name="android.permission.INTERNET"/> 在activity中即可获得webview的引用,同时load一个网址: webview = (WebView) findViewById(R.id.webView1);
webview.loadUrl("http://www.baidu.com/");
//webview.reload();// reload page 这个时候发现一个问题,启动应用后,自动的打开了系统内置的浏览器,解决这个问题需要为webview设置 WebViewClient,并重写方法: webview.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}); 若自己定义了一个页面加载进度的progressbar,需要展示给用户的时候,可以通过如下方式获取webview内页面的加载进度: webview.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
//get the newProgress and refresh progress bar
}
}); 每个页面,都有一个标题,比如www.baidu.com这个页面的title即“百度一下,你就知道”,那么如何知道当前webview正在加载的页面的title呢: webview.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
titleview.setText(title);//a textview
}
}); 二、通过webview控件下载文件 通常webview渲染的界面中含有可以下载文件的链接,点击该链接后,应该开始执行下载的操作并保存文件到本地中。webview来下载页面中的文件通常有两种方式: . 自己通过一个线程写java io的代码来下载和保存文件(可控性好) . 调用系统download的模块(代码简单) 方法一: 首先要写一个下载并保存文件的线程类 public class HttpThread extends Thread {
private String mUrl;
public HttpThread(String mUrl) {
this.mUrl = mUrl;
}
@Override
public void run() {
URL url;
try {
url = new URL(mUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
InputStream in = conn.getInputStream();
File downloadFile;
File sdFile;
FileOutputStream out = null;
if(Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)){
downloadFile = Environment.getExternalStorageDirectory();
sdFile = new File(downloadFile, "test.file");
out = new FileOutputStream(sdFile);
}
//buffer 4k
byte[] buffer = new byte[ * ];
int len = ;
while((len = in.read(buffer)) != -){
if(out != null)
out.write(buffer, , len);
}
//close resource
if(out != null)
out.close();
if(in != null){
in.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} 随后要实现一个DownloadListener接口,这个接口实现方法OnDownloadStart(),当用户点击一个可以下载的链接时,该回调方法被调用同时传进来该链接的URL,随后即可以对该URL塞入HttpThread进行下载操作: //创建DownloadListener (webkit包)
class MyDownloadListenter implements DownloadListener{
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype, long contentLength) {
System.out.println("url ==== >" + url);
new HttpThread(url).start();
}
}
//给webview加入监听
webview.setDownloadListener(new MyDownloadListenter()); 方法二: 直接发送一个action_view的intent即可: class MyDownloadListenter implements DownloadListener{
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype, long contentLength) {
System.out.println("url ==== >" + url);
//new HttpThread(url).start(); Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
} 三、错误处理 当我们使用浏览器的时候,通常因为加载的页面的服务器的各种原因导致各种出错的情况,最平常的比如404错误,通常情况下浏览器会提示一个错误提示页面。事实上这个错误提示页面是浏览器在加载了本地的一个页面,用来提示用户目前已经出错了。 但是当我们的app里面使用webview控件的时候遇到了诸如404这类的错误的时候,若也显示浏览器里面的那种错误提示页面就显得很丑陋了,那么这个时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面。 . 首先我们需要些一个html文件,比如error_handle.html,这个文件里面就是当出错的时候需要展示给用户看的一个错误提示页面,尽量做的精美一些。然后将该文件放置到代码根目录的assets文件夹下。 . 随后我们需要复写WebViewClient的onRecievedError方法,该方法传回了错误码,根据错误类型可以进行不同的错误分类处理 webview.setWebViewClient(new WebViewClient(){ @Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
switch(errorCode)
{
case HttpStatus.SC_NOT_FOUND:
view.loadUrl("file:///android_assets/error_handle.html");
break;
}
}
}); 其实,当出错的时候,我们可以选择隐藏掉webview,而显示native的错误处理控件,这个时候只需要在onReceivedError里面显示出错误处理的native控件同时隐藏掉webview即可。
四、webview同步cookies cookies是服务器用来保存每个客户的常用信息的,下次客户进入一个诸如登陆的页面时服务器会检测cookie信息,如果通过则直接进入登陆后的页面。 在webview中,如果之前已经登陆过了,那么下次再进入同样的登陆界面时,若需要再次登陆的话,一定会很恼人,所以这里提供一个webview同步cookies的方法。 .首先,我们假设某个网站的登陆界面需要提供两个参数,一个是name,一个是pwd,那么要是对这个页面进行登陆,那么必须给与这两个信息。我们假设服务器已经注册了name为jason,pwd为123456这个账号。 .下面,写一个Thread用来将name和pwd自动的登入,在服务器返回的response中获得cookie信息,稍后对这个cookie进行保存,这里先给出这个Thread的代码: public class HttpCookie extends Thread {
private Handler mHandler;
public HttpCookie(Handler mHandler) {
this.mHandler = mHandler;
}
@Override
public void run() {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("");//this place should add the login address List<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair("name", "jason"));
list.add(new BasicNameValuePair("pwd", ""));
try {
post.setEntity(new UrlEncodedFormEntity(list));
HttpResponse reponse = client.execute(post);
if(reponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
AbstractHttpClient absClient = (AbstractHttpClient) client;
List<Cookie> cookies = absClient.getCookieStore().getCookies();//执行post请求后才会有cookie,否则没有cookie
for(Cookie cookie:cookies){
if(cookie != null){
//TODO
//this place would get the cookies
}
}
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} 由于这是一个子线程,所以需要在主线程中创建并执行。 同时,因为其实子线程,那么里面必须含有一个handler的元素,用来当成功获取cookie后通知主线程进行同步和保存。初始化这个子线程的时候需要将主线程上的handler给传过来,随后在以上代码的TODO中发送消息,让主线程记录cookie,发送的这个消息需要将cookie信息包含进去: if(cookie != null){
//TODO
//this place would get the cookies
Message msg = new Message();
msg.obj = cookie;
if(mHandler != null){
mHandler.sendMessage(msg);
return;
}
} 随后在主线程中(webview加载登陆界面前),在handler中将会获取到cookie信息,下面将对该cookie进行保存和同步:
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg)
{
CookieSyncManager.createInstance(MainActivity.this);
CookieManager cookieMgr = CookieManager.getInstance();
cookieMgr.setAcceptCookie(true);
cookieMgr.setCookie("", msg.obj.toString());// this place should add the login host address(not the login index address)
CookieSyncManager.getInstance().sync();
webview.loadUrl("");// login index address
};
};
这个时候发现webview加载的login index页面中可以自动的登陆了并显示登陆后的界面。
五、 WebView与JavaScript的交互 . webview调用js mWebView.loadUrl("javascript:do()"); 以上是webview在调用js中的一个叫做do的方法,该js所在的html文件大致如下: <html>
<script language="javascript">
/* This function is invoked by the webview*/
function do() {
alert("");
}
</script>
<body>
<a><div style="width:80px;
margin:0px auto;
padding:10px;
text-align:center;
border:2px solid #;" >
<img id="droid" src="xx.png"/><br>
Click me!
</div></a>
</body>
</html> . js调用webview 我们假设下列的本地类是要给js调用的: package com.test.webview;
class DemoJavaScriptInterface {
DemoJavaScriptInterface() {
}
/**
* This is not called on the UI thread. Post a runnable to invoke
* loadUrl on the UI thread.
*/
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
//TODO
}
});
}
} 首先给webview设置: mWebview.setJavaScriptEnabled(true); 随后将本地的类(被js调用的)映射出去: mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo"); “demo”这个名字就是公布出去给JS调用的,那么js久可以直接用下列代码调用本地的DemoJavaScriptInterface类中的方法了: <body>
...
</body> 六、WebView与JavaScript相互调用混淆问题 若webview中的js调用了本地的方法,正常情况下发布的debug包js调用的时候是没有问题的,但是通常发布商业版本的apk都是要经过混淆的步骤,这个时候会发现之前调用正常的js却无法正常调用本地方法了。 这是因为混淆的时候已经把本地的代码的引用给打乱了,导致js中的代码找不到本地的方法的地址。 解决这个问题很简单,即在proguard.cfg文件中加上一些代码,声明本地中被js调用的代码不被混淆。下面举例说明: 第五节中被js调用的那个类DemoJavaScriptInterface的包名为com.test.webview,那么就要在proguard.cfg文件中加入: -keep public class com.test.webview.DemoJavaScriptInterface{
public <methods>;
} 若是内部类,则大致写成如下形式: -keep public class com.test.webview.DemoJavaScriptInterface$InnerClass{
public <methods>;
} 若android版本比较新,可能还需要添加上下列代码: -keepattributes *Annotation*
-keepattributes *JavascriptInterface* 来自:http://www.cnblogs.com/soaringEveryday/p/4495221.html

webview同步cookies的更多相关文章

  1. Cookie管理 WebView同步

    NoHttp的Cookie管理原理 在文档的初始化配置一章讲了NoHttp如何配置或者禁用cookie自动管理. NoHttp的Cookie自动维护,严格遵守Http协议,即区分临时Cookie和有效 ...

  2. 为WebView 同步cookie

    import android.os.Build;import android.text.TextUtils;import android.webkit.CookieManager;import and ...

  3. Android WebView使用深入浅出

    目前很多android app都内置了可以显示web页面的界面,会发现这个界面一般都是由一个叫做WebView的组件渲染出来的,学习该组件可以为你的app开发提升扩展性. 先说下WebView的一些优 ...

  4. Android使用开发WebView战斗技能

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/44619181 前段时间做项目的时候.在项目中用了WebView组件,遇到了一些问题 ...

  5. Android WebView 详解

    相关API 相关类介绍 WebResourceRequest 添加于API21,封装了一个Web资源的请求信息,包含:请求地址,请求方法,请求头,是否主框架,是否用户点击,是否重定向 WebResou ...

  6. Android中WebView使用全解

    开始 在Android系统中内嵌的WebKit,这是一个浏览器内核,它帮助着我们可以浏览网页.在实际开发中,如果你想让你的App能够访问网页,那就需要用到WebView这个控件. 如何使用? 其实使用 ...

  7. iOS - NetRequest 网络数据请求

    1.网络请求 1.1 网络通讯三要素 1.IP 地址(主机名): 网络中设备的唯一标示.不易记忆,可以用主机名(域名). 1) IP V4: 0~255.0~255.0~255.0~255 ,共有 2 ...

  8. okhttputils【 Android 一个改善的okHttp封装库】使用(二)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 上一篇讲了如何在项目中导入OKHttputils库的操作,这一篇主要讲常见请求的写法. get请求 public String getPe ...

  9. Android 5.0及以上版本使用webview不能存储第三方Cookies解决方案

    Android 5.0以上的手机使用原生WebView浏览网页,在进行登录的时候会提示验证码错误,通过查找5.0以上系统的api文档,发现5.0以上版本的webview做了较大的改动,如:同步cook ...

随机推荐

  1. 二次排序问题(分别使用Hadoop和Spark实现)

    不多说,直接上干货! 这篇博客里的算法部分的内容来自<数据算法:Hadoop/Spark大数据处理技巧>一书,不过书中的代码虽然思路正确,但是代码不完整,并且只有java部分的编程,我在它 ...

  2. Windows系统开发常用类-------------Environment类

    Windows系统开发常用类-------------Environment类:         SystemDirectory//显示系统目录         MachineName//计算机名称 ...

  3. express jade ejs 为什么要用这些?

    express是快速构建web应用的一个框架   线上文档 http://www.expressjs.com.cn/ 不用express行不行呢?    看了网上的回答:不用express直接搭,等你 ...

  4. angular中的ng-click指令案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. AngularJs轻松入门

    AngularJs轻松入门系列博文:http://blog.csdn.net/column/details/angular.html AngularJs轻松入门(一)创建第一个应用 AngularJs ...

  6. Mac Terminal 快捷键

    在Mac系统中并没有Home.End等键,所以在使用时并不是特别的顺手,但是有几个键位组合可以使Terminal的操作更加灵活方便. 1.将光标移动到行首:ctrl + a 2.将光标移动到行尾:ct ...

  7. 多项式拟合的cpp实现

    当我们拥有一组散点图数据时,通常更愿意看到其走势. 对现有数据进行拟合,并输出拟合优度是常用的方法之一. 拟合结果正确性的验证,可以使用excel自带的功能. 下面是c++代码的实现: #ifndef ...

  8. java RPC系列之二 HTTPINVOKER

    java RPC系列之二  HTTPINVOKER 一.java RPC简单的汇总 java的RPC得到技术,基本包含以下几个,分别是:RMI(远程方法调用) .Caucho的Hessian 和 Bu ...

  9. Junit使用第二弹

    实例总结 1. 参数化测试 有时一个测试方法,不同的参数值会产生不同的结果,那么我们为了测试全面,会把多个参数值都写出来并一一断言测试,这样有时难免费时费力,这是我们便可以采用参数化测试来解决这个问题 ...

  10. java keytool证书工具使用小结(转载)

    原文地址:http://www.micmiu.com/lang/java/keytool-start-guide/ Keytool 是一个Java数据证书的管理工具 ,Keytool将密钥(key)和 ...