Android——网络编程

WebView简单体验——可内嵌在应用程序的浏览器

WebView是一个封装了网络请求,数据解析的这么一个控件,可作为程序的内置浏览器使用

注意声明网络访问权限:android.permission.INTERNET

1     <WebView
2         android:id="@+id/webview"
3         android:layout_width="match_parent"
4         android:layout_height="match_parent" />
 1     protected void onCreate(Bundle savedInstanceState) {
 2         super.onCreate(savedInstanceState);
 3         setContentView(R.layout.activity_main);
 4         WebView webView = (WebView) findViewById(R.id.webview);
 5         // step1 设置支持js
 6         webView.getSettings().setJavaScriptEnabled(true);
 7         // step2 设置客户端本页根据传入的url打开网页,不需要调用系统浏览器
 8         webView.setWebViewClient(new WebViewClient() {
 9
10             @Override
11             public boolean shouldOverrideUrlLoading(WebView view, String url) {
12                 // 根据url访问网络
13                 view.loadUrl(url);
14                 // 设置成true,表示跳转网页时在本页打开
15                 return true;
16             }
17
18         });
19         // 默认访问百度,测试简写不可用
20         webView.loadUrl("http://www.baidu.com");
21         // 注意访问网络需要权限
22     }

http网络请求

方式一:HttpURLConnection

网络请求是比较耗时的操作,如果直接在主线程中使用的话,可能会出现ANR问题,所以通常是要开启一个子线程进行操作的

下面是常见写法,但是存在着一些弊端=》通常应用程序里面网络请求不止一个,所以应当封装成一个工具类,当需要请求的时候,直接用工具类传入地址进行访问

注:用模拟器调试的话,可以开启本地apache服务器,请求 10.0.2.2/xxx.xml

 1     private void sendRequestWithHttpURLConnection() {
 2         // 发送网络请求,必须开启子线程,否则可能阻塞主线程,ANR
 3         new Thread(new Runnable() {
 4
 5             @Override
 6             public void run() {
 7                 // 注意别写成HttpsURLConnection
 8                 HttpURLConnection connection = null;
 9                 try {
10                     // 1.得到HttpURLConnection实例——通过url的open..获得
11                     URL url = new URL("http://www.ytslf.com/get_data.xml");
12                     connection = (HttpURLConnection) url.openConnection();
13
14                     // 2.设置请求方式以及请求延时
15                     connection.setRequestMethod("GET");// GET表示需要从服务器得到数据,POST表示需要向服务器提交数据
16                     connection.setConnectTimeout(8000);
17                     connection.setReadTimeout(8000);
18
19                     // 3.获取InputStream流,读取服务器返回的数据
20                     InputStream in = connection.getInputStream();
21                     BufferedReader bufr = new BufferedReader(
22                             new InputStreamReader(in));
23                     String line = null;
24                     StringBuilder sb = new StringBuilder();
25                     while ((line = bufr.readLine()) != null) {
26                         sb.append(line);
27                     }
28                     // 4.将获取到的数据交给Handler处理
29                     Message msg = new Message();
30                     msg.what = SHOW_RESPONSE;
31                     msg.obj = sb.toString(); // 可以直接传入StringBuilder,但为了统一,传String
32                     handler.sendMessage(msg);
33                 } catch (IOException e) {
34                     e.printStackTrace();
35                 } finally {
36                     if (connection != null) {
37                         // 关闭连接
38                         connection.disconnect();
39                     }
40                 }
41
42             }
43         }).start();
44     }

方式二:HttpClient

HttpClient算是HttpURLConnection的升级版把

 1     private void sendRequestWithHttpClient() {
 2         new Thread(new Runnable() {
 3
 4             @Override
 5             public void run() {
 6                 try {
 7                     // 1.得到HttpClient实例
 8                     HttpClient httpClient = new DefaultHttpClient();
 9                     // 2.发送一个GET请求
10 //                    HttpGet httpGet = new HttpGet("http://www.ytslf.com/get_data.xml");
11                     HttpGet httpGet = new HttpGet("http://www.ytslf.com/get_data.json");
12                     // 通过execute方法执行请求,可以得到服务器反馈的数据,都封装在HttpResponse对象中
13                     HttpResponse httpResponse = httpClient.execute(httpGet);
14
15                     /*
16                      * 发送Post请求较GET复杂,需要提交参数
17                      * 1.新建一个HttpPost对象
18                      * HttpPost httpPost = new HttpPost("http://www.baidu.com");
19                      * 2.通过NameValuePair集合存放需要提交的参数
20                      *  List<NameValuePair> params =
21                      * new ArrayList<NameValuePair>();
22                      * params.add(newBasicNameValuePair("username", "admin"));
23                      * params.add(newBasicNameValuePair("password", "123456"));
24                      * UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8");
25                      * httpPost.setEntity(entity);
26                      * // 之后就和GET一样的操作
27                      * httpClient.execute(httpPost);
28                      */
29                     // 3.接下来就是要得到服务器返回的数据了
30                     if (httpResponse.getStatusLine().getStatusCode() == 200) {
31                         // 如果返回的状态码为200,则表示请求和响应都成功了
32                         HttpEntity httpEntity = httpResponse.getEntity();
33                         String response = EntityUtils.toString(httpEntity,
34                                 "utf-8");
35 //                        /*请求测试
36                         // 将数据发送到Message队列中
37                         Message msg = new Message();
38                         msg.what = SHOW_RESPONSE;
39                         msg.obj = response;
40                         handler.sendMessage(msg);
41 //                        */
42                         // 解析测试——Pull方式
43 //                        Log.d("test", "response ok");
44 //                        parseXMLWithPull(response);
45 //                        Log.d("test", "parse over");
46
47
48                     }
49
50                 } catch (Exception e) {
51                     e.printStackTrace();
52                 }
53             }
54         }).start();
55     }

XML解析

<apps>

  <app>

    <id>1</id>

    <name>Google Maps</name>

    <version>1.0</version>

  </app>

  <app>

    <id>2</id>

    <name>Chrome</name>

    <version>2.1</version>

  </app>

  <app>

    <id>3</id>

    <name>Google Play</name>

    <version>2.3</version>

  </app>

</apps>

方式一:Pull解析

 1     private void parseXMLWithPull(String xmdData){
 2         try {
 3             // 1.获取XML的PULL解析工厂实例
 4             XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
 5             // 2.通过工厂获取XML解析器实例
 6             XmlPullParser xmlPullParser = factory.newPullParser();
 7             // 3.XML解析器设置要解析的XML数据
 8             xmlPullParser.setInput(new StringReader(xmdData));
 9             // go go go!
10             int eventType = xmlPullParser.getEventType();
11             String id = "";
12             String name = "";
13             String version = "";
14
15             // 开始解析
16             while(eventType != XmlPullParser.END_DOCUMENT){
17                 String nodeName = xmlPullParser.getName();
18                 switch (eventType) {
19                 // 开始解析某个节点
20                 case XmlPullParser.START_TAG:
21                     if("id".equals(nodeName)){
22                         id = xmlPullParser.nextText();
23                     }
24                     else if("name".equals(nodeName)){
25                         name = xmlPullParser.nextText();
26                     }
27                     else if ("version".equals(nodeName)) {
28                         version = xmlPullParser.nextText();
29                     }
30                     break;
31
32                 // 完成解析某个节点
33                 case XmlPullParser.END_TAG:
34                     if("app".equals(nodeName)){
35                         Log.d("test", "id:"+id);
36                         Log.d("test", "name:"+name);
37                         Log.d("test", "version:"+version);
38                         responseText.append(id+"::"+name+"::"+version+"\n");
39                     }
40                     break;
41
42                 default:
43                     break;
44                 }
45                 eventType = xmlPullParser.next();// 解析下一个
46             }
47
48
49         } catch (Exception e) {
50             e.printStackTrace();
51         }
52     }

方式二:SAX解析

 1     // SAX解析XML
 2     private void parseXMLWithSAX(String xmlData){
 3         try {
 4             SAXParserFactory factory = SAXParserFactory.newInstance();
 5             XMLReader xmlReader = factory.newSAXParser().getXMLReader();
 6             // 创建自定义的Handler实例
 7             ContentHandler handler = new ContentHandler();
 8             // 将实例设置到XMLReader中
 9             xmlReader.setContentHandler(handler);
10             // 开始解析
11             xmlReader.parse(new InputSource(new StringReader(xmlData)));
12         } catch (Exception e) {
13             e.printStackTrace();
14         }
15     }

 1 package com.example.networktest;
 2
 3 import org.xml.sax.Attributes;
 4 import org.xml.sax.SAXException;
 5 import org.xml.sax.helpers.DefaultHandler;
 6
 7 import android.util.Log;
 8
 9 public class ContentHandler extends DefaultHandler {
10
11     private String nodeName;
12     private StringBuilder id;
13     private StringBuilder name;
14     private StringBuilder version;
15
16     /**
17      * 开始解析xml时调用
18      */
19     @Override
20     public void startDocument() throws SAXException {
21         id = new StringBuilder();
22         name = new StringBuilder();
23         version = new StringBuilder();
24     }
25
26     /**
27      * 开始解析某个节点的时候调用
28      */
29     @Override
30     public void startElement(String uri, String localName, String qName,
31             Attributes attributes) throws SAXException {
32         // 记录当前节点的名字
33         nodeName = localName;
34     }
35
36     /**
37      * 具体解析内容时调用
38      */
39     @Override
40     public void characters(char[] ch, int start, int length)
41             throws SAXException {
42         // TODO Auto-generated method stub
43         if ("id".equals(nodeName)) {
44             id.append(ch, start, length);
45         } else if ("name".equals(nodeName)) {
46             name.append(ch, start, length);
47         } else if ("version".equals(nodeName)) {
48             version.append(ch, start, length);
49         }
50     }
51
52     /**
53      * 解析完某个节点的时候调用
54      */
55     @Override
56     public void endElement(String uri, String localName, String qName)
57             throws SAXException {
58         if("app".equals(localName)){
59             // StringBuilder读取到的内容可能会有多余的空格或换行符等,通过String的trim()方法去掉
60             Log.d("test", "id:"+id.toString().trim());
61             Log.d("test", "name:"+name.toString().trim());
62             Log.d("test", "version:"+version.toString().trim());
63
64             // 清空StringBuilder
65             id.setLength(0);
66             name.setLength(0);
67             version.setLength(0);
68         }
69     }
70
71     /**
72      * xml全部解析完成时调用
73      */
74     @Override
75     public void endDocument() throws SAXException {
76     }
77
78 }

ContentHandler

JSON解析

json格式如:[{"id":"5","name":"hh","version":"2.1"},{……}]

方式一:JSONObject解析

 1     // JSONObject解析json
 2     private void parseJSONWithJSONObject(String jsonData){
 3         try {
 4             JSONArray jsonArray = new JSONArray(jsonData);
 5             for(int i=0;i<jsonArray.length();i++){
 6                 JSONObject jsonObject = jsonArray.getJSONObject(i);
 7                 String id = jsonObject.getString("id");
 8                 String name = jsonObject.getString("name");
 9                 String version = jsonObject.getString("version");
10                 Log.d("test", "id:"+id);
11                 Log.d("test", "name:"+name);
12                 Log.d("test", "version:"+version);
13                 responseText.append(id+"::"+name+"::"+version+"\n");
14             }
15         } catch (Exception e) {
16             e.printStackTrace();
17         }
18     }

方式二:GSON解析

利用GSON解析,需要用到GSON的jar包,将jar包拷贝至项目的libs文件夹即可

利用GSON,可以将json数据直接解析成一个对象,利用该对象就能的到相应的数据,这一点是极好的

例如:要解析{"name":"Tom","age":"20"}

可以定义一个具有name和age字段的Person类,解析如下

Gson gson = new Gson();Person person = gson.fromJson(jsonData,Person.class);

如果解析的是json数组,则需要用到TypeToken,将期望解析成的数据类型传入到fromJson的参数当中

List<Person> people = gson.fromJson(jsonData,new TypeToken<List<Person>>(){}.getType());

解析:

[{"id":"5","version":"5.5","name":"Angry Birds"},
{"id":"6","version":"7.0","name":"Clash of Clans"},
{"id":"7","version":"3.5","name":"Hey Day"}]

 1 package com.example.networktest;
 2
 3 public class App {
 4     private String id;
 5     private String name;
 6     private String version;
 7
 8     public String getId() {
 9         return id;
10     }
11
12     public void setId(String id) {
13         this.id = id;
14     }
15
16     public String getName() {
17         return name;
18     }
19
20     public void setName(String name) {
21         this.name = name;
22     }
23
24     public String getVersion() {
25         return version;
26     }
27
28     public void setVersion(String version) {
29         this.version = version;
30     }
31
32 }

App.java

 1     // GSON第三方jar包解析json
 2     private void parseJSONWithGSON(String jsonData){
 3         try {
 4             Gson gson = new Gson();
 5             List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>() {}.getType());
 6             for(App app : appList){
 7                 String id = app.getId();
 8                 String name = app.getName();
 9                 String version = app.getVersion();
10                 Log.d("test", "id:"+id);
11                 Log.d("test", "name:"+name);
12                 Log.d("test", "version:"+version);
13 //                responseText.append(id+"::"+name+"::"+version+"\n");
14             }
15         } catch (Exception e) {
16             e.printStackTrace();
17         }
18     }

 

Http请求的最佳写法:封装为工具类+利用Java回调监听机制

1.封装,定义一个HttpUtil工具类,将请求的代码封装成静态方法,且需要传入网络地址作为参数

 1 public class HttpUtil {
 2     public static String sendHttpRequest(String address) {
 3         HttpURLConnection connection = null;
 4         try {
 5             return null;
 6         } catch (Exception e) {
 7             // TODO: handle exception
 8             return null;
 9         } finally {
10             if (connection != null) {
11                 connection.disconnect();
12             }
13         }
14     }
15 }

细节暂时不写……

这样封装了之后,就可以愉快的调用了

String response = HttpUtil.sendHttpRequest("http://www.baidu.com");

但是仍然存在问题:

1.没有开启线程,则仍然默认是在主线程中执行网络请求,可能导致主线程阻塞

2.如果开启线程,

时间: 2024-10-13 15:09:32

Android——网络编程的相关文章

Android网络编程网上文章总结

关于网络编程,网上也有许多好的文章,这里我就选了几篇觉得不错的归纳到了一起,仅供参考 Android网络编程概述 首先,应该了解的几个问题: 1)Android平台网络相关API接口 a) java.net.*(标准Java接口) java.net.*提供与联网有关的类,包括流.数据包套接字(socket).Internet协议.常见Http处理等.比如:创建URL,以及URLConnection/HttpURLConnection对象.设置链接参数.链接到服务器.向服务器写数据.从服务器读取数

Android网络编程系列 一 TCP/IP协议族

在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必要进一步的了解,这就要我们了解网络通信层了,提到网络通信层不得不说起ISO-OSI的七层协议经典架构,如图所示: 上图的左边部分就是osi架构模型了, ISO/OSI模型,即开放式通信系统互联参考模型(Open System Interconnection Reference Model),是国际标

漫谈Android网络编程

Android从业者,十之八九都是在做网络应用,不是互联网也是局域网.如今在4G和Wifi的天下下,流量什么的都已是浮云,单机应用的市场已然悄悄的一去不复返了.所以呢,不了解网络请求的同学要小心了,当心被时代的大浪一个浪头排在沙滩上. Android实现网络编程有HTTP.也有Socket.HTTP协议是应用层协议,主要解决如何包装数据,网络应用都会用到的协议:Socket是TCP/IP协议的封装,主要解决数据如何在网络中传输,常用于与服务器保持长连接,一般用于广告推送.实时聊天.在线游戏等.

Android网络编程(一)---Socket基础

Socket通常称为""套接字.Socket字面上的中文意思为"插座".一台服务器可能会提供很多服务,每种服务对应一个Socket,而客户的"插头"也是一个Socket.Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.Socket把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议.Socket用于描述IP地址和端口,是一个通信链的句柄.应

Android网络编程之使用HttpClient批量上传文件

请尊重他人的劳动成果,转载请注明出处:Android网络编程之使用HttpClient批量上传文件 我曾在<Android网络编程之使用HTTP访问网络资源>一文中介绍过HttpCient的使用,这里就不在累述了,感兴趣的朋友可以去看一下.在这里主要介绍如何通过HttpClient实现文件上传. 1.预备知识: 在HttpCient4.3之前上传文件主要使用MultipartEntity这个类,但现在这个类已经不在推荐使用了.随之替代它的类是MultipartEntityBuilder. 下面

Android网络编程系列 一 Socket抽象层

在<Android网络编程>系列文章中,前面已经将Java的通信底层大致的描述了,在我们了解了TCP/IP通信族架构及其原理,接下来我们就开始来了解基于tcp/ip协议层的Socket抽象层.本篇文章将会让我们清楚的了解和学会使用Socket. 什么是Socket?它又是如何运作的?它的表现形式是什么?等等这些问题,本篇文章将逐步的揭晓. 一. 什么是Socket Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,你可以借助它建立TCP连接等等,而http是个应用层的

Android网络编程(一)HTTP协议原理

相关文章 Android网络编程(一)HTTP协议原理 Android网络编程(二)HttpClient与HttpURLConnection Android网络编程(三)Volley使用方法全解析 Android网络编程(四)从源代码解析volley Android网络编程(五)OkHttp2.x使用方法全解析 Android网络编程(六)OkHttp3使用方法全解析 Android网络编程(七)源代码解析OkHttp前篇[请求网络] Android网络编程(八)源代码解析OkHttp后篇[复用

Android网络编程(1)

本系列文章对整个Android网络编程进行了总结,包括基本的TCP/IP协议,HTTP协议,HTTPS协议,HttpClient,UrlConnection,一些网络通信的库到棉花糖新加入的OKHTTP. 本文主要对TCP协议的连接管理和拥塞控制两部分知识进行总结. 连接管理 TCP协议是传输层的重要协议,负责端到端的通信.为了实现面向连接的可靠传输,TCP协议使用“三次握手”和“四次挥手”的方式来创建连接,结束连接. 三次握手: 第一次握手:建立连接时,客户端C发起建立连接请求(SYN=1)到

Android网络编程之传递数据给服务器(二)

Android网络编程之传递数据给服务器(二) 请尊重他人的劳动成果,转载请注明出处:Android网络编程之传递数据给服务器(二) 我曾在<Android网络编程之传递数据给服务器(一)> 一文中介绍了如何通过GET方式传递数据给服务器,通过GET方式传递数据主要适用于数据大小不超过2KB,且对安全性要求不高的情况下.下面就介绍通过POST方式传递数据主到服务器. 一.通过Post方式传递数据给服务器 通过Post方式传递数据给服务器是Android应用程序开发提交数据给服务器的一种主要的方

Android网络编程之传递数据给服务器(一)

Android网络编程之传递数据给服务器(一) 请尊重他人的劳动成果,转载请注明出处:Android网络编程之传递数据给服务器(一) 因为Android程序需要和服务器进行通信,所以需要服务器端提供的支持. 一.通过GET方式传递数据给服务器 通过GET方式上传数据主要适用于数据大小不超过2KB,且对安全性要求不高的情况下. 1.创建服务器端: 服务器端项目结构: 第一步:创建控制器Servlet package com.jph.sgm.servlet; import java.io.IOExc