通常情况下,每一个需要访问网络的应用程序都会有一个自己的服务器,应用可以向服务器提交数据,也可以从服务器上获取数据。应用(客户端)和服务器之间 的数据传输常见格式有XML和JSON格式。
i.下面是XML格式的一个例子
<apps>
<app>
<id>1id>
<name>Google Mapsname>
<version>1.0version>
app>
<app>
<id>2id>
<name>Chromename>
<version>1.0version>
app>
<app>
<id>3id>
<name>Google Playname>
<version>1.0version>
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 对象表示语法的子集。
-数据在键值对中
-数据由逗号分隔
-花括号保存对象
-方括号保存数组
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>1id>
<name>Google Mapsname>
<version>1.0version>
app>
<app>
<id>2id>
<name>Chromename>
<version>1.0version>
app>
<app>
<id>3id>
<name>Google Playname>
<version>1.0version>
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
,出现如下如下界面,说明数据准备成功:
解析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("http://10.0.2.2/data.xml").build();
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();
}
}
});
}
}
xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.geekp.internet.xml.PullMainActivity">
<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>
运行结果:
从上面的代码中,我们可以看到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 {
}
}
下面来看个例子:
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:[email protected]
*/
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();
}
}
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("http://10.0.2.2/data.xml").build();
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();
}
}
});
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.geekp.internet.xml.SAXainActivity">
<Button
android:id="@+id/btnrequest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请求" />
RelativeLayout>
得到服务器的数据之后,首先创建了一个SAXParserFactory
的实例然后再获取XMLReader
对象,接着将我们编好的DefaultHandler子类设置到XMLReader
中,最后调用parse().
整个工程的源码,请点击这里下载
解析JSon格式的数据通常有JSONObject和GSON两种方式:
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("http://10.0.2.2/data.json")
.build();
try {
Response response = httpclient.newCall(request).execute();
String data = response.body().string();
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();
}
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.geekp.json.JSONObjectMainActivity">
<Button
android:id="@+id/btnsend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请求" />
RelativeLayout>
效果:
由于我们在服务器中定义的是一个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:[email protected]
*/
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;
}
}
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("http://10.0.2.2/data.json")
.build();
try {
Response response = httpclient.newCall(request).execute();
String data = response.body().string();
parseJSonWithGSON(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
private void parseJSonWithGSON(final String data) {
Gson gson = new Gson();
List beanlist = gson.fromJson(data, new TypeToken>() {
}.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());
}
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_gson_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.geekp.json.gson.GsonMainActivity">
<Button
android:id="@+id/btnsendre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请求" />
RelativeLayout>