1.网络访问方式
Android SDK提供了一些与网络有关的包。
包 | 描述 |
java.net | 该包提供与网络通信相关的类,包括流和数据包socket、Internet协议和常见HTTP处理。该包是一个多功能网络资源。Java开发人员可以立即使用这个熟悉的包创建应用程序 |
java.io | 该包虽然没有提供显示网络通信功能,但是仍然非常重要。该包中的类由其他Java包中提供的socket和连接使用。它们还用于与本地文件的交互。 |
java.nio | 该包包含表示特定数据类型缓冲区的类,适用于两个基于java语言的端点之间的通信 |
org.apache* | 该包表示许多为HTTP通信提供精确控制和功能的包,可以将Apache视为流行的开源Web服务器 |
android.net | 该包除核心java.net.*类以外,包含额外的网络访问socket和URI类,后者被频繁用于Android应用程序开发,而不仅仅是传统的联网 |
android.net.http | 该包包含处理SSL证书的类 |
Android与服务器通信的方式一般有两种:HTTP通信和SOCKET通信。
1.1HTTP通信
超文本传输协议(Hypertext Transfer Protocol,HTTP)是Intent的基础,同时也是手机上应用最广泛的通信协议之一。HTTP工作在TCP/IP体系中的TCP上。它可以通过传输层的TCP在客户端和服务器端之间进行传输数据以及数据之间的交互,格式如:http://host:port/path,“http”表示要通过HTTP来定位网络资源;"host"表示合法的Internet主机域名或者IP地址;"port"指定一个端口号,为空则使用缺省端口号80;"path"指定请求资源的URI,例如输入:www.android.com,浏览器自动转换成:http://www.android.com/。
一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。
图1.HTTP请求报文的一般格式
(1)请求行
请求行由请求方法、URL字段和HTTP版本字段3个字段组成,它们用空格分隔。例如:GET/index.html HTTP/1.0
HTTP请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。以下介绍最常用的GET方法和POST方法。
- GET方法:当客户端要从服务器中读取文档时,使用GET方法。GET方法要求服务器将URL定位的资源放在响应报文的数据部分,并回送给客户端。使用GET方法时,请求参数和对应的值附加在URL后面,利用一个问号(?)代表URL的结尾与请求参数的开始,传递参数长度有限制。例如:/index.jsp?id=100&op=bind。
- POST方法:当客户端给服务器提供信息较多时,使用POST方法。POST方法将请求参数封装在HTTP请求数据中,以键/值得形式出现,从而可以传输大量数据。
(2)请求头部
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号(:)分隔。请求头部通知服务器有关客户端请求的信息。典型的请求头部有:
- User-Agent:产生请求的浏览器类型。
- Accept:客户端可识别的内容型列表。
- Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
(3)空行
最后一个请求头部之后是一个空行,用来发送回车和换行符,通知服务器以下不再有请求头部。
(4)请求数据
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头部是Content-Type和Content-Length。
一个HTTP响应报文由3个部分组成:状态行、消息报头、响应正文。
其次,我们介绍HTTP连接。
在HTTP连接中,客户端每一次发送请求,服务器端都需要给予相应的响应,在当前请求结束之后,会主动释放本次连接。从建立连接到关闭连接的过程称为“一次连接”。在HTTP1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求之后,就自动释放连接。而HTTP1.1则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”“无状态”的连接。所以客户端应用程序要想获取最新的网络数据,就需要客户端实时向服务器发起连接请求。此外,HTTP连接使用的是“请求一响应”的方式(2次握手),不仅在请求时需要建立连接,而且需要在客户端向服务器发出请求后,服务器端才能返回数据。
Android应用程序经常会和服务器端交互,这就需要手机客户端发送网络请求。下面介绍4种网络请求方式。
(1)Get方式请求
//发起请求的路径
String path="http://reg.163.com/logins.jsp?id=hellowordld&pwd=android";
try {
//新建一个URL对象
URL url=new URL(path);
//打开一个HttpURLConnection连接
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//连接超时设置,比如设置时间为5s
urlConnection.setConnectTimeout(5*1000);
//执行连接操作
urlConnection.connect();
//若请求成功,通过读取连接的数据流来获取返回的数据
if(urlConnection.getResponseCode() == 200){//返回的状态码为200时,则连接成功
//readStream()方法为从inputStream中获得数据的自定义方法
byte[] data = readStream(urlConnection.getInputStream());
}else{
Log.d("d","Get方式请求失败");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
(2)Post方式请求
//发起请求的路径
String path="http://reg.163.com/logins.jsp?id=hellowordld&pwd=android";
try {
//将请求的参数进行了UTF-8编码,并转换成byte数组
String params = "id"+ URLEncoder.encode("helloword","UTF-8");
//新建一个URL对象
URL url=new URL(path);
//打开一个HttpURLConnection连接
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//连接超时设置,比如设置时间为5s
urlConnection.setConnectTimeout(5*1000);
//使用Post请求时,设置允许输出
urlConnection.setDoInput(true);
//在使用Post请求时,设置不能使用缓存
urlConnection.setUseCaches(false);
//设置该请求时为Post请求
urlConnection.setRequestMethod("POST");
urlConnection.setInstanceFollowRedirects(true);
//配置请求Content-Type
urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencode");
//执行连接操作
urlConnection.connect();
//发送请求参数
DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());
dos.write(postData);
dos.flush();
dos.close();
if(urlConnection.getResponseCode() == 200){//连接成功
//readStream()方法为从inputStream中获得数据的自定义方法
byte[] data = readStream(urlConnection.getInputStream());
}else{
Log.i("d","Post方式请求失败");
}
//关闭连接
urlConnection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
(3)HttpGet方式请求
//发起请求的路径
String path="http://reg.163.com/logins.jsp?id=hellowordld&pwd=android";
//新建一个HttpGet对象
HttpGet httpGet = new HttpGet(path);
//获取HttpClient对象以及HttpResponse实例。
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResp = httpClient.execute(httpGet);
//判断请求是否成功,若成功则返回获取的数据
if(httpResp.getStatusLine().getStatusCode() == 200){
String result = EntityUtils.toString(httpResp.getEntity(),"UTF-8");
}else{
Log.i("d", "HttpGet方式请求失败");
}
(4)HttpPost方式请求
//发起请求的路径
String path="http://reg.163.com/logins.jsp?id=hellowordld&pwd=android";
//新建一个HttpPost对象
HttpPost httpPost = new HttpPost(path);
//配置Post请求参数
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id","helloworld"));
params.add(new BasicNameValuePair("pwd","android"));
//设置字符集
HttpEntity entity = new URLEncoderFormEntity(params,HTTP.UTF-8);
//设置参数实体
httpPost.setEntity(entity);
//获取Http对象及HttpResponse实例
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResp = httpClient.execute(httpPost);
//判断请求是否成功,若成功则返回获取的数据
if(httpResp.getStatusLine().getStatusCode() == 200){
String result = EntityUtils.toString(httpResp.getEntity(),"UTF-8");
}else{
Log.i("d", "HttpPost方式请求失败");
}
注意HttpClient 需要导入jar包,http://hc.apache.org/httpclient-legacy/为下载地址。
此外,要想进行网络通信,还需要再AndroidManifest.xml文件中配置权限:<uses-permission android:name="android.permission.INTERNET"/>
1.2Socket通信
在介绍Socket通信之前,我们先了解Socket连接。要想明白Socket连接,则先要明白TCP连接。手机能够使用联网功能是因为手机底层应用了TCP/IP,可以使手机终端通过无线网络建立TCP连接。TCP可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。
首先,建立一个TCP连接需要经过“三次握手”。
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack = j + 1),同时,自己发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack = k+1)。此包发送完毕后,客户端和服务器进入ESTABLISHED状态,完成三次握手。
图2.三次握手的全过程
套接字(Socket)是通信的基石,是支持TCP/IP的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信的五种信息:连接使用的协议、本地主机的IP地址、本地进程的协议端口、远程主机的IP地址、远程进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP交互提供了套接字(Socket)接口。通过Socket接口,应用层可以和传输层,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket;另一个运行于服务器端,称为ServerSocket。
套接字之间的连接过程分为三个步骤:服务器监听、客户端请求、连接确认。
(1)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
(2)客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后向服务器端套接字提出连接请求。
(3)连接确认:当服务器端套接字监听到或者收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端。一旦客户端确认了此描述,双方就正式建立连接。而服务器套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
图3.Socket基本通信模型
1.3HTTP连接和Socket连接的区别
在通常情况下,Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。而Http连接使用的是“请求一响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能返回数据。
很多情况下,需要服务器端主动向客户端推送数据,从而保持客户端于服务器端的实时与同步。此时若双方建立的Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端。
2.数据解析
2.1JSON格式解析
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。JSON完全独立于语言的文本格式,也保留了类似C语言家族的习惯(包括C、C++、C#、Java、JavaSript、Perl、Python等)。这些特性使JSON称为理想的数据交换语言,其易于人阅读和编写,同时也易于机器解析和生成。
JSON数据是一些列键值对的集合,Android的JSON解析部分都在org.json包中。下面主要介绍JSONObject和JSONArray两个类。
JSONObejct类:JSON中对象(Object)以"{"开始,以"}"结束。对象中的每一个item都是一个键值对,表现为"key:value"的形式。键值对之间使用逗号(英文状态)分隔。代码如下:
{
"name":"coolxing",
"age":24,
"address":{
“street”:"huilongGuan",
"city":"beijing",
"country":"china"
}
}
JSON对象的key只能是String类型的,而value可以是String、Number、Boolean、null、Object对象,甚至是Array数组,也就是说可以存在嵌套的情况。
JSONArray类:JSON数组(Array)以"["开始,以"]"结束,数组中的每一个元素可以是String、Number、Boolean、null、Object对象,甚至是Array数组,书组件的元素使用逗号(英文状态)分隔,代码如下。
[
"coolxing",24
{
"street":"huiLongGuan",
"city":"beijing"
"country":"china"
}
]
在熟悉了JSON数据格式之后,我们接下来将创建一个JSON文本。假设现在要创建这样一个JSON文本。
{
"phone":["12345678"],//数组
"name":"xxx", //字符串
"age":100, //数值
"address":{
"country":"china",
"province":"jiangsu"
}, //对象
"married":false //布尔值
}
下面为创建上述JSON文本呢的基本思路。
(1)如果最外层是{},那么要求创建一个对象。
(2)第一个键"phone"的值是数组,所以需要创建数组对象
(3)把键为"phone""name""age"的数组加入person对象
(4)键address的值是对象,所以又要创建一个对象
(5)把键为"address""married"的值加入person对象
//创建一个对象
JSONObject person = new JSONObject();
//创建数组对象
JSONArray phone = new JSONArray();
phone.put("12345678");
try {
person.put("phone",phone);
person.put("name","xxx");
person.put("age",100);
//创建一个对象
JSONObject address = new JSONObject();
address.put("country","china");
address.put("province","jiangsu");
person.put("address",address);
person.put("married",false);
} catch (JSONException e) {
e.printStackTrace();
}
以下为解析JSON数据的基本思路。
(1)获取JSON
(2)第一个值为数组,所以先获取数组
(3)解析person对象中键为"phone"的值
(4)解析person对象中键为"name""age"的值
(5)第四个值为对象,所以先获取对象,之后进行键为“country”“province”“married”的解析
//如果有多个对象,可以通过以下方法一次进行解析。
//解析如下:
try {
JSONObject object = new JSONObject(phone.toString());
JSONArray array = object.getJSONArray("phone");
List<HashMap<String,Object>> list = new ArrayList<HashMap<String, Object>>();
for (int i = 0;i < array.length();i++){
//创建json对象
JSONObject object2 = array.getJSONObject(i);
String country = object2.getString("country");
String province = object2.getString("province");
HashMap<String,Object> map = new HashMap<>();
map.put("country",country);
map.put("province",province);
list.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
2.2SAX方式解析
在Android开发中,经常会解析xml文件。常见的解析xml的方式有三种:SAX、Pull、Dom。下面介绍以下SAX。
SAX(Simple API for XML)是基于事件驱动的。Android的事件机制是基于回调函数的,在用SAX解析xml文档时,在读到文档开始和结束标签时就会回调一个事件,在读到其他节点与内容的时候也回调一个事件。
既然涉及事件,就有事件源和事件处理器。在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser方法来解析XML文档,并产生事件。事件处理器是org.xml.sax包中ContentHandler、DTDHandler、ErrorHandler以及EntityResolver这四个接口。
XMLReader通过相应事件处理器注册方法sexXXXX()来完成与ContentHandler、DTDHandler、ErrorHandler以及EntityResolver这4个接口的连接。详细内容如下。
处理器名称 | 处理事件 | XMLReader注册方法 |
ContentHandler | 与文档内容有关的事件。 (1)文档的开始与结束 (3)可忽略的实体 (4)名称空间前缀映射开始和结束 (5)处理指令 (6)字符数据和可忽略的空格 | setContentHanlder(ContentHandler.h) |
ErrorHandler | 处理XML文档时产生的错误 | setErrorHandler(ErrorHandler.h) |
DTDHandler | 处理对文档的DTD进行解析时产生的相应事件 | setDTDHandler(DTDHandler.h) |
EntityResolver | 处理外部实体 | setEntityResolver(EntityResolver.r) |
但是我们无需继承这4个接口,SDK为我们提供了DefaultHandler类来处理回调问题。DefaultHandler类的一些主要事件回调方法如下表。
方法名称 | 含义 |
setDocumentLocation(Locator locator) | 设置一个可以定位文档内容时间事件发生位置的定位对象 |
startDocument() | 用于处理文档解析开始 |
startElement(String uri,Strin localName,String qName,Attributes atts) | 处理元素开始时间,从参数中可以获取元素所在空间的URL、元素名称、属性列表等信息 |
Characters(char[] ch,int start,int length) | 处理元素的字符内容,从参数中可以获得内容 |
endElement(String uri,String localName,String qName) | 处理元素结束事件,从参数中可以获得元素所在空间的URL、元素名称等信息 |
endDocument() | 用于处理文档解析的结束事件 |
另外,SAX解析器提供了一个工厂类:SAXParserFactory,SAX的解析类SAXParser,可以调用它的parser()方法进行解析。
以上内容可知,我们需要XmlReader以及DefaultHandler来配合解析一个xml文档,具体解析思路如下。
(1)创建SAXParserFactory对象。
(2)根据SAXParserFactory.newSAXParser()方法返回一个SAXparser解析器。
(3)根据SAXParser解析器获取事件源对象XMLReader
(4)实例化一个DeafultHandler对象。
(5)连接事件源对象XMLReader到事件处理类DefaultHandler中
(6)调用XMLReader的parse()方法从输入源中获取到的xml数据。
(7)通过DefaultHandler返回我们需要的数据集合。
public List<River> parse(String xmlPath){
List<River> rivers = null;
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
//获取事件源
XMLReader xmlReader = parser.getXMLReader();
//设置处理器
RiverHandler handler = new RiverHandler();
xmlReader.setContentHandler(handler);
//解析xml文档
xmlReader.parse(new InputSource(new URL(xmlPath).openStream()));
xmlReader.parse(new InputSource(this.Context.getAssets().open(xmlPath)));
rivers = handler.getRivers();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return rivers;
}
SAX方式解析数据时,重点在DefaultHandler对象中对每一个元素节点、属性、文本内容、文档内容进行处理。
前面说过,DefaultHandler是基于事件处理模型的,基本处理方式是:当SAX解析器导航到文档开始标签时回调startDocument()方法,导航到文档结束标签时回调endDocument()方法。当SAX解析器导航到元素开始标签时回调startElement()方法,导航到其文本内容时回调characters()方法,导航到标签结束时回调endElemen()方法。
处理xml文档的逻辑如下:
(1)当导航到文档开始标签时,在回调函数startDocument中,可以不做处理,当然也可以验证UTF-8等
(2)当导航到rivers开始标签时,在回调函数startElement()中,可以实例化一个集合用来存储list。不过我们这里不用,因为在构造函数中已经实例化了。
(3)导航到river开始标签时,就说明需要实例化River对象了。当然,river标签中还有name、lenth属性,因此实例化River后还必须取出属性值attributes.getValue(NAME)。同时赋予river对象中,并为导航到的river标签中添加一个boolean为"true"的表示,用来说明导航到了river元素。
(4)有的river标签内还有子标签(节点),但是SAX解析器不知道导航到什么标签的,它只懂得开始、结束而已。那么如何让它人的我们的各个标签呢?这就需要判断。此处使用回调函数startElement()中的参数String localName,把我们的标签字符串与这个参数比较一下即可。我们还必须让SAX知道,现在导航的是某个标签,因此添加一个"true"属性让SAX解析器知道。
(5)当然它一定会导航到结束标签</river>或者</rivers>,如果是</river>标签,记得把river对象添加进list。如果是river中的子标签</introduction>,就把前面的设置标记导航到整个标签的boolean标记设置为"false"
3.获取网络状态
在Android应用程序的开发过程中,有时需要判断手机网络类型。就目前的Android手机来说,可能会存在5种网络状态。
(1)无网络(可能情况:手机停机、网络没有开启、信号不好)
(2)使用Wifi上网
(3)CMWAP(中国移动代理)
(4)CMNET上网
(5)2G/3G/4G上网
通常使用ConectivityManager类来确定是否存在网络连接。我们还可以获得网络变化的情况。
ConnectivityManager nw = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = nw.getActiveNetworkInfo();
networkInfo.isAvailable();//网络是否可用
networkInfo.getDetailedState();//网络详细状态
networkInfo.isConnected();//网络是否连接
//获取网络连接状态
NetworkInfo.State mobile = nw.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
//获取Wifi连接网络状态
NetworkInfo.State wifi = nw.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
//当然要在manifest中添加网络权限。
4.JavaScript与Java交互
如果你想发布一个Web App作为客户端的一部分,则可以使用WebView。WebView是Android中View的扩展,能将Web页面作为活动布局(Activity Layout)。它不包含一个浏览器的完整功能,比如导航控制或者地址栏。WebView默认做的仅仅是展现一个Web页面。
使用WebView的一个常见场景是,当我们想要在应用中提供一些可能需要更新的信息时,就需要在Android应用中创建包含WebView的Activity,然后利用它来展示我们挂在网上的文档。
另外一个使用WebView的场景是,我们为用户提供数据时需要连接网络获取数据,比如E-mail。在这种情况下,我们可能会发现在Android应用中创建一个WebView来展示提供了相关数据的Web页面要更为容易,而不是让Android应用程序试图连接到网络来获取数据、解析数据并将其显示到Android相应的布局中。我们可以设计一个专供Android设备使用的Web页面,并在Android中实现一个WebView来加载这个页面。
4.1WebView
Android手机内置了一款基于webkit内核的浏览器,且Android SDK为开发者提供了WebView组件。
要在应用中加入WebView,只需要在活动布局中加入元素即可。
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webview"/>
如果访问的页面中有JavaScript,则WebView必须设置支持JavaScript。
WebView webView =findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
如果页面中有链接,并且希望单击链接继续在当前应用程序中响应,而不是通过Android系统自带的浏览器来响应,那么必须设置WebView的WebViewClient对象。
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
浏览网页时,如果不做任何处理,单击系统"Back"键,整个浏览器会调用finish()方法并退出浏览器。如果希望浏览器回退网页而不是退出,需要在当前Activity中处理并重写该Back事件。
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack() == true){
webView.goBack();
return true;
}
return super.onKeyDown(keyCode,event);
}
如果WebView中需要用户手动输入用户名、密码或其他信息,则WebView必须设置支持获取手势焦点:webview.requestFocusFromTouch()。
WebView加载页面主要调用三个方法:LoadUrl、LoadData、LoadDataWithBaseURL。
(1)LoadUrl:直接加载并显示网页、图片。
(2)LoadData:显示文字与图片内容。
(3)LoadDataWithBaseURL:显示文字与图片内容(支持多个模拟器版本)
常用方法如下:
(1)直接网页显示:
private void webHtml(){
webView.loadUrl("http://www.google.com");
}
(2)中文显示
private void locakHtmlZh(){
String data = "<html>"+"<body>"+"测试webview加载图片"+"</body>"+"</html>";
webView.loadData(URLEncoder.encode(data,encoding),mimeType,encoding);
}
(3)显示本地网页文件
private void localHtml(){
webView.loadUrl("file://android_asset/test.html");
}
(4)显示本地图片和文字混合的Html内容
private void localHtmlImage(){
String data = "测试本地图片和文字混合显示,这里是<IMG src ='\"file:///adroid_asset/icon.png\"/'>APK里的图片";
webView.loadDataWithBaseURL("about:blank",data,mimeType,encoding,"");
}
关于WebView中WebSettings的常用方法如下表。
常用方法 | 描述 |
setJavaScriptEnabled(true) | 支持js脚本 |
setPluginsEnabled(true) | 支持插件 |
setUseWideViewPort(false) | 将图片调整到适合WebView的大小 |
setSupportZoom(true) | 支持缩放 |
setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN) | 支持内容从新布局 |
supportMultipleWindows() | 多窗口 |
setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK) | 关闭WebView中缓存 |
setAllowFileAccess(true) | 设置可以访问文件 |
setNeedInitialFocus(true) | 当WebView调用requestFoucus时为WebView设置节点 |
在WebView有效工作之前,要保证应用能访问网络。要访问网络,需要在配置文件中获得网络许可。
<uses-permission android:name="android.permission.INTERNET"/>
4.2在WebView中使用JavaScrpit
在手机客户端,当遇到页面设计比较复杂的情况时,我们可以通过WebView来直接嵌入一个Web页面。WebView对JavaScript具有很好的支持。