STEP-1 Add 3 permission to AndroidManifest.xml
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
STEP-2 Add below string to values/strings.xml
Strings.xml
<resources> <string name="app_name">NetworkUsage</string> <!-- Menu items --> <string name="settings">Settings</string> <string name="refresh">Refresh</string> <!-- NetworkActivity --> <string name="page_title">Newest StackOverflow questions tagged \'android\'</string> <string name="updated">Last updated:</string> <string name="lost_connection">Lost connection.</string> <string name="wifi_connected">Wi-Fi reconnected.</string> <string name="connection_error">Unable to load content. Check your network connection.</string> <string name="xml_error">Error parsing XML.</string> </resources>
STEP-3 Now create an resource file in res/values/ directory and name it - arrays.xml
arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="listArray"> <item>Only when on Wi-Fi</item> <item>On any network</item> </string-array> <string-array name="listValues"> <item>Wi-Fi</item> <item>Any</item> </string-array> </resources>a
STEP-4 Now, create a directory under res and name it - xml
Goto app --> res --> right click --> new --> directory --> Name it : xml
Now, create xml resource file under xml directory.
preferences.xml
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <ListPreference
android:title="Download Feed"
android:summary="Network connectivity required to download the feed."
android:key="listPref" android:defaultValue="Wi-Fi"
android:entries="@array/listArray"
android:entryValues="@array/listValues" /> <CheckBoxPreference
android:title="Show Summaries"
android:defaultValue="false"
android:summary="Show a summary for each link."
android:key="summaryPref" /> </PreferenceScreen>
STEP-5 Now create a java resource file in app/java/ and name it - SettingsActivity
SettingsActivity.java
import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.PreferenceActivity; import com.example.divakar.xmlparsing.R; /** * This preference activity has in its manifest declaration an intent filter for
* the ACTION_MANAGE_NETWORK_USAGE action. This activity provides a settings UI * for users to
specify network settings to control data usage. */
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Loads the XML preferences file.
addPreferencesFromResource(R.xml.preferences); } @Override
protected void onResume() { super.onResume(); // Registers a callback to be invoked whenever a user changes a preference.
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); } @Override
protected void onPause() { super.onPause(); // Unregisters t he listener set in onResume().
// It's best practice to unregister listeners when your app isn't using them to cut down on
// unnecessary system overhead. You do this in onPause(). getPreferenceScreen() .getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); } // Fires when the user changes a preference.
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // Sets refreshDisplay to true so that when the user returns to the main
// activity, the display refreshes to reflect the new settings.
MainActivity.refreshDisplay = true; } }
STEP-6 Now create an another java resource file in app/java/ and name it -
StackOverflowXmlParser
StackOverflowXmlParser.java
import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class StackOverflowXmlParser { private static final String ns = null; // We don't use namespaces public List<Entry> parse(InputStream in) throws XmlPullParserException, IOException { try { XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(in, null); parser.nextTag(); return readFeed(parser); } finally { in.close(); } } private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException { List<Entry> entries = new ArrayList<Entry>(); parser.require(XmlPullParser.START_TAG, ns, "feed"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); // Starts by looking for the entry tagif (name.equals("entry")) { entries.add(readEntry(parser)); } else { skip(parser); } } return entries; } // This class represents a single entry (post) in the XML feed.// It includes the data members "title," "link," and "summary."public static class Entry { public final String title; public final String link; public final String summary; private Entry(String title, String summary, String link) { this.title = title; this.summary = summary; this.link = link; } } // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them// off // to their respective "read" methods for processing. Otherwise, skips the tag.private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, ns, "entry"); String title = null; String summary = null; String link = null; while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("title")) { title = readTitle(parser); } else if (name.equals("summary")) { summary = readSummary(parser); } else if (name.equals("link")) { link = readLink(parser); } else { skip(parser); } } return new Entry(title, summary, link); } // Processes title tags in the feed.private String readTitle(XmlPullParser parser) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, ns, "title"); String title = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "title"); return title; } // Processes link tags in the feed.private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException { String link = ""; parser.require(XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName(); String relType = parser.getAttributeValue(null, "rel"); if (tag.equals("link")) { if (relType.equals("alternate")) { link = parser.getAttributeValue(null, "href"); parser.nextTag(); } } parser.require(XmlPullParser.END_TAG, ns, "link"); return link; } // Processes summary tags in the feed.private String readSummary(XmlPullParser parser) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, ns, "summary"); String summary = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "summary"); return summary; } // For the tags title and summary, extracts their text values.private String readText(XmlPullParser parser) throws IOException, XmlPullParserException { String result = ""; if (parser.next() == XmlPullParser.TEXT) { result = parser.getText(); parser.nextTag(); } return result; } // Skips tags the parser isn't interested in. Uses depth to handle nested tags. i.e.,// if the next tag after a START_TAG isn't a matching END_TAG, it keeps going until it// finds the matching END_TAG (as indicated by the value of "depth" being 0).private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { if (parser.getEventType() != XmlPullParser.START_TAG) { throw new IllegalStateException(); } int depth = 1; while (depth != 0) { switch (parser.next()) { case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth++; break; } } } }STEP-7 Now, goto your activity_main.xml and paste the below code
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent" android:layout_height="fill_parent"android:orientation="vertical" > <WebView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/webview"android:layout_width="fill_parent"android:layout_height="fill_parent"/> </LinearLayout>STEP-8 Now, paste this below code to java res file.
MainActivity.java
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.divakar.xmlparsing.R; import com.example.divakar.xmlparsing.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; public class MainActivity 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 settingsSharedPreferences 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.activity_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. @Overridepublic boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.mainmenu, menu); return true; } // Handles the user's menu selection. @Overridepublic 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.activity_main); // Displays the HTML string in the UI via a WebViewWebView 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 textSharedPreferences 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(); } } } }
No comments:
Post a Comment