Android網絡編程
1.XML和JSON格式數據
通常情況下,每一個需要訪問網絡的應用程序都會有一個自己的服務器,應用可以向服務器提交數據,也可以從服務器上獲取數據。應用(客戶端)和服務器之間 的數據傳輸常見格式有XML和JSON格式。
i.下面是XML格式的一個例子
<apps>
<app>
<id>1</id>
<name>Google Maps</name>
<version>1.0</version>
</app>
<app>
<id>2</id>
<name>Chrome</name>
<version>1.0</version>
</app>
<app>
<id>3</id>
<name>Google Play</name>
<version>1.0</version>
</app>
</apps>
語法如下:
a)、任何的起始標簽都必須有一個結束標簽。
b)、可以采用另一種簡化語法,可以在一個標簽中同時表示起始和結束標簽。這種語法是在大于符號之前緊跟一個斜線(/),例如<百度百科詞條/>。XML解析器會將其翻譯成<百度百科詞條></百度百科詞條>。
c)、標簽必須按合適的順序進行嵌套,所以結束標簽必須按鏡像順序匹配起始標簽,例如這是一串百度百科中的樣例字符串。這好比是將起始和結束標簽看作是數學中的左右括號:在沒有關閉所有的內部括號之前,是不能關閉外面的括號的。
d)、所有的特性都必須有值。
e)、所有的特性都必須在值的周圍加上雙引號。
ii.JSON例子
[{"id":"1","version":"1.2","name":"Tom"},
{"id":"2","version":"2.2","name":"Jack"},
{"id":"3","version":"1.6","name":"Tomson"}]
語法如下:
JSON 語法是 JavaScript 對象表示語法的子集。
-數據在鍵值對中
-數據由逗號分隔
-花括號保存對象
-方括號保存數組
3.前期準備
i.OKhttp
這里使用Square公司的OKHTTP框架,添加依賴:
compile 'com.squareup.okhttp3:okhttp:3.6.0'
ii.需要聯網權限:
<uses-permission android:name="android.permission.INTERNET" />
iii.Apache http 服務器準備
下載: 鏈接:http://pan.baidu.com/s/1qXZGqmg 密碼:rj7x
下載得到msi文件,點擊安裝,安裝教程很多,我不贅述了。
然后再瀏覽器輸入: 127.0.0.1
出現 IT WORKS! 說明服務器安裝成功
最后是準備數據源:
新建data.xml包含數據:
<apps>
<app>
<id>1</id>
<name>Google Maps</name>
<version>1.0</version>
</app>
<app>
<id>2</id>
<name>Chrome</name>
<version>1.0</version>
</app>
<app>
<id>3</id>
<name>Google Play</name>
<version>1.0</version>
</app>
</apps>
在瀏覽器輸入 http://127.0.0.1/data.xml ,出現如下如下界面,說明數據準備成功:
新建 data.json:
[{"id":"1","version":"1.2","name":"Tom"},
{"id":"2","version":"2.2","name":"Jack"},
{"id":"3","version":"1.6","name":"Tomson"}]
在瀏覽器輸入 http://127.0.0.1/data.json ,出現如下如下界面,說明數據準備成功:
4.解析XML
解析XML主要有:PULL解析方法和SAX解析方法。
做好前期準備,新建一個項目。
i.PULL解析方式:
PullMainActivity .java
package com.example.geekp.internet.xml;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;
import com.example.geekp.internet.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class PullMainActivity extends AppCompatActivity {
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.response_text);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendRequest();
}
});
}
private void sendRequest() {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient httpclient = new OkHttpClient();
// 10.0.2.2對于模擬器來講就是PC的IP地址
Request request = new Request.Builder().url(");
try {
Response response = httpclient.newCall(request).execute();
String bulider = response.body().string();
parseXMLWithPull(bulider);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void parseXMLWithPull(final String builder) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(builder));
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
String version = "";
while (XmlPullParser.END_DOCUMENT != eventType) {
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)) {
System.out.println(id);
System.out.println(name);
System.out.println(version);
Toast.makeText(getApplicationContext(),"id is:"+id+" name is:"+name+" version is:"+version,Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}</code></pre>
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send request" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/response_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout></code></pre>
運行結果:

從上面的代碼中,我們可以看到PULL關鍵的代碼是:
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(builder));
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
String version = "";
while (XmlPullParser.END_DOCUMENT != eventType) {
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)) {
System.out.println(id);
System.out.println(name);
System.out.println(version);
Toast.makeText(getApplicationContext(),"id is:"+id+" name is:"+name+" version is:"+version,Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
eventType = xmlPullParser.next();
}
首先要獲取一個XmlPullParserFactory的實例,并借助這個實例得到XMLPullparser對象,然后調用setInput的方法將服務器返回的數據設置進去就可以開始解析了。
ii.SAX解析方式
通常需要寫一個DefaultHandler的子類并實現下面的五個方法:
class MH extends DefaultHandler {
//開始解析XML時調用
@Override
public void startDocument() throws SAXException {
}
//開始解析某個結點的時候調用
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
}
//獲取結點中的內容調用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
}
//完成解析某個結點的時候調用
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
}
//完成整個xml的時候調用
@Override
public void endDocument() throws SAXException {
}
}</code></pre>
下面來看個例子:
ContentHandler .java
package com.example.geekp.internet.xml;
//import jdk.internal.org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
- Created by geekp on 2017/2/24.
- Email:810275469@qq.com
*/
public class ContentHandler extends DefaultHandler {
private StringBuffer id;
private StringBuilder name;
private StringBuilder version;
private String nodeName;
@Override
public void startDocument() throws SAXException {
id=new StringBuffer();
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 {
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))
{
System.out.println("id is: "+id.toString().trim());
System.out.println("name is :" +name.toString().trim());
System.out.println("version is :"+version.toString().trim());
//最后要stringbuilder清空
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}</code></pre>
SAXainActivity .java
package com.example.geekp.internet.xml;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.example.geekp.internet.R;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class SAXainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
button=(Button)findViewById(R.id.btnrequest);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendRequestwithOkhttp();
}
});
}
private void sendRequestwithOkhttp() {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient httpclient = new OkHttpClient();
// 10.0.2.2對于模擬器來講就是PC的IP地址
Request request = new Request.Builder().url(");
try {
Response response = httpclient.newCall(request).execute();
String data = response.body().string();
parseXMLWithSAX(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void parseXMLWithSAX(final String data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
SAXParserFactory factory=SAXParserFactory.newInstance();
try {
XMLReader reader=factory.newSAXParser().getXMLReader();
ContentHandler contentHandler=new ContentHandler();
//將contentHandler的實例設置到XMLreader中
reader.setContentHandler(contentHandler);
reader.parse(new InputSource(new StringReader(data)));
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}</code></pre>
xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="
<Button
android:id="@+id/btnrequest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="請求" />
</RelativeLayout></code></pre>
效果圖:

得到服務器的數據之后,首先創建了一個 SAXParserFactory 的實例然后再獲取 XMLReader 對象,接著將我們編好的DefaultHandler子類設置到 XMLReader 中,最后調用parse().
整個工程的源碼, 請點擊這里下載
5.解析JSon格式的數據
解析JSon格式的數據通常有JSONObject和GSON兩種方式:
i.JSONObject
package com.example.geekp.json;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class JSONObjectMainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.btnsend);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendRequestwithOkhttp();
}
});
}
private void sendRequestwithOkhttp() {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient httpclient = new OkHttpClient();
// 10.0.2.2對于模擬器來講就是PC的IP地址
Request request = new Request.Builder()
.url("
parseJSonWithJsonObject(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void parseJSonWithJsonObject(final String data) {
try {
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
System.out.println("id is:" + object.getString("id"));
System.out.println("name is :" + object.getString("name"));
System.out.println("version is:" + object.getString("version"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}</code></pre>
xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="
<Button
android:id="@+id/btnsend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="請求" />
</RelativeLayout></code></pre>
效果:

由于我們在服務器中定義的是一個JSon數組,因此我們需要先將返回的數組傳到一個JSONArray對象中,然后再遍歷這個數組。
ii.GSON方式
GSON是一個開源庫,使用它首先得添加依賴:
compile 'com.google.code.gson:gson:2.8.0'
Bean.java
package com.example.geekp.json.gson;
/**
- Created by geekp on 2017/2/24.
- Email:810275469@qq.com
*/
public class Bean {
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;
}
}</code></pre>
GsonMainActivity .java
package com.example.geekp.json.gson;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.example.geekp.json.R;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.List;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class GsonMainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gson_main);
button = (Button) findViewById(R.id.btnsendre);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendRequestwithOkhttp();
}
});
}
private void sendRequestwithOkhttp() {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient httpclient = new OkHttpClient();
// 10.0.2.2對于模擬器來講就是PC的IP地址
Request request = new Request.Builder()
.url("
private void parseJSonWithGSON(final String data) {
Gson gson = new Gson();
List<Bean> beanlist = gson.fromJson(data, new TypeToken<List<Bean>>() {
}.getType());
for(Bean bean:beanlist)
{
System.out.println("id is :"+bean.getId());
System.out.println("name is:"+bean.getName());
System.out.println("vesrsion is :"+bean.getVersion());
}
}
}</code></pre>
xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="
<Button
android:id="@+id/btnsendre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="請求" />
</RelativeLayout></code></pre>
這樣也可以成功地解析JSON數據了;

來自:http://www.androidchina.net/6554.html