Android网络技术
一、WebView
webView.getSettings().setJavaScriptEnabled(true); //使webView支持JavaScript脚本
webView.setWebViewClient(new WebViewClient()); //使跳转网页时目标网页仍在WebView中显示,而不打开浏览器
webView.loadUrl("http://www.baidu.com"); //加载网页
二、使用HTTP协议访问网络
1、使用HttpURLConnection
(1)获取HttpURLConnection的实例。
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
(2)设置HTTP请求所使用的方法。常用的方法有GET和POST。
connection.setRequestMethod("GET");
向服务器提交用户名和密码:
connection.setRequestMethod("POST"); DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.writeBytes("username=admin&password=123456");
(3)设置连接超时、读取超时的毫秒数、以及服务器希望得到的一些消息头等。这部分根据需求进行编写。
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
(4)调用getInputStream()方法获取服务器返回的输入流。
InputStream in = connection.getInputStream();
(5)对输入流进行读取
(6)调用disconnect()将这个HTTP连接关闭。
2、使用OkHttp
(1)添加OkHttp库依赖
compile 'com.squareup.okhttp3:okhttp:3.6.0'
(2)创建一个OkHttpClient的实例
OkHttpClient client = new OkHttpClient();
- 发起一条HTTP请求:
(3)创建一个Request对象(在build()方法之前连缀其他方法来丰富这个request对象)
Request request = new Request.Builder().url("http://www.baidu.com").build();
(4)调用OkHttpClient的newCall()方法来创建一个call对象,并调用它的execute()方法来发送请求并获取服务器返回的数据。
Response response = client.newCall(request).execute();
(5)Response对象就是服务器返回的数据。
String responseData = response.body().string();
- 发起一条POST请求:
(3)构建一个RequestBody对象来存放待提交的参数
RequestBody requestBody = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
(4)在Request.Builer中调用post()方法,并将RequestBody对象传入
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(requestBody)
.build();
(5)发送请求并获取服务器返回的数据
Response response = client.newCall(request).execute();
String responseData = response.body().string();
三、解析XML格式数据
1、Pull解析方式
(1)获取XmlPullParserFactory的实例,然后借助这个实例得到XmlPullParser对象。
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
(2)调用XmlPullParser的setInput()方法将服务器返回的XML数据设置进去。
xmlPullParser.setInput(new StringReader(xmlData));
(3)通过getEventType()得到当前的解析事件
int eventType = xmlPullParser.getEventType();
(4)在while中进行解析。如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没完成,该while循环最后调用next()可以获取下一个解析事件。
在while循环中,通过getName()获取当前节点的名字,如果发现结点名为开始标记,就可以调用nextText()方法获取结点内具体的内容。
代码示例:
private void parseXMLWithPull(String responseData) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(responseData));
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
String version = "";
while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if ("id".equals(nodeName)) {
id = xmlPullParser.nextText();
} else if ("name".equals(nodeName)) {
name = xmlPullParser.nextText();
} else if ("version".equals(nodeName)) {
version = xmlPullParser.nextText();
}
break;
case XmlPullParser.END_TAG:
if ("app".equals(nodeName)) {
Log.d("MainActivity", "id is " + id);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "version is " + version);
}
break;
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
2、SAX解析方式
新建一个类继承自DefaultHandler,重写父类的5个方法。其中,startDocument()会在开始XML解析时调用;startElement()会在开始解析某个结点的时候调用;characters()会在获取结点中内容时调用;endElement()会在完成解析某个节点时调用;endDocument()会在完成整个XML解析时调用。
ContentHandler.java
public class ContentHandler extends DefaultHandler{
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
@Override
public void startDocument() throws SAXException {
id = new StringBuilder();
name = new StringBuilder();
version = new StringBuilder();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//记录当前节点名
nodeName = localName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//根据当前节点名判断将内容添加到哪一个StringBuilder对象中
if ("id".equals(nodeName)) {
id.append(ch, start, length);
} else if ("name".equals(nodeName)) {
name.append(ch, start, length);
} else if ("version".equals(nodeName)) {
version.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("app".equals(localName)) {
Log.d("ContentHandler", "id is " + id.toString().trim());
Log.d("ContentHandler", "name is " + name.toString().trim());
Log.d("ContentHandler", "version is " + version.toString().trim());
//最后将StringBuilder清空掉
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}
解析过程:
private void parseXMLWithSAX(String xmlData) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
ContentHandler handler = new ContentHandler();
//将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
//开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
} catch (Exception e) {
e.printStackTrace();
}
}
四、解析JSON格式数据
1、使用JSONObject
private void parseJSONWithJSONObject(String jsonData) {
try {
JSONArray jsonArray = new JSONArray(jsonData);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
String version = jsonObject.getString("version");
Log.d("MainActivity", "id is " + id);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "version is " + version);
}
} catch (Exception e) {
e.printStackTrace();
}
}
2、使用GSON
(1)添加GSON库依赖
compile 'com.google.code.gson:gson:2.7'
(2)
GSON库将一段Json格式的字符串自动映射成一个对象。如一段Json数据:{“name”:”Tom”,”age”:20},解析这一段Json数据,就可以先定义一个Person类,加入name和age两个字段,然后调用如下代码:
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());
实例:
新建App.java:
public class App {
private String id;
private String name;
private String version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
GSON解析Json:
private void parseJSONWithGSON(String jsonData) {
Gson gson = new Gson();
List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>(){}.getType());
for (App app : appList) {
Log.d("MainActivity", "id is " + app.getId());
Log.d("MainActivity", "name is " + app.getName());
Log.d("MainActivity", "version is " + app.getVersion());
}
}
五、Http请求工具类
public class HttpUtils {
public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
StringBuilder response = new StringBuilder();
try {
URL url = new URL(address);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
if (listener != null) {
//回调onFinish()方法
listener.onFinish(response.toString());
}
} catch (Exception e) {
if (listener != null) {
//回调onError()方法
listener.onError(e);
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
public static void sendOkHttpRequest(String address, Callback callback) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.build();
client.newCall(request).enqueue(callback);
}
}
由于如果在以上方法内部不开启子线程可能会造成主线程阻塞,而开启子线程,Http请求方法会在服务器还没来得及响应的时候就执行结束了。所以此处需要利用Java的回调机制。实际使用时代码:
HttpUtils.sendHttpRequest("http://www.baidu.com", new HttpCallbackListener() {
@Override
public void onFinish(String response) {
//在这里根据返回内容执行具体的逻辑
...
}
@Override
public void onError(Exception e) {
//在这里进行异常处理
}
});
HttpUtils.sendOkHttpRequest("http://www.baidu.com", new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//在这里进行异常处理
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//得到服务器返回的具体内容
String responseData = response.body().string();
}
});