/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
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
- /*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.example.android.networkusage;
- import android.app.Activity;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.SharedPreferences;
- import android.net.ConnectivityManager;
- import android.net.NetworkInfo;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.preference.PreferenceManager;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.webkit.WebView;
- import android.widget.Toast;
- import com.example.android.networkusage.R;
- import com.example.android.networkusage.StackOverflowXmlParser.Entry;
- import org.xmlpull.v1.XmlPullParserException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- import java.util.Calendar;
- import java.util.List;
- /**
- * Main Activity for the sample application.
- *
- * This activity does the following:
- *
- * o Presents a WebView screen to users. This WebView has a list of HTML links to the latest
- * questions tagged 'android' on stackoverflow.com.
- *
- * o Parses the StackOverflow XML feed using XMLPullParser.
- *
- * o Uses AsyncTask to download and process the XML feed.
- *
- * o Monitors preferences and the device's network connection to determine whether
- * to refresh the WebView content.
- */
- public class NetworkActivity extends Activity {
- public static final String WIFI = "Wi-Fi";
- public static final String ANY = "Any";
- private static final String URL =
- "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
- // Whether there is a Wi-Fi connection.
- private static boolean wifiConnected = false;
- // Whether there is a mobile connection.
- private static boolean mobileConnected = false;
- // Whether the display should be refreshed.
- public static boolean refreshDisplay = true;
- // The user's current network preference setting.
- public static String sPref = null;
- // The BroadcastReceiver that tracks network connectivity changes.
- private NetworkReceiver receiver = new NetworkReceiver();
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Register BroadcastReceiver to track connection changes.
- IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
- receiver = new NetworkReceiver();
- this.registerReceiver(receiver, filter);
- }
- // Refreshes the display if the network connection and the
- // pref settings allow it.
- @Override
- public void onStart() {
- super.onStart();
- // Gets the user's network preference settings
- SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- // Retrieves a string value for the preferences. The second parameter
- // is the default value to use if a preference value is not found.
- sPref = sharedPrefs.getString("listPref", "Wi-Fi");
- updateConnectedFlags();
- // Only loads the page if refreshDisplay is true. Otherwise, keeps previous
- // display. For example, if the user has set "Wi-Fi only" in prefs and the
- // device loses its Wi-Fi connection midway through the user using the app,
- // you don't want to refresh the display--this would force the display of
- // an error page instead of stackoverflow.com content.
- if (refreshDisplay) {
- loadPage();
- }
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (receiver != null) {
- this.unregisterReceiver(receiver);
- }
- }
- // Checks the network connection and sets the wifiConnected and mobileConnected
- // variables accordingly.
- private void updateConnectedFlags() {
- ConnectivityManager connMgr =
- (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
- if (activeInfo != null && activeInfo.isConnected()) {
- wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
- mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
- } else {
- wifiConnected = false;
- mobileConnected = false;
- }
- }
- // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
- // This avoids UI lock up. To prevent network operations from
- // causing a delay that results in a poor user experience, always perform
- // network operations on a separate thread from the UI.
- private void loadPage() {
- if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
- || ((sPref.equals(WIFI)) && (wifiConnected))) {
- // AsyncTask subclass
- new DownloadXmlTask().execute(URL);
- } else {
- showErrorPage();
- }
- }
- // Displays an error if the app is unable to load content.
- private void showErrorPage() {
- setContentView(R.layout.main);
- // The specified network connection is not available. Displays error message.
- WebView myWebView = (WebView) findViewById(R.id.webview);
- myWebView.loadData(getResources().getString(R.string.connection_error),
- "text/html", null);
- }
- // Populates the activity's options menu.
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.mainmenu, menu);
- return true;
- }
- // Handles the user's menu selection.
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.settings:
- Intent settingsActivity = new Intent(getBaseContext(), SettingsActivity.class);
- startActivity(settingsActivity);
- return true;
- case R.id.refresh:
- loadPage();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
- // Implementation of AsyncTask used to download XML feed from stackoverflow.com.
- private class DownloadXmlTask extends AsyncTask<String, Void, String> {
- @Override
- protected String doInBackground(String... urls) {
- try {
- return loadXmlFromNetwork(urls[0]);
- } catch (IOException e) {
- return getResources().getString(R.string.connection_error);
- } catch (XmlPullParserException e) {
- return getResources().getString(R.string.xml_error);
- }
- }
- @Override
- protected void onPostExecute(String result) {
- setContentView(R.layout.main);
- // Displays the HTML string in the UI via a WebView
- WebView myWebView = (WebView) findViewById(R.id.webview);
- myWebView.loadData(result, "text/html", null);
- }
- }
- // Uploads XML from stackoverflow.com, parses it, and combines it with
- // HTML markup. Returns HTML string.
- private String loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
- InputStream stream = null;
- StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser();
- List<Entry> entries = null;
- String title = null;
- String url = null;
- String summary = null;
- Calendar rightNow = Calendar.getInstance();
- DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");
- // Checks whether the user set the preference to include summary text
- SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- boolean pref = sharedPrefs.getBoolean("summaryPref", false);
- StringBuilder htmlString = new StringBuilder();
- htmlString.append("<h3>" + getResources().getString(R.string.page_title) + "</h3>");
- htmlString.append("<em>" + getResources().getString(R.string.updated) + " " +
- formatter.format(rightNow.getTime()) + "</em>");
- try {
- stream = downloadUrl(urlString);
- entries = stackOverflowXmlParser.parse(stream);
- // Makes sure that the InputStream is closed after the app is
- // finished using it.
- } finally {
- if (stream != null) {
- stream.close();
- }
- }
- // StackOverflowXmlParser returns a List (called "entries") of Entry objects.
- // Each Entry object represents a single post in the XML feed.
- // This section processes the entries list to combine each entry with HTML markup.
- // Each entry is displayed in the UI as a link that optionally includes
- // a text summary.
- for (Entry entry : entries) {
- htmlString.append("<p><a href='");
- htmlString.append(entry.link);
- htmlString.append("'>" + entry.title + "</a></p>");
- // If the user set the preference to include summary text,
- // adds it to the display.
- if (pref) {
- htmlString.append(entry.summary);
- }
- }
- return htmlString.toString();
- }
- // Given a string representation of a URL, sets up a connection and gets
- // an input stream.
- private InputStream downloadUrl(String urlString) throws IOException {
- URL url = new URL(urlString);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setReadTimeout(10000 /* milliseconds */);
- conn.setConnectTimeout(15000 /* milliseconds */);
- conn.setRequestMethod("GET");
- conn.setDoInput(true);
- // Starts the query
- conn.connect();
- InputStream stream = conn.getInputStream();
- return stream;
- }
- /**
- *
- * This BroadcastReceiver intercepts the android.net.ConnectivityManager.CONNECTIVITY_ACTION,
- * which indicates a connection change. It checks whether the type is TYPE_WIFI.
- * If it is, it checks whether Wi-Fi is connected and sets the wifiConnected flag in the
- * main activity accordingly.
- *
- */
- public class NetworkReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- ConnectivityManager connMgr =
- (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
- // Checks the user prefs and the network connection. Based on the result, decides
- // whether
- // to refresh the display or keep the current display.
- // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
- if (WIFI.equals(sPref) && networkInfo != null
- && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
- // If device has its Wi-Fi connection, sets refreshDisplay
- // to true. This causes the display to be refreshed when the user
- // returns to the app.
- refreshDisplay = true;
- Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();
- // If the setting is ANY network and there is a network connection
- // (which by process of elimination would be mobile), sets refreshDisplay to true.
- } else if (ANY.equals(sPref) && networkInfo != null) {
- refreshDisplay = true;
- // Otherwise, the app can't download content--either because there is no network
- // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
- // is no Wi-Fi connection.
- // Sets refreshDisplay to false.
- } else {
- refreshDisplay = false;
- Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
- }
- }
- }
- }