android执行网络操作



本篇我们会介绍连接到网络中涉及的基本任务,监测的网络连接(包括连接更改),并给予用户控制应用程序的网络使用情况。还介绍了如何解析和使用XML数据。

这个类包含一个示例应用程序来说明如何执行常见的网络操作。您可以下载示例(在右边),并用它作为自己的应用程序源代码的可重用代码。本章的重点有三:

1.连接到网络

2.管理网络的使用

3.解析XML数据

 

一、连接到网络

在mainfest中声明权限,代码如下:

 

Java代码 
  1. <uses-permission android:name="android.permission.INTERNET" />  
  2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
 

选择http客户端

大多数联网的Android应用程序使用HTTP来发送和接收数据。Android包括两个HTTP客户:HttpURLConnection HttpClient和Apache。都支持HTTPS,流媒体上传和下载,可配置的超时,IPv6,和连接池。我们建议使用HttpURLConnection目标应用程序。

检查网络连接

在你的应用程序尝试连接到网络,它应该检查是否一个网络连接可用使用getActiveNetworkInfo()和一个()。记住,这个装置可能范围的一个网络,或用户可能已经禁用wi - fi和移动数据访问。

 

Java代码 
  1. public void myClickHandler(View view) {  
  2.     ...  
  3.     ConnectivityManager connMgr = (ConnectivityManager)   
  4.         getSystemService(Context.CONNECTIVITY_SERVICE);  
  5.     NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();  
  6.     if (networkInfo != null && networkInfo.isConnected()) {  
  7.         // fetch data  
  8.     } else {  
  9.         // display error  
  10.     }  
  11.     ...  
  12. }  
 

在单独线程中执行网络操作

网络操作可以包括不可预测的延迟。为了防止这种导致一个糟糕的用户体验,总是执行网络操作在一个单独的线程。

 

Java代码 
  1. public class HttpExampleActivity extends Activity {  
  2.     private static final String DEBUG_TAG = "HttpExample";  
  3.     private EditText urlText;  
  4.     private TextView textView;  
  5.       
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);     
  10.         urlText = (EditText) findViewById(R.id.myUrl);  
  11.         textView = (TextView) findViewById(R.id.myText);  
  12.     }  
  13. // When user clicks button, calls AsyncTask.  
  14.     // Before attempting to fetch the URL, makes sure that there is a network connection.  
  15.     public void myClickHandler(View view) {  
  16.         // Gets the URL from the UI's text field.  
  17.         String stringUrl = urlText.getText().toString();  
  18.         ConnectivityManager connMgr = (ConnectivityManager)   
  19.             getSystemService(Context.CONNECTIVITY_SERVICE);  
  20.         NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();  
  21.         if (networkInfo != null && networkInfo.isConnected()) {  
  22.             new DownloadWebpageText().execute(stringUrl);  
  23.         } else {  
  24.             textView.setText("No network connection available.");  
  25.         }  
  26.     }  
  27. // Uses AsyncTask to create a task away from the main UI thread. This task takes a   
  28.      // URL string and uses it to create an HttpUrlConnection. Once the connection  
  29.      // has been established, the AsyncTask downloads the contents of the webpage as  
  30.      // an InputStream. Finally, the InputStream is converted into a string, which is  
  31.      // displayed in the UI by the AsyncTask's onPostExecute method.  
  32.      private class DownloadWebpageText extends AsyncTask {  
  33.         @Override  
  34.         protected String doInBackground(String... urls) {  
  35.                 
  36.             // params comes from the execute() call: params[0] is the url.  
  37.             try {  
  38.                 return downloadUrl(urls[0]);  
  39.             } catch (IOException e) {  
  40.                 return "Unable to retrieve web page. URL may be invalid.";  
  41.             }  
  42.         }  
  43.         // onPostExecute displays the results of the AsyncTask.  
  44.         @Override  
  45.         protected void onPostExecute(String result) {  
  46.             textView.setText(result);  
  47.        }  
  48.     }  
  49.     ...  
  50. }  
 

连接和下载数据

在你的线程执行您的网络交易,你可以使用HttpURLConnection来执行一个GET和下载数据。在您调用connect(),你可以得到一个InputStream的数据通过调用getInputStream()。

 

Java代码 
  1. // Given a URL, establishes an HttpUrlConnection and retrieves  
  2. // the web page content as a InputStream, which it returns as  
  3. // a string.  
  4. private String downloadUrl(String myurl) throws IOException {  
  5.     InputStream is = null;  
  6.     // Only display the first 500 characters of the retrieved  
  7.     // web page content.  
  8.     int len = 500;  
  9.           
  10.     try {  
  11.         URL url = new URL(myurl);  
  12.         HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  13.         conn.setReadTimeout(10000 /* milliseconds */);  
  14.         conn.setConnectTimeout(15000 /* milliseconds */);  
  15.         conn.setRequestMethod("GET");  
  16.         conn.setDoInput(true);  
  17.         // Starts the query  
  18.         conn.connect();  
  19.         int response = conn.getResponseCode();  
  20.         Log.d(DEBUG_TAG, "The response is: " + response);  
  21.         is = conn.getInputStream();  
  22. // Convert the InputStream into a string  
  23.         String contentAsString = readIt(is, len);  
  24.         return contentAsString;  
  25.           
  26.     // Makes sure that the InputStream is closed after the app is  
  27.     // finished using it.  
  28.     } finally {  
  29.         if (is != null) {  
  30.             is.close();  
  31.         }   
  32.     }  
  33. }  
 

getResponseCode()返回连接的状态码。这是一种有用的方式获得一些额外的信息的连接。一个200的状态代码表示成功。

转换InputStreamString

 

Java代码 
  1. // Reads an InputStream and converts it to a String.  
  2. public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {  
  3.     Reader reader = null;  
  4.     reader = new InputStreamReader(stream, "UTF-8");          
  5.     char[] buffer = new char[len];  
  6.     reader.read(buffer);  
  7.     return new String(buffer);  
  8. }  
 

 

 

二、管理网络

检查设备的网络连接

一个设备可以有各种类型的网络连接。这节课的重点是使用wi - fi或手机或网络连接,这个代码片段测试网络连接wi - fi和移动。它确定这些网络接口是可用的或连接的(即网络连接是否存在,如果可以建立套接字和传递数据)

 

Java代码 
  1. private static final String DEBUG_TAG = "NetworkStatusExample";  
  2. ...        
  3. ConnectivityManager connMgr = (ConnectivityManager)   
  4.         getSystemService(Context.CONNECTIVITY_SERVICE);  
  5. NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);   
  6. boolean isWifiConn = networkInfo.isConnected();  
  7. networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);  
  8. boolean isMobileConn = networkInfo.isConnected();  
  9. Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);  
  10. Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);  
 

管理网络的使用

您可以实现一个首选项活动,让用户明确控制应用程序的使用网络资源。例如: 1.你可能允许用户上传的视频只有当设备被连接到wi - fi网络。2.你可能会同步(或没有)根据特定标准如网络可用性、时间间隔,等等。

编写一个应用程序,支持网络访问和管理网络的使用,你的清单必须有正确的权限和意图过滤器。

在样例应用程序中,这个规定了SettingsActivity,将显示一个UI让用户知道何时可以进行下载操作。

 

Xml代码 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.android.networkusage"  
  4.     ...>  
  5. <uses-sdk android:minSdkVersion="4"   
  6.            android:targetSdkVersion="14" />  
  7.           
  8.     <uses-permission android:name="android.permission.INTERNET" />  
  9.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  10. <application  
  11.         ...>  
  12.         ...  
  13.         <activity android:label="SettingsActivity" android:name=".SettingsActivity">  
  14.              <intent-filter>  
  15.                 <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />  
  16.                 <category android:name="android.intent.category.DEFAULT" />  
  17.           </intent-filter>  
  18.         </activity>  
  19.     </application>  
  20. </manifest>  
 

 

 

Java代码 
  1. public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {  
  2.       
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.           
  7.         // Loads the XML preferences file  
  8.         addPreferencesFromResource(R.xml.preferences);  
  9.     }  
  10.     
  11.     @Override  
  12.     protected void onResume() {  
  13.         super.onResume();  
  14. // Registers a listener whenever a key changes              
  15.         getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);  
  16.     }  
  17.     
  18.     @Override  
  19.     protected void onPause() {  
  20.         super.onPause();  
  21. // Unregisters the listener set in onResume().  
  22.        // It's best practice to unregister listeners when your app isn't using them to cut down on   
  23.        // unnecessary system overhead. You do this in onPause().              
  24.        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);      
  25.     }  
  26.     
  27.     // When the user changes the preferences selection,   
  28.     // onSharedPreferenceChanged() restarts the main activity as a new  
  29.     // task. Sets the the refreshDisplay flag to "true" to indicate that   
  30.     // the main activity should update its display.  
  31.     // The main activity queries the PreferenceManager to get the latest settings.  
  32.       
  33.     @Override  
  34.     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {      
  35.         // Sets refreshDisplay to true so that when the user returns to the main  
  36.         // activity, the display refreshes to reflect the new settings.  
  37.         NetworkActivity.refreshDisplay = true;  
  38.     }  
  39. }  
 

 

响应网络变动

如果有一个匹配发生在设置和设备的网络连接(例如,如果设置为“wi - fi”和设备有一个wi - fi连接)之间,应用程序下载提继续并刷新显示

 

Java代码 
  1. public class NetworkActivity extends Activity {  
  2.     public static final String WIFI = "Wi-Fi";  
  3.     public static final String ANY = "Any";  
  4.     private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";  
  5.      
  6.     // Whether there is a Wi-Fi connection.  
  7.     private static boolean wifiConnected = false;   
  8.     // Whether there is a mobile connection.  
  9.     private static boolean mobileConnected = false;  
  10.     // Whether the display should be refreshed.  
  11.     public static boolean refreshDisplay = true;  
  12.       
  13.     // The user's current network preference setting.  
  14.     public static String sPref = null;  
  15.       
  16.     // The BroadcastReceiver that tracks network connectivity changes.  
  17.     private NetworkReceiver receiver = new NetworkReceiver();  
  18.       
  19.     @Override  
  20.     public void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.           
  23.         // Registers BroadcastReceiver to track network connection changes.  
  24.         IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);  
  25.         receiver = new NetworkReceiver();  
  26.         this.registerReceiver(receiver, filter);  
  27.     }  
  28.       
  29.     @Override   
  30.     public void onDestroy() {  
  31.         super.onDestroy();  
  32.         // Unregisters BroadcastReceiver when app is destroyed.  
  33.         if (receiver != null) {  
  34.             this.unregisterReceiver(receiver);  
  35.         }  
  36.     }  
  37.       
  38.     // Refreshes the display if the network connection and the  
  39.     // pref settings allow it.  
  40.       
  41.     @Override  
  42.     public void onStart () {  
  43.         super.onStart();    
  44.           
  45.         // Gets the user's network preference settings  
  46.         SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);  
  47.           
  48.         // Retrieves a string value for the preferences. The second parameter  
  49.         // is the default value to use if a preference value is not found.  
  50.         sPref = sharedPrefs.getString("listPref""Wi-Fi");  
  51. updateConnectedFlags();   
  52.          
  53.         if(refreshDisplay){  
  54.             loadPage();      
  55.         }  
  56.     }  
  57.       
  58.     // Checks the network connection and sets the wifiConnected and mobileConnected  
  59.     // variables accordingly.   
  60.     public void updateConnectedFlags() {  
  61.         ConnectivityManager connMgr = (ConnectivityManager)   
  62.                 getSystemService(Context.CONNECTIVITY_SERVICE);  
  63.           
  64.         NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();  
  65.         if (activeInfo != null && activeInfo.isConnected()) {  
  66.             wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;  
  67.             mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;  
  68.         } else {  
  69.             wifiConnected = false;  
  70.             mobileConnected = false;  
  71.         }    
  72.     }  
  73.         
  74.     // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.  
  75.     public void loadPage() {  
  76.         if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))  
  77.                 || ((sPref.equals(WIFI)) && (wifiConnected))) {  
  78.             // AsyncTask subclass  
  79.             new DownloadXmlTask().execute(URL);  
  80.         } else {  
  81.             showErrorPage();  
  82.         }  
  83.     }  
  84. ...  
  85.       
  86. }  
 

检测网络连接变化

 

Java代码 
  1. public class NetworkReceiver extends BroadcastReceiver {     
  2.         
  3. @Override  
  4. public void onReceive(Context context, Intent intent) {  
  5.     ConnectivityManager conn =  (ConnectivityManager)  
  6.         context.getSystemService(Context.CONNECTIVITY_SERVICE);  
  7.     NetworkInfo networkInfo = conn.getActiveNetworkInfo();  
  8.          
  9.     // Checks the user prefs and the network connection. Based on the result, decides whether  
  10.     // to refresh the display or keep the current display.  
  11.     // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.  
  12.     if (WIFI.equals(sPref) && networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {  
  13.         // If device has its Wi-Fi connection, sets refreshDisplay  
  14.         // to true. This causes the display to be refreshed when the user  
  15.         // returns to the app.  
  16.         refreshDisplay = true;  
  17.         Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();  
  18. // If the setting is ANY network and there is a network connection  
  19.     // (which by process of elimination would be mobile), sets refreshDisplay to true.  
  20.     } else if (ANY.equals(sPref) && networkInfo != null) {  
  21.         refreshDisplay = true;  
  22.                    
  23.     // Otherwise, the app can't download content--either because there is no network  
  24.     // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there   
  25.     // is no Wi-Fi connection.  
  26.     // Sets refreshDisplay to false.  
  27.     } else {  
  28.         refreshDisplay = false;  
  29.         Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();  
  30.     }  
  31. }  
 

 

三、解析xml

上传和解析XML数据是很常见的任务,网络连接应用程序。这一课解释了如何解析XML文档并使用他们的数据

选择转换器

我们建议XmlPullParser,这是一种高效且可维护的方式来解析XML在Android里。

分析需求

 

Xml代码 
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" ...">       
  3. <title type="text">newest questions tagged android - Stack Overflow</title>  
  4. ...  
  5.     <entry>  
  6.     ...  
  7.     </entry>  
  8.     <entry>  
  9.         <id>http://stackoverflow.com/q/9439999</id>  
  10.         <re:rank scheme="http://stackoverflow.com">0</re:rank>  
  11.         <title type="text">Where is my data file?</title>  
  12.         <category scheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags" term="android"/>  
  13.         <category scheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags" term="file"/>  
  14.         <author>  
  15.             <name>cliff2310</name>  
  16.             <uri>http://stackoverflow.com/users/1128925</uri>  
  17.         </author>  
  18.         <link rel="alternate" href="http://stackoverflow.com/questions/9439999/where-is-my-data-file" />  
  19.         <published>2012-02-25T00:30:54Z</published>  
  20.         <updated>2012-02-25T00:30:54Z</updated>  
  21.         <summary type="html">  
  22.             <p>I have an Application that requires a data file...</p>  
  23. </summary>  
  24.     </entry>  
  25.     <entry>  
  26.     ...  
  27.     </entry>  
  28. ...  
  29. </feed>  
 

实例化转化器

 

Java代码 
  1. public class StackOverflowXmlParser {  
  2.     // We don't use namespaces  
  3.     private static final String ns = null;  
  4.      
  5.     public List parse(InputStream in) throws XmlPullParserException, IOException {  
  6.         try {  
  7.             XmlPullParser parser = Xml.newPullParser();  
  8.             parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);  
  9.             parser.setInput(in, null);  
  10.             parser.nextTag();  
  11.             return readFeed(parser);  
  12.         } finally {  
  13.             in.close();  
  14.         }  
  15.     }  
  16.  ...   
  17. }  
  18. 读取xml  
  19. private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {  
  20.     List entries = new ArrayList();  
  21. parser.require(XmlPullParser.START_TAG, ns, "feed");  
  22.     while (parser.next() != XmlPullParser.END_TAG) {  
  23.         if (parser.getEventType() != XmlPullParser.START_TAG) {  
  24.             continue;  
  25.         }  
  26.         String name = parser.getName();  
  27.         // Starts by looking for the entry tag  
  28.         if (name.equals("entry")) {  
  29.             entries.add(readEntry(parser));  
  30.         } else {  
  31.             skip(parser);  
  32.         }  
  33.     }    
  34.     return entries;  
  35. }  
 

 

下面这个代码片段展示了如何解析器解析条目、标题、链接和总结:

 

Java代码 
  1. public static class Entry {  
  2.     public final String title;  
  3.     public final String link;  
  4.     public final String summary;  
  5. private Entry(String title, String summary, String link) {  
  6.         this.title = title;  
  7.         this.summary = summary;  
  8.         this.link = link;  
  9.     }  
  10. }  
  11.     
  12. // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off  
  13. // to their respective "read" methods for processing. Otherwise, skips the tag.  
  14. private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {  
  15.     parser.require(XmlPullParser.START_TAG, ns, "entry");  
  16.     String title = null;  
  17.     String summary = null;  
  18.     String link = null;  
  19.     while (parser.next() != XmlPullParser.END_TAG) {  
  20.         if (parser.getEventType() != XmlPullParser.START_TAG) {  
  21.             continue;  
  22.         }  
  23.         String name = parser.getName();  
  24.         if (name.equals("title")) {  
  25.             title = readTitle(parser);  
  26.         } else if (name.equals("summary")) {  
  27.             summary = readSummary(parser);  
  28.         } else if (name.equals("link")) {  
  29.             link = readLink(parser);  
  30.         } else {  
  31.             skip(parser);  
  32.         }  
  33.     }  
  34.     return new Entry(title, summary, link);  
  35. }  
  36. // Processes title tags in the feed.  
  37. private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {  
  38.     parser.require(XmlPullParser.START_TAG, ns, "title");  
  39.     String title = readText(parser);  
  40.     parser.require(XmlPullParser.END_TAG, ns, "title");  
  41.     return title;  
  42. }  
  43.     
  44. // Processes link tags in the feed.  
  45. private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException {  
  46.     String link = "";  
  47.     parser.require(XmlPullParser.START_TAG, ns, "link");  
  48.     String tag = parser.getName();  
  49.     String relType = parser.getAttributeValue(null"rel");    
  50.     if (tag.equals("link")) {  
  51.         if (relType.equals("alternate")){  
  52.             link = parser.getAttributeValue(null"href");  
  53.             parser.nextTag();  
  54.         }   
  55.     }  
  56.     parser.require(XmlPullParser.END_TAG, ns, "link");  
  57.     return link;  
  58. }  
  59. // Processes summary tags in the feed.  
  60. private String readSummary(XmlPullParser parser) throws IOException, XmlPullParserException {  
  61.     parser.require(XmlPullParser.START_TAG, ns, "summary");  
  62.     String summary = readText(parser);  
  63.     parser.require(XmlPullParser.END_TAG, ns, "summary");  
  64.     return summary;  
  65. }  
  66. // For the tags title and summary, extracts their text values.  
  67. private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {  
  68.     String result = "";  
  69.     if (parser.next() == XmlPullParser.TEXT) {  
  70.         result = parser.getText();  
  71.         parser.nextTag();  
  72.     }  
  73.     return result;  
  74. }  
  75.   ...  
  76. }  
 

跳过无用的标签

 

Java代码 
  1. private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {  
  2.     if (parser.getEventType() != XmlPullParser.START_TAG) {  
  3.         throw new IllegalStateException();  
  4.     }  
  5.     int depth = 1;  
  6.     while (depth != 0) {  
  7.         switch (parser.next()) {  
  8.         case XmlPullParser.END_TAG:  
  9.             depth--;  
  10.             break;  
  11.         case XmlPullParser.START_TAG:  
  12.             depth++;  
  13.             break;  
  14.         }  
  15.     }  
  16.  }  
 

使用xml数据

 

Java代码 
  1. public class NetworkActivity extends Activity {  
  2.     public static final String WIFI = "Wi-Fi";  
  3.     public static final String ANY = "Any";  
  4.     private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";  
  5.      
  6.     // Whether there is a Wi-Fi connection.  
  7.     private static boolean wifiConnected = false;   
  8.     // Whether there is a mobile connection.  
  9.     private static boolean mobileConnected = false;  
  10.     // Whether the display should be refreshed.  
  11.     public static boolean refreshDisplay = true;   
  12.     public static String sPref = null;  
  13. ...  
  14.         
  15.     // Uses AsyncTask to download the XML feed from stackoverflow.com.  
  16.     public void loadPage() {    
  17.         
  18.         if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {  
  19.             new DownloadXmlTask().execute(URL);  
  20.         }  
  21.         else if ((sPref.equals(WIFI)) && (wifiConnected)) {  
  22.             new DownloadXmlTask().execute(URL);  
  23.         } else {  
  24.             // show error  
  25.         }    
  26.     }  
 

动态下载xml

 

Java代码 
  1. // Implementation of AsyncTask used to download XML feed from stackoverflow.com.  
  2. private class DownloadXmlTask extends AsyncTask<String, Void, String> {  
  3.     @Override  
  4.     protected String doInBackground(String... urls) {  
  5.         try {  
  6.             return loadXmlFromNetwork(urls[0]);  
  7.         } catch (IOException e) {  
  8.             return getResources().getString(R.string.connection_error);  
  9.         } catch (XmlPullParserException e) {  
  10.             return getResources().getString(R.string.xml_error);  
  11.         }  
  12.     }  
  13. @Override  
  14.     protected void onPostExecute(String result) {    
  15.         setContentView(R.layout.main);  
  16.         // Displays the HTML string in the UI via a WebView  
  17.         WebView myWebView = (WebView) findViewById(R.id.webview);  
  18.         myWebView.loadData(result, "text/html"null);  
  19.     }  
  20. }  
 

加载xml

 

Java代码 
  1. // Uploads XML from stackoverflow.com, parses it, and combines it with  
  2. // HTML markup. Returns HTML string.  
  3. private String loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {  
  4.     InputStream stream = null;  
  5.     // Instantiate the parser  
  6.     StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();  
  7.     List<Entry> entries = null;  
  8.     String title = null;  
  9.     String url = null;  
  10.     String summary = null;  
  11.     Calendar rightNow = Calendar.getInstance();   
  12.     DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");  
  13.           
  14.     // Checks whether the user set the preference to include summary text  
  15.     SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);  
  16.     boolean pref = sharedPrefs.getBoolean("summaryPref"false);  
  17.           
  18.     StringBuilder htmlString = new StringBuilder();  
  19.     htmlString.append("<h3>" + getResources().getString(R.string.page_title) + "</h3>");  
  20.     htmlString.append("<em>" + getResources().getString(R.string.updated) + " " +   
  21.             formatter.format(rightNow.getTime()) + "</em>");  
  22.           
  23.     try {  
  24.         stream = downloadUrl(urlString);          
  25.         entries = stackOverflowXmlParser.parse(stream);  
  26.     // Makes sure that the InputStream is closed after the app is  
  27.     // finished using it.  
  28.     } finally {  
  29.         if (stream != null) {  
  30.             stream.close();  
  31.         }   
  32.      }  
  33.       
  34.     // StackOverflowXmlParser returns a List (called "entries") of Entry objects.  
  35.     // Each Entry object represents a single post in the XML feed.  
  36.     // This section processes the entries list to combine each entry with HTML markup.  
  37.     // Each entry is displayed in the UI as a link that optionally includes  
  38.     // a text summary.  
  39.     for (Entry entry : entries) {         
  40.         htmlString.append("<p><a href='");  
  41.         htmlString.append(entry.link);  
  42.         htmlString.append("'>" + entry.title + "</a></p>");  
  43.         // If the user set the preference to include summary text,  
  44.         // adds it to the display.  
  45.         if (pref) {  
  46.             htmlString.append(entry.summary);  
  47.         }  
  48.     }  
  49.     return htmlString.toString();  
  50. }  
  51. // Given a string representation of a URL, sets up a connection and gets  
  52. // an input stream.  
  53. private InputStream downloadUrl(String urlString) throws IOException {  
  54.     URL url = new URL(urlString);  
  55.     HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  56.     conn.setReadTimeout(10000 /* milliseconds */);  
  57.     conn.setConnectTimeout(15000 /* milliseconds */);  
  58.     conn.setRequestMethod("GET");  
  59.     conn.setDoInput(true);  
  60.     // Starts the query  
  61.     conn.connect();  
  62.     InputStream stream = conn.getInputStream();        
  63. }  

 

 

上面的片段代码为了帮助大家理解,这里还是老习惯,贴上项目的源代码,本来是有项目截图,运行效果图之类的图的,只是这篇文章太长了,再弄图片,就更占篇幅了,所以就只贴源码了,大家可以自己的运行起来看看,希望能从整体的架构和具体的代码细节上帮助到大家。

本篇我们会介绍连接到网络中涉及的基本任务,监测的网络连接(包括连接更改),并给予用户控制应用程序的网络使用情况。还介绍了如何解析和使用XML数据。

这个类包含一个示例应用程序来说明如何执行常见的网络操作。您可以下载示例(在右边),并用它作为自己的应用程序源代码的可重用代码。本章的重点有三:

1.连接到网络

2.管理网络的使用

3.解析XML数据

 

一、连接到网络

在mainfest中声明权限,代码如下:

 

Java代码 
  1. <uses-permission android:name="android.permission.INTERNET" />  
  2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
 

选择http客户端

大多数联网的Android应用程序使用HTTP来发送和接收数据。Android包括两个HTTP客户:HttpURLConnection HttpClient和Apache。都支持HTTPS,流媒体上传和下载,可配置的超时,IPv6,和连接池。我们建议使用HttpURLConnection目标应用程序。

检查网络连接

在你的应用程序尝试连接到网络,它应该检查是否一个网络连接可用使用getActiveNetworkInfo()和一个()。记住,这个装置可能范围的一个网络,或用户可能已经禁用wi - fi和移动数据访问。

 

Java代码 
  1. public void myClickHandler(View view) {  
  2.     ...  
  3.     ConnectivityManager connMgr = (ConnectivityManager)   
  4.         getSystemService(Context.CONNECTIVITY_SERVICE);  
  5.     NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();  
  6.     if (networkInfo != null && networkInfo.isConnected()) {  
  7.         // fetch data  
  8.     } else {  
  9.         // display error  
  10.     }  
  11.     ...  
  12. }  
 

在单独线程中执行网络操作

网络操作可以包括不可预测的延迟。为了防止这种导致一个糟糕的用户体验,总是执行网络操作在一个单独的线程。

 

Java代码 
  1. public class HttpExampleActivity extends Activity {  
  2.     private static final String DEBUG_TAG = "HttpExample";  
  3.     private EditText urlText;  
  4.     private TextView textView;  
  5.       
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.main);     
  10.         urlText = (EditText) findViewById(R.id.myUrl);  
  11.         textView = (TextView) findViewById(R.id.myText);  
  12.     }  
  13. // When user clicks button, calls AsyncTask.  
  14.     // Before attempting to fetch the URL, makes sure that there is a network connection.  
  15.     public void myClickHandler(View view) {  
  16.         // Gets the URL from the UI's text field.  
  17.         String stringUrl = urlText.getText().toString();  
  18.         ConnectivityManager connMgr = (ConnectivityManager)   
  19.             getSystemService(Context.CONNECTIVITY_SERVICE);  
  20.         NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();  
  21.         if (networkInfo != null && networkInfo.isConnected()) {  
  22.             new DownloadWebpageText().execute(stringUrl);  
  23.         } else {  
  24.             textView.setText("No network connection available.");  
  25.         }  
  26.     }  
  27. // Uses AsyncTask to create a task away from the main UI thread. This task takes a   
  28.      // URL string and uses it to create an HttpUrlConnection. Once the connection  
  29.      // has been established, the AsyncTask downloads the contents of the webpage as  
  30.      // an InputStream. Finally, the InputStream is converted into a string, which is  
  31.      // displayed in the UI by the AsyncTask's onPostExecute method.  
  32.      private class DownloadWebpageText extends AsyncTask {  
  33.         @Override  
  34.         protected String doInBackground(String... urls) {  
  35.                 
  36.             // params comes from the execute() call: params[0] is the url.  
  37.             try {  
  38.                 return downloadUrl(urls[0]);  
  39.             } catch (IOException e) {  
  40.                 return "Unable to retrieve web page. URL may be invalid.";  
  41.             }  
  42.         }  
  43.         // onPostExecute displays the results of the AsyncTask.  
  44.         @Override  
  45.         protected void onPostExecute(String result) {  
  46.             textView.setText(result);  
  47.        }  
  48.     }  
  49.     ...  
  50. }  
 

连接和下载数据

在你的线程执行您的网络交易,你可以使用HttpURLConnection来执行一个GET和下载数据。在您调用connect(),你可以得到一个InputStream的数据通过调用getInputStream()。

 

Java代码 
  1. // Given a URL, establishes an HttpUrlConnection and retrieves  
  2. // the web page content as a InputStream, which it returns as  
  3. // a string.  
  4. private String downloadUrl(String myurl) throws IOException {  
  5.     InputStream is = null;  
  6.     // Only display the first 500 characters of the retrieved  
  7.     // web page content.  
  8.     int len = 500;  
  9.           
  10.     try {  
  11.         URL url = new URL(myurl);  
  12.         HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  13.         conn.setReadTimeout(10000 /* milliseconds */);  
  14.         conn.setConnectTimeout(15000 /* milliseconds */);  
  15.         conn.setRequestMethod("GET");  
  16.         conn.setDoInput(true);  
  17.         // Starts the query  
  18.         conn.connect();  
  19.         int response = conn.getResponseCode();  
  20.         Log.d(DEBUG_TAG, "The response is: " + response);  
  21.         is = conn.getInputStream();  
  22. // Convert the InputStream into a string  
  23.         String contentAsString = readIt(is, len);  
  24.         return contentAsString;  
  25.           
  26.     // Makes sure that the InputStream is closed after the app is  
  27.     // finished using it.  
  28.     } finally {  
  29.         if (is != null) {  
  30.             is.close();  
  31.         }   
  32.     }  
  33. }  
 

getResponseCode()返回连接的状态码。这是一种有用的方式获得一些额外的信息的连接。一个200的状态代码表示成功。

转换InputStreamString

 

Java代码 
  1. // Reads an InputStream and converts it to a String.  
  2. public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {  
  3.     Reader reader = null;  
  4.     reader = new InputStreamReader(stream, "UTF-8");          
  5.     char[] buffer = new char[len];  
  6.     reader.read(buffer);  
  7.     return new String(buffer);  
  8. }  
 

 

 

二、管理网络

检查设备的网络连接

一个设备可以有各种类型的网络连接。这节课的重点是使用wi - fi或手机或网络连接,这个代码片段测试网络连接wi - fi和移动。它确定这些网络接口是可用的或连接的(即网络连接是否存在,如果可以建立套接字和传递数据)

 

Java代码 
  1. private static final String DEBUG_TAG = "NetworkStatusExample";  
  2. ...        
  3. ConnectivityManager connMgr = (ConnectivityManager)   
  4.         getSystemService(Context.CONNECTIVITY_SERVICE);  
  5. NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);   
  6. boolean isWifiConn = networkInfo.isConnected();  
  7. networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);  
  8. boolean isMobileConn = networkInfo.isConnected();  
  9. Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);  
  10. Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);  
 

管理网络的使用

您可以实现一个首选项活动,让用户明确控制应用程序的使用网络资源。例如: 1.你可能允许用户上传的视频只有当设备被连接到wi - fi网络。2.你可能会同步(或没有)根据特定标准如网络可用性、时间间隔,等等。

编写一个应用程序,支持网络访问和管理网络的使用,你的清单必须有正确的权限和意图过滤器。

在样例应用程序中,这个规定了SettingsActivity,将显示一个UI让用户知道何时可以进行下载操作。

 

Xml代码 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.android.networkusage"  
  4.     ...>  
  5. <uses-sdk android:minSdkVersion="4"   
  6.            android:targetSdkVersion="14" />  
  7.           
  8.     <uses-permission android:name="android.permission.INTERNET" />  
  9.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  10. <application  
  11.         ...>  
  12.         ...  
  13.         <activity android:label="SettingsActivity" android:name=".SettingsActivity">  
  14.              <intent-filter>  
  15.                 <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />  
  16.                 <category android:name="android.intent.category.DEFAULT" />  
  17.           </intent-filter>  
  18.         </activity>  
  19.     </application>  
  20. </manifest>  
 

 

 

Java代码 
  1. public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {  
  2.       
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.           
  7.         // Loads the XML preferences file  
  8.         addPreferencesFromResource(R.xml.preferences);  
  9.     }  
  10.     
  11.     @Override  
  12.     protected void onResume() {  
  13.         super.onResume();  
  14. // Registers a listener whenever a key changes              
  15.         getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);  
  16.     }  
  17.     
  18.     @Override  
  19.     protected void onPause() {  
  20.         super.onPause();  
  21. // Unregisters the listener set in onResume().  
  22.        // It's best practice to unregister listeners when your app isn't using them to cut down on   
  23.        // unnecessary system overhead. You do this in onPause().              
  24.        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);      
  25.     }  
  26.     
  27.     // When the user changes the preferences selection,   
  28.     // onSharedPreferenceChanged() restarts the main activity as a new  
  29.     // task. Sets the the refreshDisplay flag to "true" to indicate that   
  30.     // the main activity should update its display.  
  31.     // The main activity queries the PreferenceManager to get the latest settings.  
  32.       
  33.     @Override  
  34.     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {      
  35.         // Sets refreshDisplay to true so that when the user returns to the main  
  36.         // activity, the display refreshes to reflect the new settings.  
  37.         NetworkActivity.refreshDisplay = true;  
  38.     }  
  39. }  
 

 

响应网络变动

如果有一个匹配发生在设置和设备的网络连接(例如,如果设置为“wi - fi”和设备有一个wi - fi连接)之间,应用程序下载提继续并刷新显示

 

Java代码 
  1. public class NetworkActivity extends Activity {  
  2.     public static final String WIFI = "Wi-Fi";  
  3.     public static final String ANY = "Any";  
  4.     private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";  
  5.      
  6.     // Whether there is a Wi-Fi connection.  
  7.     private static boolean wifiConnected = false;   
  8.     // Whether there is a mobile connection.  
  9.     private static boolean mobileConnected = false;  
  10.     // Whether the display should be refreshed.  
  11.     public static boolean refreshDisplay = true;  
  12.       
  13.     // The user's current network preference setting.  
  14.     public static String sPref = null;  
  15.       
  16.     // The BroadcastReceiver that tracks network connectivity changes.  
  17.     private NetworkReceiver receiver = new NetworkReceiver();  
  18.       
  19.     @Override  
  20.     public void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.           
  23.         // Registers BroadcastReceiver to track network connection changes.  
  24.         IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);  
  25.         receiver = new NetworkReceiver();  
  26.         this.registerReceiver(receiver, filter);  
  27.     }  
  28.       
  29.     @Override   
  30.     public void onDestroy() {  
  31.         super.onDestroy();  
  32.         // Unregisters BroadcastReceiver when app is destroyed.  
  33.         if (receiver != null) {  
  34.             this.unregisterReceiver(receiver);  
  35.         }  
  36.     }  
  37.       
  38.     // Refreshes the display if the network connection and the  
  39.     // pref settings allow it.  
  40.       
  41.     @Override  
  42.     public void onStart () {  
  43.         super.onStart();    
  44.           
  45.         // Gets the user's network preference settings  
  46.         SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);  
  47.           
  48.         // Retrieves a string value for the preferences. The second parameter  
  49.         // is the default value to use if a preference value is not found.  
  50.         sPref = sharedPrefs.getString("listPref""Wi-Fi");  
  51. updateConnectedFlags();   
  52.          
  53.         if(refreshDisplay){  
  54.             loadPage();      
  55.         }  
  56.     }  
  57.       
  58.     // Checks the network connection and sets the wifiConnected and mobileConnected  
  59.     // variables accordingly.   
  60.     public void updateConnectedFlags() {  
  61.         ConnectivityManager connMgr = (ConnectivityManager)   
  62.                 getSystemService(Context.CONNECTIVITY_SERVICE);  
  63.           
  64.         NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();  
  65.         if (activeInfo != null && activeInfo.isConnected()) {  
  66.             wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;  
  67.             mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;  
  68.         } else {  
  69.             wifiConnected = false;  
  70.             mobileConnected = false;  
  71.         }    
  72.     }  
  73.         
  74.     // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.  
  75.     public void loadPage() {  
  76.         if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))  
  77.                 || ((sPref.equals(WIFI)) && (wifiConnected))) {  
  78.             // AsyncTask subclass  
  79.             new DownloadXmlTask().execute(URL);  
  80.         } else {  
  81.             showErrorPage();  
  82.         }  
  83.     }  
  84. ...  
  85.       
  86. }  
 

检测网络连接变化

 

Java代码 
  1. public class NetworkReceiver extends BroadcastReceiver {     
  2.         
  3. @Override  
  4. public void onReceive(Context context, Intent intent) {  
  5.     ConnectivityManager conn =  (ConnectivityManager)  
  6.         context.getSystemService(Context.CONNECTIVITY_SERVICE);  
  7.     NetworkInfo networkInfo = conn.getActiveNetworkInfo();  
  8.          
  9.     // Checks the user prefs and the network connection. Based on the result, decides whether  
  10.     // to refresh the display or keep the current display.  
  11.     // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.  
  12.     if (WIFI.equals(sPref) && networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {  
  13.         // If device has its Wi-Fi connection, sets refreshDisplay  
  14.         // to true. This causes the display to be refreshed when the user  
  15.         // returns to the app.  
  16.         refreshDisplay = true;  
  17.         Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();  
  18. // If the setting is ANY network and there is a network connection  
  19.     // (which by process of elimination would be mobile), sets refreshDisplay to true.  
  20.     } else if (ANY.equals(sPref) && networkInfo != null) {  
  21.         refreshDisplay = true;  
  22.                    
  23.     // Otherwise, the app can't download content--either because there is no network  
  24.     // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there   
  25.     // is no Wi-Fi connection.  
  26.     // Sets refreshDisplay to false.  
  27.     } else {  
  28.         refreshDisplay = false;  
  29.         Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();  
  30.     }  
  31. }  
 

 

三、解析xml

上传和解析XML数据是很常见的任务,网络连接应用程序。这一课解释了如何解析XML文档并使用他们的数据

选择转换器

我们建议XmlPullParser,这是一种高效且可维护的方式来解析XML在Android里。

分析需求

 

Xml代码 
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" ...">       
  3. <title type="text">newest questions tagged android - Stack Overflow</title>  
  4. ...  
  5.     <entry>  
  6.     ...  
  7.     </entry>  
  8.     <entry>  
  9.         <id>http://stackoverflow.com/q/9439999</id>  
  10.         <re:rank scheme="http://stackoverflow.com">0</re:rank>  
  11.         <title type="text">Where is my data file?</title>  
  12.         <category scheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags" term="android"/>  
  13.         <category scheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags" term="file"/>  
  14.         <author>  
  15.             <name>cliff2310</name>  
  16.             <uri>http://stackoverflow.com/users/1128925</uri>  
  17.         </author>  
  18.         <link rel="alternate" href="http://stackoverflow.com/questions/9439999/where-is-my-data-file" />  
  19.         <published>2012-02-25T00:30:54Z</published>  
  20.         <updated>2012-02-25T00:30:54Z</updated>  
  21.         <summary type="html">  
  22.             <p>I have an Application that requires a data file...</p>  
  23. </summary>  
  24.     </entry>  
  25.     <entry>  
  26.     ...  
  27.     </entry>  
  28. ...  
  29. </feed>  
 

实例化转化器

 

Java代码 
  1. public class StackOverflowXmlParser {  
  2.     // We don't use namespaces  
  3.     private static final String ns = null;  
  4.      
  5.     public List parse(InputStream in) throws XmlPullParserException, IOException {  
  6.         try {  
  7.             XmlPullParser parser = Xml.newPullParser();  
  8.             parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);  
  9.             parser.setInput(in, null);  
  10.             parser.nextTag();  
  11.             return readFeed(parser);  
  12.         } finally {  
  13.             in.close();  
  14.         }  
  15.     }  
  16.  ...   
  17. }  
  18. 读取xml  
  19. private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {  
  20.     List entries = new ArrayList();  
  21. parser.require(XmlPullParser.START_TAG, ns, "feed");  
  22.     while (parser.next() != XmlPullParser.END_TAG) {  
  23.         if (parser.getEventType() != XmlPullParser.START_TAG) {  
  24.             continue;  
  25.         }  
  26.         String name = parser.getName();  
  27.         // Starts by looking for the entry tag  
  28.         if (name.equals("entry")) {  
  29.             entries.add(readEntry(parser));  
  30.         } else {  
  31.             skip(parser);  
  32.         }  
  33.     }    
  34.     return entries;  
  35. }  
 

 

下面这个代码片段展示了如何解析器解析条目、标题、链接和总结:

 

Java代码 
  1. public static class Entry {  
  2.     public final String title;  
  3.     public final String link;  
  4.     public final String summary;  
  5. private Entry(String title, String summary, String link) {  
  6.         this.title = title;  
  7.         this.summary = summary;  
  8.         this.link = link;  
  9.     }  
  10. }  
  11.     
  12. // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off  
  13. // to their respective "read" methods for processing. Otherwise, skips the tag.  
  14. private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException {  
  15.     parser.require(XmlPullParser.START_TAG, ns, "entry");  
  16.     String title = null;  
  17.     String summary = null;  
  18.     String link = null;  
  19.     while (parser.next() != XmlPullParser.END_TAG) {  
  20.         if (parser.getEventType() != XmlPullParser.START_TAG) {  
  21.             continue;  
  22.         }  
  23.         String name = parser.getName();  
  24.         if (name.equals("title")) {  
  25.             title = readTitle(parser);  
  26.         } else if (name.equals("summary")) {  
  27.             summary = readSummary(parser);  
  28.         } else if (name.equals("link")) {  
  29.             link = readLink(parser);  
  30.         } else {  
  31.             skip(parser);  
  32.         }  
  33.     }  
  34.     return new Entry(title, summary, link);  
  35. }  
  36. // Processes title tags in the feed.  
  37. private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException {  
  38.     parser.require(XmlPullParser.START_TAG, ns, "title");  
  39.     String title = readText(parser);  
  40.     parser.require(XmlPullParser.END_TAG, ns, "title");  
  41.     return title;  
  42. }  
  43.     
  44. // Processes link tags in the feed.  
  45. private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException {  
  46.     String link = "";  
  47.     parser.require(XmlPullParser.START_TAG, ns, "link");  
  48.     String tag = parser.getName();  
  49.     String relType = parser.getAttributeValue(null"rel");    
  50.     if (tag.equals("link")) {  
  51.         if (relType.equals("alternate")){  
  52.             link = parser.getAttributeValue(null"href");  
  53.             parser.nextTag();  
  54.         }   
  55.     }  
  56.     parser.require(XmlPullParser.END_TAG, ns, "link");  
  57.     return link;  
  58. }  
  59. // Processes summary tags in the feed.  
  60. private String readSummary(XmlPullParser parser) throws IOException, XmlPullParserException {  
  61.     parser.require(XmlPullParser.START_TAG, ns, "summary");  
  62.     String summary = readText(parser);  
  63.     parser.require(XmlPullParser.END_TAG, ns, "summary");  
  64.     return summary;  
  65. }  
  66. // For the tags title and summary, extracts their text values.  
  67. private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {  
  68.     String result = "";  
  69.     if (parser.next() == XmlPullParser.TEXT) {  
  70.         result = parser.getText();  
  71.         parser.nextTag();  
  72.     }  
  73.     return result;  
  74. }  
  75.   ...  
  76. }  
 

跳过无用的标签

 

Java代码 
  1. private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {  
  2.     if (parser.getEventType() != XmlPullParser.START_TAG) {  
  3.         throw new IllegalStateException();  
  4.     }  
  5.     int depth = 1;  
  6.     while (depth != 0) {  
  7.         switch (parser.next()) {  
  8.         case XmlPullParser.END_TAG:  
  9.             depth--;  
  10.             break;  
  11.         case XmlPullParser.START_TAG:  
  12.             depth++;  
  13.             break;  
  14.         }  
  15.     }  
  16.  }  
 

使用xml数据

 

Java代码 
  1. public class NetworkActivity extends Activity {  
  2.     public static final String WIFI = "Wi-Fi";  
  3.     public static final String ANY = "Any";  
  4.     private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";  
  5.      
  6.     // Whether there is a Wi-Fi connection.  
  7.     private static boolean wifiConnected = false;   
  8.     // Whether there is a mobile connection.  
  9.     private static boolean mobileConnected = false;  
  10.     // Whether the display should be refreshed.  
  11.     public static boolean refreshDisplay = true;   
  12.     public static String sPref = null;  
  13. ...  
  14.         
  15.     // Uses AsyncTask to download the XML feed from stackoverflow.com.  
  16.     public void loadPage() {    
  17.         
  18.         if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {  
  19.             new DownloadXmlTask().execute(URL);  
  20.         }  
  21.         else if ((sPref.equals(WIFI)) && (wifiConnected)) {  
  22.             new DownloadXmlTask().execute(URL);  
  23.         } else {  
  24.             // show error  
  25.         }    
  26.     }  
 

动态下载xml

 

Java代码 
  1. // Implementation of AsyncTask used to download XML feed from stackoverflow.com.  
  2. private class DownloadXmlTask extends AsyncTask<String, Void, String> {  
  3.     @Override  
  4.     protected String doInBackground(String... urls) {  
  5.         try {  
  6.             return loadXmlFromNetwork(urls[0]);  
  7.         } catch (IOException e) {  
  8.             return getResources().getString(R.string.connection_error);  
  9.         } catch (XmlPullParserException e) {  
  10.             return getResources().getString(R.string.xml_error);  
  11.         }  
  12.     }  
  13. @Override  
  14.     protected void onPostExecute(String result) {    
  15.         setContentView(R.layout.main);  
  16.         // Displays the HTML string in the UI via a WebView  
  17.         WebView myWebView = (WebView) findViewById(R.id.webview);  
  18.         myWebView.loadData(result, "text/html"null);  
  19.     }  
  20. }  
 

加载xml

 

Java代码 
  1. // Uploads XML from stackoverflow.com, parses it, and combines it with  
  2. // HTML markup. Returns HTML string.  
  3. private String loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {  
  4.     InputStream stream = null;  
  5.     // Instantiate the parser  
  6.     StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();  
  7.     List<Entry> entries = null;  
  8.     String title = null;  
  9.     String url = null;  
  10.     String summary = null;  
  11.     Calendar rightNow = Calendar.getInstance();   
  12.     DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");  
  13.           
  14.     // Checks whether the user set the preference to include summary text  
  15.     SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);  
  16.     boolean pref = sharedPrefs.getBoolean("summaryPref"false);  
  17.           
  18.     StringBuilder htmlString = new StringBuilder();  
  19.     htmlString.append("<h3>" + getResources().getString(R.string.page_title) + "</h3>");  
  20.     htmlString.append("<em>" + getResources().getString(R.string.updated) + " " +   
  21.             formatter.format(rightNow.getTime()) + "</em>");  
  22.           
  23.     try {  
  24.         stream = downloadUrl(urlString);          
  25.         entries = stackOverflowXmlParser.parse(stream);  
  26.     // Makes sure that the InputStream is closed after the app is  
  27.     // finished using it.  
  28.     } finally {  
  29.         if (stream != null) {  
  30.             stream.close();  
  31.         }   
  32.      }  
  33.       
  34.     // StackOverflowXmlParser returns a List (called "entries") of Entry objects.  
  35.     // Each Entry object represents a single post in the XML feed.  
  36.     // This section processes the entries list to combine each entry with HTML markup.  
  37.     // Each entry is displayed in the UI as a link that optionally includes  
  38.     // a text summary.  
  39.     for (Entry entry : entries) {         
  40.         htmlString.append("<p><a href='");  
  41.         htmlString.append(entry.link);  
  42.         htmlString.append("'>" + entry.title + "</a></p>");  
  43.         // If the user set the preference t http:// o include summary text,  
  44.         // adds it to the display.  
  45.         if (pref) {  
  46.             htmlString.append(entry.summary);  
  47.         }  
  48.     }  
  49.     return htmlString.toString();  
  50. }  
  51. // Given a string representation of a URL, sets up a connection and gets  
  52. // an input stream.  
  53. private InputStream downloadUrl(String urlString) throws IOException {  
  54.     URL url = new URL(urlString);  
  55.     HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  56.     conn.setReadTimeout(10000 /* milliseconds */);  
  57.     conn.setConnectTimeout(15000 /* milliseconds */);  
  58.     conn.setRequestMethod("GET");  
  59.     conn.setDoInput(true);  
  60.     // Starts the query  
  61.     conn.connect();  
  62.     InputStream stream = conn.getInputStream();        
  63. }  

 

 

上面的片段代码为了帮助大家理解,这里还是老习惯,贴上项目的源代码,本来是有项目截图,运行效果图之类的图的,只是这篇文章太长了,再弄图片,就更占篇幅了,所以就只贴源码了,大家可以自己的运行起来看看,希望能从整体的架构和具体的代码细节上帮助到大家。点击打开下载链接

你可能感兴趣的:(java,android,网络,Stream,service)