PageRenderTime 38ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java

http://github.com/android/platform_frameworks_base
Java | 321 lines | 189 code | 39 blank | 93 comment | 30 complexity | 7ea907cf519b723b7fe5ec6137268038 MD5 | raw file
Possible License(s): BitTorrent-1.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, CC0-1.0
  1. /*
  2. * Copyright (C) 2012 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  5. * in compliance with the License. You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License
  10. * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  11. * or implied. See the License for the specific language governing permissions and limitations under
  12. * the License.
  13. */
  14. package com.example.android.networkusage;
  15. import android.app.Activity;
  16. import android.content.BroadcastReceiver;
  17. import android.content.Context;
  18. import android.content.Intent;
  19. import android.content.IntentFilter;
  20. import android.content.SharedPreferences;
  21. import android.net.ConnectivityManager;
  22. import android.net.NetworkInfo;
  23. import android.os.AsyncTask;
  24. import android.os.Bundle;
  25. import android.preference.PreferenceManager;
  26. import android.view.Menu;
  27. import android.view.MenuInflater;
  28. import android.view.MenuItem;
  29. import android.webkit.WebView;
  30. import android.widget.Toast;
  31. import com.example.android.networkusage.R;
  32. import com.example.android.networkusage.StackOverflowXmlParser.Entry;
  33. import org.xmlpull.v1.XmlPullParserException;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.net.HttpURLConnection;
  37. import java.net.URL;
  38. import java.text.DateFormat;
  39. import java.text.SimpleDateFormat;
  40. import java.util.Calendar;
  41. import java.util.List;
  42. /**
  43. * Main Activity for the sample application.
  44. *
  45. * This activity does the following:
  46. *
  47. * o Presents a WebView screen to users. This WebView has a list of HTML links to the latest
  48. * questions tagged 'android' on stackoverflow.com.
  49. *
  50. * o Parses the StackOverflow XML feed using XMLPullParser.
  51. *
  52. * o Uses AsyncTask to download and process the XML feed.
  53. *
  54. * o Monitors preferences and the device's network connection to determine whether
  55. * to refresh the WebView content.
  56. */
  57. public class NetworkActivity extends Activity {
  58. public static final String WIFI = "Wi-Fi";
  59. public static final String ANY = "Any";
  60. private static final String URL =
  61. "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
  62. // Whether there is a Wi-Fi connection.
  63. private static boolean wifiConnected = false;
  64. // Whether there is a mobile connection.
  65. private static boolean mobileConnected = false;
  66. // Whether the display should be refreshed.
  67. public static boolean refreshDisplay = true;
  68. // The user's current network preference setting.
  69. public static String sPref = null;
  70. // The BroadcastReceiver that tracks network connectivity changes.
  71. private NetworkReceiver receiver = new NetworkReceiver();
  72. @Override
  73. public void onCreate(Bundle savedInstanceState) {
  74. super.onCreate(savedInstanceState);
  75. // Register BroadcastReceiver to track connection changes.
  76. IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
  77. receiver = new NetworkReceiver();
  78. this.registerReceiver(receiver, filter);
  79. }
  80. // Refreshes the display if the network connection and the
  81. // pref settings allow it.
  82. @Override
  83. public void onStart() {
  84. super.onStart();
  85. // Gets the user's network preference settings
  86. SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
  87. // Retrieves a string value for the preferences. The second parameter
  88. // is the default value to use if a preference value is not found.
  89. sPref = sharedPrefs.getString("listPref", "Wi-Fi");
  90. updateConnectedFlags();
  91. // Only loads the page if refreshDisplay is true. Otherwise, keeps previous
  92. // display. For example, if the user has set "Wi-Fi only" in prefs and the
  93. // device loses its Wi-Fi connection midway through the user using the app,
  94. // you don't want to refresh the display--this would force the display of
  95. // an error page instead of stackoverflow.com content.
  96. if (refreshDisplay) {
  97. loadPage();
  98. }
  99. }
  100. @Override
  101. public void onDestroy() {
  102. super.onDestroy();
  103. if (receiver != null) {
  104. this.unregisterReceiver(receiver);
  105. }
  106. }
  107. // Checks the network connection and sets the wifiConnected and mobileConnected
  108. // variables accordingly.
  109. private void updateConnectedFlags() {
  110. ConnectivityManager connMgr =
  111. (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  112. NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
  113. if (activeInfo != null && activeInfo.isConnected()) {
  114. wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
  115. mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
  116. } else {
  117. wifiConnected = false;
  118. mobileConnected = false;
  119. }
  120. }
  121. // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
  122. // This avoids UI lock up. To prevent network operations from
  123. // causing a delay that results in a poor user experience, always perform
  124. // network operations on a separate thread from the UI.
  125. private void loadPage() {
  126. if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
  127. || ((sPref.equals(WIFI)) && (wifiConnected))) {
  128. // AsyncTask subclass
  129. new DownloadXmlTask().execute(URL);
  130. } else {
  131. showErrorPage();
  132. }
  133. }
  134. // Displays an error if the app is unable to load content.
  135. private void showErrorPage() {
  136. setContentView(R.layout.main);
  137. // The specified network connection is not available. Displays error message.
  138. WebView myWebView = (WebView) findViewById(R.id.webview);
  139. myWebView.loadData(getResources().getString(R.string.connection_error),
  140. "text/html", null);
  141. }
  142. // Populates the activity's options menu.
  143. @Override
  144. public boolean onCreateOptionsMenu(Menu menu) {
  145. MenuInflater inflater = getMenuInflater();
  146. inflater.inflate(R.menu.mainmenu, menu);
  147. return true;
  148. }
  149. // Handles the user's menu selection.
  150. @Override
  151. public boolean onOptionsItemSelected(MenuItem item) {
  152. switch (item.getItemId()) {
  153. case R.id.settings:
  154. Intent settingsActivity = new Intent(getBaseContext(), SettingsActivity.class);
  155. startActivity(settingsActivity);
  156. return true;
  157. case R.id.refresh:
  158. loadPage();
  159. return true;
  160. default:
  161. return super.onOptionsItemSelected(item);
  162. }
  163. }
  164. // Implementation of AsyncTask used to download XML feed from stackoverflow.com.
  165. private class DownloadXmlTask extends AsyncTask<String, Void, String> {
  166. @Override
  167. protected String doInBackground(String... urls) {
  168. try {
  169. return loadXmlFromNetwork(urls[0]);
  170. } catch (IOException e) {
  171. return getResources().getString(R.string.connection_error);
  172. } catch (XmlPullParserException e) {
  173. return getResources().getString(R.string.xml_error);
  174. }
  175. }
  176. @Override
  177. protected void onPostExecute(String result) {
  178. setContentView(R.layout.main);
  179. // Displays the HTML string in the UI via a WebView
  180. WebView myWebView = (WebView) findViewById(R.id.webview);
  181. myWebView.loadData(result, "text/html", null);
  182. }
  183. }
  184. // Uploads XML from stackoverflow.com, parses it, and combines it with
  185. // HTML markup. Returns HTML string.
  186. private String loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
  187. InputStream stream = null;
  188. StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();
  189. List<Entry> entries = null;
  190. String title = null;
  191. String url = null;
  192. String summary = null;
  193. Calendar rightNow = Calendar.getInstance();
  194. DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");
  195. // Checks whether the user set the preference to include summary text
  196. SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
  197. boolean pref = sharedPrefs.getBoolean("summaryPref", false);
  198. StringBuilder htmlString = new StringBuilder();
  199. htmlString.append("<h3>" + getResources().getString(R.string.page_title) + "</h3>");
  200. htmlString.append("<em>" + getResources().getString(R.string.updated) + " " +
  201. formatter.format(rightNow.getTime()) + "</em>");
  202. try {
  203. stream = downloadUrl(urlString);
  204. entries = stackOverflowXmlParser.parse(stream);
  205. // Makes sure that the InputStream is closed after the app is
  206. // finished using it.
  207. } finally {
  208. if (stream != null) {
  209. stream.close();
  210. }
  211. }
  212. // StackOverflowXmlParser returns a List (called "entries") of Entry objects.
  213. // Each Entry object represents a single post in the XML feed.
  214. // This section processes the entries list to combine each entry with HTML markup.
  215. // Each entry is displayed in the UI as a link that optionally includes
  216. // a text summary.
  217. for (Entry entry : entries) {
  218. htmlString.append("<p><a href='");
  219. htmlString.append(entry.link);
  220. htmlString.append("'>" + entry.title + "</a></p>");
  221. // If the user set the preference to include summary text,
  222. // adds it to the display.
  223. if (pref) {
  224. htmlString.append(entry.summary);
  225. }
  226. }
  227. return htmlString.toString();
  228. }
  229. // Given a string representation of a URL, sets up a connection and gets
  230. // an input stream.
  231. private InputStream downloadUrl(String urlString) throws IOException {
  232. URL url = new URL(urlString);
  233. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  234. conn.setReadTimeout(10000 /* milliseconds */);
  235. conn.setConnectTimeout(15000 /* milliseconds */);
  236. conn.setRequestMethod("GET");
  237. conn.setDoInput(true);
  238. // Starts the query
  239. conn.connect();
  240. InputStream stream = conn.getInputStream();
  241. return stream;
  242. }
  243. /**
  244. *
  245. * This BroadcastReceiver intercepts the android.net.ConnectivityManager.CONNECTIVITY_ACTION,
  246. * which indicates a connection change. It checks whether the type is TYPE_WIFI.
  247. * If it is, it checks whether Wi-Fi is connected and sets the wifiConnected flag in the
  248. * main activity accordingly.
  249. *
  250. */
  251. public class NetworkReceiver extends BroadcastReceiver {
  252. @Override
  253. public void onReceive(Context context, Intent intent) {
  254. ConnectivityManager connMgr =
  255. (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  256. NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
  257. // Checks the user prefs and the network connection. Based on the result, decides
  258. // whether
  259. // to refresh the display or keep the current display.
  260. // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
  261. if (WIFI.equals(sPref) && networkInfo != null
  262. && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
  263. // If device has its Wi-Fi connection, sets refreshDisplay
  264. // to true. This causes the display to be refreshed when the user
  265. // returns to the app.
  266. refreshDisplay = true;
  267. Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();
  268. // If the setting is ANY network and there is a network connection
  269. // (which by process of elimination would be mobile), sets refreshDisplay to true.
  270. } else if (ANY.equals(sPref) && networkInfo != null) {
  271. refreshDisplay = true;
  272. // Otherwise, the app can't download content--either because there is no network
  273. // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
  274. // is no Wi-Fi connection.
  275. // Sets refreshDisplay to false.
  276. } else {
  277. refreshDisplay = false;
  278. Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
  279. }
  280. }
  281. }
  282. }