android执行网络操作

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 17:18   2972   0



本篇我们会介绍连接到网络中涉及的基本任务,监测的网络连接(包括连接更改),并给予用户控制应用程序的网络使用情况。还介绍了如何解析和使用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. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. urlText = (EditText) findViewById(R.id.myUrl);
  10. textView = (TextView) findViewById(R.id.myText);
  11. }
  12. // When user clicks button, calls AsyncTask.
  13. // Before attempting to fetch the URL, makes sure that there is a network connection.
  14. public void myClickHandler(View view) {
  15. // Gets the URL from the UI's text field.
  16. String stringUrl = urlText.getText().toString();
  17. ConnectivityManager connMgr = (ConnectivityManager)
  18. getSystemService(Context.CONNECTIVITY_SERVICE);
  19. NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
  20. if (networkInfo != null && networkInfo.isConnected()) {
  21. new DownloadWebpageText().execute(stringUrl);
  22. } else {
  23. textView.setText("No network connection available.");
  24. }
  25. }
  26. // Uses AsyncTask to create a task away from the main UI thread. This task takes a
  27. // URL string and uses it to create an HttpUrlConnection. Once the connection
  28. // has been established, the AsyncTask downloads the contents of the webpage as
  29. // an InputStream. Finally, the InputStream is converted into a string, which is
  30. // displayed in the UI by the AsyncTask's onPostExecute method.
  31. private class DownloadWebpageText extends AsyncTask {
  32. @Override
  33. protected String doInBackground(String... urls) {
  34. // params comes from the execute() call: params[0] is the url.
  35. try {
  36. return downloadUrl(urls[0]);
  37. } catch (IOException e) {
  38. return "Unable to retrieve web page. URL may be invalid.";
  39. }
  40. }
  41. // onPostExecute displays the results of the AsyncTask.
  42. @Override
  43. protected void onPostExecute(String result) {
  44. textView.setText(result);
  45. }
  46. }
  47. ...
  48. }

连接和下载数据

在你的线程执行您的网络交易,你可以使用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. try {
  10. URL url = new URL(myurl);
  11. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  12. conn.setReadTimeout(10000 /* milliseconds */);
  13. conn.setConnectTimeout(15000 /* milliseconds */);
  14. conn.setRequestMethod("GET");
  15. conn.setDoInput(true);
  16. // Starts the query
  17. conn.connect();
  18. int response = conn.getResponseCode();
  19. Log.d(DEBUG_TAG, "The response is: " + response);
  20. is = conn.getInputStream();
  21. // Convert the InputStream into a string
  22. String contentAsString = readIt(is, len);
  23. return contentAsString;
  24. // Makes sure that the InputStream is closed after the app is
  25. // finished using it.
  26. } finally {
  27. if (is != null) {
  28. is.close();
  29. }
  30. }
  31. }

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. <uses-permission android:name="android.permission.INTERNET" />
  8. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  9. <application
  10. ...>
  11. ...
  12. <activity android:label="SettingsActivity" android:name=".SettingsActivity">
  13. <intent-filter>
  14. <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
  15. <category android:name="android.intent.category.DEFAULT" />
  16. </intent-filter>
  17. </activity>
  18. </application>
  19. </manifest>

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

响应网络变动

如果有一个匹配发生在设置和设备的网络连接(例如,如果设置为“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. // Whether there is a Wi-Fi connection.
  6. private static boolean wifiConnected = false;
  7. // Whether there is a mobile connection.
  8. private static boolean mobileConnected = false;
  9. // Whether the display should be refreshed.
  10. public static boolean refreshDisplay = true;
  11. // The user's current network preference setting.
  12. public static String sPref = null;
  13. // The BroadcastReceiver that tracks network connectivity changes.
  14. private NetworkReceiver receiver = new NetworkReceiver();
  15. @Override
  16. public void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. // Registers BroadcastReceiver to track network connection changes.
  19. IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
  20. receiver = new NetworkReceiver();
  21. this.registerReceiver(receiver, filter);
  22. }
  23. @Override
  24. public void onDestroy() {
  25. super.onDestroy();
  26. // Unregisters BroadcastReceiver when app is destroyed.
  27. if (receiver != null) {
  28. this.unregisterReceiver(receiver);
  29. }
  30. }
  31. // Refreshes the display if the network connection and the
  32. // pref settings allow it.
  33. @Override
  34. public void onStart () {
  35. super.onStart();
  36. // Gets the user's network preference settings
  37. SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
  38. // Retrieves a string value for the preferences. The second parameter
  39. // is the default value to use if a preference value is not found.
  40. sPref = sharedPrefs.getString("listPref", "Wi-Fi");
  41. updateConnectedFlags();
  42. if(refreshDisplay){
  43. loadPage();
  44. }
  45. }
  46. // Checks the network connection and sets the wifiConnected and mobileConnected
  47. // variables accordingly.
  48. public void updateConnectedFlags() {
  49. ConnectivityManager connMgr = (ConnectivityManager)
  50. getSystemService(Context.CONNECTIVITY_SERVICE);
  51. NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
  52. if (activeInfo != null && activeInfo.isConnected()) {
  53. wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
  54. mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
  55. } else {
  56. wifiConnected = false;
  57. mobileConnected = false;
  58. }
  59. }
  60. // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
  61. public void loadPage() {
  62. if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
  63. || ((sPref.equals(WIFI)) && (wifiConnected))) {
  64. // AsyncTask subclass
  65. new DownloadXmlTask().execute(URL);
  66. } else {
  67. showErrorPage();
  68. }
  69. }
  70. ...
  71. }

检测网络连接变化

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

三、解析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. public List parse(InputStream in) throws XmlPullParserException, IOException {
  5. try {
  6. XmlPullParser parser = Xml.newPullParser();
  7. parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
  8. parser.setInput(in, null);
  9. parser.nextTag();
  10. return readFeed(parser);
  11. } finally {
  12. in.close();
  13. }
  14. }
  15. ...
  16. }
  17. 读取xml
  18. private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
  19. List entries = new ArrayList();
  20. parser.require(XmlPullParser.START_TAG, ns, "feed");
  21. while (parser.next() != XmlPullParser.END_TAG) {
  22. if (parser.getEventType() != XmlPullParser.START_TAG) {
  23. continue;
  24. }
  25. String name = parser.getName();
  26. // Starts by looking for the entry tag
  27. if (name.equals("entry")) {
  28. entries.add(readEntry(parser));
  29. } else {
  30. skip(parser);
  31. }
  32. }
  33. return entries;
  34. }

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

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

跳过无用的标签

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. // Whether there is a Wi-Fi connection.
  6. private static boolean wifiConnected = false;
  7. // Whether there is a mobile connection.
  8. private static boolean mobileConnected = false;
  9. // Whether the display should be refreshed.
  10. public static boolean refreshDisplay = true;
  11. public static String sPref = null;
  12. ...
  13. // Uses AsyncTask to download the XML feed from stackoverflow.com.
  14. public void loadPage() {
  15. if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {
  16. new DownloadXmlTask().execute(URL);
  17. }
  18. else if ((sPref.equals(WIFI)) && (wifiConnected)) {
  19. new DownloadXmlTask().execute(URL);
  20. } else {
  21. // show error
  22. }
  23. }

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

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

本篇我们会介绍连接到网络中涉及的基本任务,监测的网络连接(包括连接更改),并给予用户控制应用程序的网络使用情况。还介绍了如何解析和使用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. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. urlText = (EditText) findViewById(R.id.myUrl);
  10. textView = (TextView) findViewById(R.id.myText);
  11. }
  12. // When user clicks button, calls AsyncTask.
  13. // Before attempting to fetch the URL, makes sure that there is a network connection.
  14. public void myClickHandler(View view) {
  15. // Gets the URL from the UI's text field.
  16. String stringUrl = urlText.getText().toString();
  17. ConnectivityManager connMgr = (ConnectivityManager)
  18. getSystemService(Context.CONNECTIVITY_SERVICE);
  19. NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
  20. if (networkInfo != null && networkInfo.isConnected()) {
  21. new DownloadWebpageText().execute(stringUrl);
  22. } else {
  23. textView.setText("No network connection available.");
  24. }
  25. }
  26. // Uses AsyncTask to create a task away from the main UI thread. This task takes a
  27. // URL string and uses it to create an HttpUrlConnection. Once the connection
  28. // has been established, the AsyncTask downloads the contents of the webpage as
  29. // an InputStream. Finally, the InputStream is converted into a string, which is
  30. // displayed in the UI by the AsyncTask's onPostExecute method.
  31. private class DownloadWebpageText extends AsyncTask {
  32. @Override
  33. protected String doInBackground(String... urls) {
  34. // params comes from the execute() call: params[0] is the url.
  35. try {
  36. return downloadUrl(urls[0]);
  37. } catch (IOException e) {
  38. return "Unable to retrieve web page. URL may be invalid.";
  39. }
  40. }
  41. // onPostExecute displays the results of the AsyncTask.
  42. @Override
  43. protected void onPostExecute(String result) {
  44. textView.setText(result);
  45. }
  46. }
  47. ...
  48. }

连接和下载数据

在你的线程执行您的网络交易,你可以使用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. try {
  10. URL url = new URL(myurl);
  11. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  12. conn.setReadTimeout(10000 /* milliseconds */);
  13. conn.setConnectTimeout(15000 /* milliseconds */);
  14. conn.setRequestMethod("GET");
  15. conn.setDoInput(true);
  16. // Starts the query
  17. conn.connect();
  18. int response = conn.getResponseCode();
  19. Log.d(DEBUG_TAG, "The response is: " + response);
  20. is = conn.getInputStream();
  21. // Convert the InputStream into a string
  22. String contentAsString = readIt(is, len);
  23. return contentAsString;
  24. // Makes sure that the InputStream is closed after the app is
  25. // finished using it.
  26. } finally {
  27. if (is != null) {
  28. is.close();
  29. }
  30. }
  31. }

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. <uses-permission android:name="android.permission.INTERNET" />
  8. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  9. <application
  10. ...>
  11. ...
  12. <activity android:label="SettingsActivity" android:name=".SettingsActivity">
  13. <intent-filter>
  14. <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
  15. <category android:name="android.intent.category.DEFAULT" />
  16. </intent-filter>
  17. </activity>
  18. </application>
  19. </manifest>

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

响应网络变动

如果有一个匹配发生在设置和设备的网络连接(例如,如果设置为“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. // Whether there is a Wi-Fi connection.
  6. private static boolean wifiConnected = false;
  7. // Whether there is a mobile connection.
  8. private static boolean mobileConnected = false;
  9. // Whether the display should be refreshed.
  10. public static boolean refreshDisplay = true;
  11. // The user's current network preference setting.
  12. public static String sPref = null;
  13. // The BroadcastReceiver that tracks network connectivity changes.
  14. private NetworkReceiver receiver = new NetworkReceiver();
  15. @Override
  16. public void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. // Registers BroadcastReceiver to track network connection changes.
  19. IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
  20. receiver = new NetworkReceiver();
  21. this.registerReceiver(receiver, filter);
  22. }
  23. @Override
  24. public void onDestroy() {
  25. super.onDestroy();
  26. // Unregisters BroadcastReceiver when app is destroyed.
  27. if (receiver != null) {
  28. this.unregisterReceiver(receiver);
  29. }
  30. }
  31. // Refreshes the display if the network connection and the
  32. // pref settings allow it.
  33. @Override
  34. public void onStart () {
  35. super.onStart();
  36. // Gets the user's network preference settings
  37. SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
  38. // Retrieves a string value for the preferences. The second parameter
  39. // is the default value to use if a preference value is not found.
  40. sPref = sharedPrefs.getString("listPref", "Wi-Fi");
  41. updateConnectedFlags();
  42. if(refreshDisplay){
  43. loadPage();
  44. }
  45. }
  46. // Checks the network connection and sets the wifiConnected and mobileConnected
  47. // variables accordingly.
  48. public void updateConnectedFlags() {
  49. ConnectivityManager connMgr = (ConnectivityManager)
  50. getSystemService(Context.CONNECTIVITY_SERVICE);
  51. NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
  52. if (activeInfo != null && activeInfo.isConnected()) {
  53. wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
  54. mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
  55. } else {
  56. wifiConnected = false;
  57. mobileConnected = false;
  58. }
  59. }
  60. // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
  61. public void loadPage() {
  62. if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
  63. || ((sPref.equals(WIFI)) && (wifiConnected))) {
  64. // AsyncTask subclass
  65. new DownloadXmlTask().execute(URL);
  66. } else {
  67. showErrorPage();
  68. }
  69. }
  70. ...
  71. }

检测网络连接变化

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

三、解析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. public List parse(InputStream in) throws XmlPullParserException, IOException {
  5. try {
  6. XmlPullParser parser = Xml.newPullParser();
  7. parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
  8. parser.setInput(in, null);
  9. parser.nextTag();
  10. return readFeed(parser);
  11. } finally {
  12. in.close();
  13. }
  14. }
  15. ...
  16. }
  17. 读取xml
  18. private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
  19. List entries = new ArrayList();
  20. parser.require(XmlPullParser.START_TAG, ns, "feed");
  21. while (parser.next() != XmlPullParser.END_TAG) {
  22. if (parser.getEventType() != XmlPullParser.START_TAG) {
  23. continue;
  24. }
  25. String name = parser.getName();
  26. // Starts by looking for the entry tag
  27. if (name.equals("entry")) {
  28. entries.add(readEntry(parser));
  29. } else {
  30. skip(parser);
  31. }
  32. }
  33. return entries;
  34. }

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

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

跳过无用的标签

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. // Whether there is a Wi-Fi connection.
  6. private static boolean wifiConnected = false;
  7. // Whether there is a mobile connection.
  8. private static boolean mobileConnected = false;
  9. // Whether the display should be refreshed.
  10. public static boolean refreshDisplay = true;
  11. public static String sPref = null;
  12. ...
  13. // Uses AsyncTask to download the XML feed from stackoverflow.com.
  14. public void loadPage() {
  15. if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {
  16. new DownloadXmlTask().execute(URL);
  17. }
  18. else if ((sPref.equals(WIFI)) && (wifiConnected)) {
  19. new DownloadXmlTask().execute(URL);
  20. } else {
  21. // show error
  22. }
  23. }

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

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

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP