Android网络编程
sekobe
8年前
<h2>1.XML和JSON格式数据</h2> <p>通常情况下,每一个需要访问网络的应用程序都会有一个自己的服务器,应用可以向服务器提交数据,也可以从服务器上获取数据。应用(客户端)和服务器之间 的数据传输常见格式有XML和JSON格式。</p> <p>i.下面是XML格式的一个例子</p> <pre> <code class="language-java"><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></code></pre> <p>语法如下:</p> <pre> <code class="language-java">a)、任何的起始标签都必须有一个结束标签。 b)、可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<百度百科词条/>。XML解析器会将其翻译成<百度百科词条></百度百科词条>。 c)、标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如这是一串百度百科中的样例字符串。这好比是将起始和结束标签看作是数学中的左右括号:在没有关闭所有的内部括号之前,是不能关闭外面的括号的。 d)、所有的特性都必须有值。 e)、所有的特性都必须在值的周围加上双引号。</code></pre> <p>ii.JSON例子</p> <pre> <code class="language-java">[{"id":"1","version":"1.2","name":"Tom"}, {"id":"2","version":"2.2","name":"Jack"}, {"id":"3","version":"1.6","name":"Tomson"}]</code></pre> <p>语法如下:</p> <pre> <code class="language-java">JSON 语法是 JavaScript 对象表示语法的子集。 -数据在键值对中 -数据由逗号分隔 -花括号保存对象 -方括号保存数组</code></pre> <h2>3.前期准备</h2> <p>i.OKhttp</p> <p>这里使用Square公司的OKHTTP框架,添加依赖:</p> <pre> <code class="language-java">compile 'com.squareup.okhttp3:okhttp:3.6.0'</code></pre> <p>ii.需要联网权限:</p> <pre> <code class="language-java"><uses-permission android:name="android.permission.INTERNET" /></code></pre> <p>iii.Apache http 服务器准备</p> <p>下载: 链接:http://pan.baidu.com/s/1qXZGqmg 密码:rj7x</p> <p>下载得到msi文件,点击安装,安装教程很多,我不赘述了。</p> <p style="text-align: center;">然后再浏览器输入: 127.0.0.1<br> <img src="https://simg.open-open.com/show/76673a259badcca6da07b0a4cbd06af4.png"></p> <p>出现 IT WORKS! 说明服务器安装成功</p> <p>最后是准备数据源:</p> <p>新建data.xml包含数据:</p> <pre> <code class="language-java"><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></code></pre> <p>在浏览器输入 http://127.0.0.1/data.xml ,出现如下如下界面,说明数据准备成功:</p> <p><img src="https://simg.open-open.com/show/114ff4dd1e8695744424b7530f37e4f7.png"></p> <p>新建 data.json:</p> <pre> <code class="language-java">[{"id":"1","version":"1.2","name":"Tom"}, {"id":"2","version":"2.2","name":"Jack"}, {"id":"3","version":"1.6","name":"Tomson"}]</code></pre> <p>在浏览器输入 http://127.0.0.1/data.json ,出现如下如下界面,说明数据准备成功:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/653c5a647a3d23ed719642857cb7143e.png"></p> <h2>4.解析XML</h2> <p>解析XML主要有:PULL解析方法和SAX解析方法。</p> <p>做好前期准备,新建一个项目。</p> <p>i.PULL解析方式:</p> <p>PullMainActivity .java</p> <pre> <code class="language-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(); } } }); } }</code></pre> <p>xml:</p> <pre> <code class="language-java"><?xml version="1.0" encoding="utf-8"?> <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></code></pre> <p>运行结果:</p> <p><img src="https://simg.open-open.com/show/f9cf8d8dbc0fe45dd2b346330819cd03.gif"></p> <p>从上面的代码中,我们可以看到PULL关键的代码是:</p> <pre> <code class="language-java">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(); }</code></pre> <p>首先要获取一个XmlPullParserFactory的实例,并借助这个实例得到XMLPullparser对象,然后调用setInput的方法将服务器返回的数据设置进去就可以开始解析了。</p> <p>ii.SAX解析方式</p> <p>通常需要写一个DefaultHandler的子类并实现下面的五个方法:</p> <pre> <code class="language-java">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> <p>下面来看个例子:</p> <p>ContentHandler .java</p> <pre> <code class="language-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> <p>SAXainActivity .java</p> <pre> <code class="language-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(); } } }); } }</code></pre> <p>xml:</p> <pre> <code class="language-java"><?xml version="1.0" encoding="utf-8"?> <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></code></pre> <p>效果图:</p> <p><img src="https://simg.open-open.com/show/f9cf8d8dbc0fe45dd2b346330819cd03.gif"></p> <p>得到服务器的数据之后,首先创建了一个 SAXParserFactory 的实例然后再获取 XMLReader 对象,接着将我们编好的DefaultHandler子类设置到 XMLReader 中,最后调用parse().</p> <p>整个工程的源码, <a href="/misc/goto?guid=4959748366962184560" rel="nofollow,noindex">请点击这里下载</a></p> <h2>5.解析JSon格式的数据</h2> <p>解析JSon格式的数据通常有JSONObject和GSON两种方式:</p> <h2>i.JSONObject</h2> <pre> <code class="language-java">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(); } } }</code></pre> <p>xml:</p> <pre> <code class="language-java"><?xml version="1.0" encoding="utf-8"?> <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></code></pre> <p>效果:</p> <p><img src="https://simg.open-open.com/show/7a57c2c60abac59b83abf5f32f129fcd.gif"></p> <p>由于我们在服务器中定义的是一个JSon数组,因此我们需要先将返回的数组传到一个JSONArray对象中,然后再遍历这个数组。</p> <p>ii.GSON方式</p> <p>GSON是一个开源库,使用它首先得添加依赖:</p> <pre> <code class="language-java">compile 'com.google.code.gson:gson:2.8.0'</code></pre> <p>Bean.java</p> <pre> <code class="language-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> <p>GsonMainActivity .java</p> <pre> <code class="language-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<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> <p>xml:</p> <pre> <code class="language-java"><?xml version="1.0" encoding="utf-8"?> <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></code></pre> <p>这样也可以成功地解析JSON数据了;</p> <p><img src="https://simg.open-open.com/show/7a57c2c60abac59b83abf5f32f129fcd.gif"></p> <p> </p> <p> </p> <p>来自:http://www.androidchina.net/6554.html</p> <p> </p>