diff options
Diffstat (limited to 'samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java')
-rw-r--r-- | samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java b/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java new file mode 100644 index 0000000..b7ed331 --- /dev/null +++ b/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java @@ -0,0 +1,321 @@ +/* + * 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(); + } + } + } +} |