Android网络通信编程

1.网络访问方式

Android SDK提供了一些与网络有关的包。

表1 网络包
描述
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个接口的连接。详细内容如下。

表3 事件处理器
处理器名称处理事件XMLReader注册方法
ContentHandler

与文档内容有关的事件。

(1)文档的开始与结束
(2)xml元素的开始与结束

(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类的一些主要事件回调方法如下表。

表4 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的常用方法如下表。

表5 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具有很好的支持。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值