Java tutorial
/******************************************************************************** * (C) Copyright 2000-2010. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ********************************************************************************/ package org.uguess.android.sysinfo; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.URL; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; import android.support.v4.app.ListFragment; import android.text.ClipboardManager; import android.text.Html; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; /** * NetStateManager */ public final class NetStateManager extends ListFragment implements Constants { private static final String PSTORE_NETMANAGER = NetStateManager.class.getSimpleName(); private static final String PREF_KEY_REMOTE_QUERY = "remote_query"; //$NON-NLS-1$ private static final String PREF_KEY_SHOW_REMOTE_NAME = "show_remote_name"; //$NON-NLS-1$ private static final String PREF_KEY_SHOW_LOCAL_ADDRESS = "show_local_address"; //$NON-NLS-1$ private static final int ORDER_TYPE_PROTO = 0; private static final int ORDER_TYPE_LOCAL = 1; private static final int ORDER_TYPE_REMOTE = 2; private static final int ORDER_TYPE_STATE = 3; private static final int ENABLED = 0; private static final int DISABLED = 1; private static final int WIFI_ONLY = 2; private static final String[] SOCKET_STATES = new String[] { "ESTABLISHED", //$NON-NLS-1$ "SYN_SENT", //$NON-NLS-1$ "SYN_RECV", //$NON-NLS-1$ "FIN_WAIT1", //$NON-NLS-1$ "FIN_WAIT2", //$NON-NLS-1$ "TIME_WAIT", //$NON-NLS-1$ "CLOSE", //$NON-NLS-1$ "CLOSE_WAIT", //$NON-NLS-1$ "LAST_ACK", //$NON-NLS-1$ "LISTEN", //$NON-NLS-1$ "CLOSING" //$NON-NLS-1$ }; ConnectionItem dummyInfo; HashMap<String, IpInfo> queryCache; ProgressDialog progress; volatile boolean aborted; Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case MSG_CONTENT_READY: if (aborted) { return; } showIpInfo((IpInfo) msg.obj, getActivity()); this.post(task); break; case MSG_DISMISS_PROGRESS: if (progress != null) { progress.dismiss(); progress = null; } break; } }; }; Runnable task = new Runnable() { public void run() { refresh(); int interval = Util.getIntOption(getActivity(), PSTORE_NETMANAGER, PREF_KEY_REFRESH_INTERVAL, REFRESH_LOW); switch (interval) { case REFRESH_HIGH: handler.postDelayed(this, 1000); break; case REFRESH_NORMAL: handler.postDelayed(this, 2000); break; case REFRESH_LOW: handler.postDelayed(this, 4000); break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); queryCache = new HashMap<String, IpInfo>(); dummyInfo = new ConnectionItem(); dummyInfo.proto = getString(R.string.protocol); dummyInfo.local = getString(R.string.local_remote_addr); dummyInfo.state = getString(R.string.state); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); ListView listView = (ListView) view.findViewById(android.R.id.list); registerForContextMenu(listView); ArrayAdapter<ConnectionItem> adapter = new ArrayAdapter<ConnectionItem>(getActivity(), R.layout.net_item) { public android.view.View getView(int position, android.view.View convertView, android.view.ViewGroup parent) { View view; TextView txt_proto, txt_ip, txt_state; Activity ctx = getActivity(); if (convertView == null) { view = ctx.getLayoutInflater().inflate(R.layout.net_item, parent, false); } else { view = convertView; } if (position >= getCount()) { return view; } ConnectionItem itm = getItem(position); txt_proto = (TextView) view.findViewById(R.id.txt_proto); txt_ip = (TextView) view.findViewById(R.id.txt_ip); txt_state = (TextView) view.findViewById(R.id.txt_state); txt_proto.setText(itm.proto); txt_state.setText(itm.state); boolean showLocal = Util.getBooleanOption(ctx, PSTORE_NETMANAGER, PREF_KEY_SHOW_LOCAL_ADDRESS); if (itm == dummyInfo) { if (showLocal) { txt_ip.setText(R.string.local_remote_addr); } else { txt_ip.setText(R.string.remote_address); } txt_proto.setTextColor(Color.WHITE); txt_ip.setTextColor(Color.WHITE); txt_state.setTextColor(Color.WHITE); } else { if (showLocal) { txt_ip.setText(itm.local + '\n' + (itm.remoteName == null ? itm.remote : itm.remoteName)); } else { txt_ip.setText(itm.remoteName == null ? itm.remote : itm.remoteName); } txt_proto.setTextAppearance(ctx, android.R.style.TextAppearance_Small); txt_ip.setTextAppearance(ctx, android.R.style.TextAppearance_Small); txt_state.setTextAppearance(ctx, android.R.style.TextAppearance_Small); } return view; } }; setListAdapter(adapter); return view; } @Override public void onListItemClick(ListView l, View v, int position, long id) { if (position > 0) { int state = Util.getIntOption(getActivity(), PSTORE_NETMANAGER, PREF_KEY_REMOTE_QUERY, ENABLED); if (state == DISABLED) { return; } else if (state == WIFI_ONLY) { ConnectivityManager cm = (ConnectivityManager) getActivity() .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (info == null || !info.isConnected()) { return; } } ConnectionItem itm = (ConnectionItem) l.getItemAtPosition(position); String ip = getValidIP(itm.remote); if (!TextUtils.isEmpty(ip)) { queryIPInfo(ip); } else { Util.shortToast(getActivity(), R.string.no_ip_info); } } } @Override public void onDestroyView() { if (progress != null) { progress.dismiss(); progress = null; } ((ArrayAdapter<ConnectionItem>) getListView().getAdapter()).clear(); super.onDestroyView(); } @Override public void onDestroy() { super.onDestroy(); } @Override public void onResume() { aborted = false; super.onResume(); handler.post(task); } @Override public void onPause() { aborted = true; handler.removeCallbacks(task); handler.removeMessages(MSG_CONTENT_READY); super.onPause(); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { MenuItem mi = menu.add(Menu.NONE, MI_PREFERENCE, Menu.NONE, R.string.preference); mi.setIcon(android.R.drawable.ic_menu_preferences); Util.setShowAsAction(mi, MenuItem.SHOW_AS_ACTION_NEVER); } @Override public boolean onOptionsItemSelected(MenuItem item) { Activity ctx = getActivity(); if (item.getItemId() == MI_PREFERENCE) { Intent it = new Intent(ctx, NetStateSettings.class); it.putExtra(PREF_KEY_REFRESH_INTERVAL, Util.getIntOption(ctx, PSTORE_NETMANAGER, PREF_KEY_REFRESH_INTERVAL, REFRESH_LOW)); it.putExtra(PREF_KEY_REMOTE_QUERY, Util.getIntOption(ctx, PSTORE_NETMANAGER, PREF_KEY_REMOTE_QUERY, ENABLED)); it.putExtra(PREF_KEY_SHOW_REMOTE_NAME, Util.getBooleanOption(ctx, PSTORE_NETMANAGER, PREF_KEY_SHOW_REMOTE_NAME)); it.putExtra(PREF_KEY_SHOW_LOCAL_ADDRESS, Util.getBooleanOption(ctx, PSTORE_NETMANAGER, PREF_KEY_SHOW_LOCAL_ADDRESS)); it.putExtra(PREF_KEY_SORT_ORDER_TYPE, Util.getIntOption(ctx, PSTORE_NETMANAGER, PREF_KEY_SORT_ORDER_TYPE, ORDER_TYPE_PROTO)); it.putExtra(PREF_KEY_SORT_DIRECTION, Util.getIntOption(ctx, PSTORE_NETMANAGER, PREF_KEY_SORT_DIRECTION, ORDER_ASC)); startActivityForResult(it, 1); return true; } return false; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { int pos = ((AdapterContextMenuInfo) menuInfo).position; if (pos > 0) { menu.setHeaderTitle(R.string.actions); menu.add(R.string.copy_ip); } } @Override public boolean onContextItemSelected(MenuItem item) { int pos = ((AdapterContextMenuInfo) item.getMenuInfo()).position; if (pos > 0 && pos < getListView().getCount()) { ConnectionItem itm = (ConnectionItem) getListView().getItemAtPosition(pos); if (itm != null && !TextUtils.isEmpty(itm.remote)) { ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); if (cm != null) { cm.setText(itm.remoteName == null ? itm.remote : itm.remoteName); Util.shortToast(getActivity(), R.string.copied_hint); } } return true; } return false; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { Activity ctx = getActivity(); if (requestCode == 1 && data != null) { Util.updateIntOption(data, ctx, PSTORE_NETMANAGER, PREF_KEY_REFRESH_INTERVAL, REFRESH_LOW); Util.updateIntOption(data, ctx, PSTORE_NETMANAGER, PREF_KEY_REMOTE_QUERY, ENABLED); Util.updateIntOption(data, ctx, PSTORE_NETMANAGER, PREF_KEY_SORT_ORDER_TYPE, ORDER_TYPE_PROTO); Util.updateIntOption(data, ctx, PSTORE_NETMANAGER, PREF_KEY_SORT_DIRECTION, ORDER_ASC); Util.updateBooleanOption(data, ctx, PSTORE_NETMANAGER, PREF_KEY_SHOW_REMOTE_NAME); Util.updateBooleanOption(data, ctx, PSTORE_NETMANAGER, PREF_KEY_SHOW_LOCAL_ADDRESS); } } static String getValidIP(String ip) { if (ip != null) { int idx = ip.lastIndexOf(':'); if (idx != -1) { ip = ip.substring(0, idx).trim(); } if (!"0.0.0.0".equals(ip) && !"127.0.0.1".equals(ip)) //$NON-NLS-1$ //$NON-NLS-2$ { return ip; } } return null; } void queryIPInfo(final String ip) { IpInfo info = queryCache.get(ip); if (info != null) { handler.sendMessage(handler.obtainMessage(MSG_CONTENT_READY, info)); return; } if (progress != null) { progress.dismiss(); } progress = new ProgressDialog(getActivity()); progress.setMessage(getString(R.string.query_ip_msg)); progress.setIndeterminate(true); progress.show(); new Thread(new Runnable() { public void run() { IpInfo info = new IpInfo(); info.ip = ip; info = getIpInfo(info); queryCache.put(ip, info); handler.sendEmptyMessage(MSG_DISMISS_PROGRESS); handler.sendMessage(handler.obtainMessage(MSG_CONTENT_READY, info)); } }).start(); } void refresh() { ArrayList<ConnectionItem> data = new ArrayList<ConnectionItem>(); data.add(dummyInfo); ArrayList<ConnectionItem> items = readStatesRaw(); if (items != null) { final int type = Util.getIntOption(getActivity(), PSTORE_NETMANAGER, PREF_KEY_SORT_ORDER_TYPE, ORDER_TYPE_PROTO); final int direction = Util.getIntOption(getActivity(), PSTORE_NETMANAGER, PREF_KEY_SORT_DIRECTION, ORDER_ASC); final Collator clt = Collator.getInstance(); switch (type) { case ORDER_TYPE_PROTO: Collections.sort(items, new Comparator<ConnectionItem>() { public int compare(ConnectionItem obj1, ConnectionItem obj2) { return clt.compare(obj1.proto, obj2.proto) * direction; } }); break; case ORDER_TYPE_LOCAL: Collections.sort(items, new Comparator<ConnectionItem>() { public int compare(ConnectionItem obj1, ConnectionItem obj2) { return clt.compare(obj1.local, obj2.local) * direction; } }); break; case ORDER_TYPE_REMOTE: Collections.sort(items, new Comparator<ConnectionItem>() { public int compare(ConnectionItem obj1, ConnectionItem obj2) { return clt.compare(obj1.remoteName == null ? obj1.remote : obj1.remoteName, obj2.remoteName == null ? obj2.remote : obj2.remoteName) * direction; } }); break; case ORDER_TYPE_STATE: Collections.sort(items, new Comparator<ConnectionItem>() { public int compare(ConnectionItem obj1, ConnectionItem obj2) { return clt.compare(obj1.state == null ? "" //$NON-NLS-1$ : obj1.state, obj2.state == null ? "" //$NON-NLS-1$ : obj2.state) * direction; } }); break; } data.addAll(items); } ArrayAdapter<ConnectionItem> adapter = (ArrayAdapter<ConnectionItem>) getListView().getAdapter(); adapter.setNotifyOnChange(false); adapter.clear(); for (int i = 0, size = data.size(); i < size; i++) { adapter.add(data.get(i)); } adapter.notifyDataSetChanged(); if (adapter.getCount() == 1) { Log.d(NetStateManager.class.getName(), "No network traffic detected"); //$NON-NLS-1$ } } void setFont(TextView txt, int type) { if (txt.getTypeface() == null || txt.getTypeface().getStyle() != type) { txt.setTypeface(Typeface.DEFAULT, type); } } private ArrayList<ConnectionItem> readStatesRaw() { ArrayList<ConnectionItem> items = new ArrayList<NetStateManager.ConnectionItem>(); Activity ctx = getActivity(); parseRawData(items, ctx, queryCache, "TCP", "/proc/net/tcp", false); //$NON-NLS-1$ //$NON-NLS-2$ parseRawData(items, ctx, queryCache, "UDP", "/proc/net/udp", true); //$NON-NLS-1$ //$NON-NLS-2$ parseRawData(items, ctx, queryCache, "TCP", "/proc/net/tcp6", false); //$NON-NLS-1$ //$NON-NLS-2$ parseRawData(items, ctx, queryCache, "UDP", "/proc/net/udp6", true); //$NON-NLS-1$ //$NON-NLS-2$ return items; } private static void parseRawData(final ArrayList<ConnectionItem> items, Activity ac, HashMap<String, IpInfo> queryCache, String proto, String source, boolean ignoreState) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(source)), 4096); boolean first = true; int localOffset = -1, remOffset = -1, stateOffset = -1, stateEndOffset = -1; String line; final boolean showRemoteName = Util.getBooleanOption(ac, PSTORE_NETMANAGER, PREF_KEY_SHOW_REMOTE_NAME); String remoteIp; int portIdx; IpInfo remoteInfo; while ((line = reader.readLine()) != null) { if (first) { localOffset = line.indexOf("local_address"); //$NON-NLS-1$ remOffset = line.indexOf("rem_address"); //$NON-NLS-1$ if (remOffset == -1) { remOffset = line.indexOf("remote_address"); //$NON-NLS-1$ } stateOffset = line.indexOf("st", remOffset); //$NON-NLS-1$ stateEndOffset = line.indexOf(' ', stateOffset); if (localOffset == -1 || remOffset == -1 || stateOffset == -1 || stateEndOffset == -1) { Log.e(NetStateManager.class.getName(), "Unexpected " //$NON-NLS-1$ + proto + " header format: " //$NON-NLS-1$ + line); break; } first = false; } else { ConnectionItem ci = new ConnectionItem(); ci.proto = proto; ci.local = parseRawIP(line.substring(localOffset, remOffset).trim()); ci.remote = parseRawIP(line.substring(remOffset, stateOffset).trim()); if (showRemoteName) { remoteIp = getValidIP(ci.remote); if (remoteIp != null) { remoteInfo = queryCache.get(remoteIp); if (remoteInfo != null && !TextUtils.isEmpty(remoteInfo.host)) { portIdx = ci.remote.lastIndexOf(':'); if (portIdx != -1) { ci.remoteName = remoteInfo.host + ci.remote.substring(portIdx); } else { ci.remoteName = remoteInfo.host; } } } } if (!ignoreState) { int st = Integer.parseInt(line.substring(stateOffset, stateEndOffset).trim(), 16); ci.state = "Unknown"; //$NON-NLS-1$ if (st > 0 && st <= SOCKET_STATES.length) { ci.state = SOCKET_STATES[st - 1]; } } items.add(ci); } } } catch (FileNotFoundException fe) { Log.d(NetStateManager.class.getName(), "File not found: " + fe.getLocalizedMessage()); //$NON-NLS-1$ } catch (Exception e) { Log.e(NetStateManager.class.getName(), e.getLocalizedMessage(), e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { Log.e(NetStateManager.class.getName(), e.getLocalizedMessage(), e); } } } } private static String parseRawIP(String raw) { if (!TextUtils.isEmpty(raw)) { int idx = raw.lastIndexOf(':'); if (idx != -1) { String port = raw.substring(idx + 1).trim(); String ip = raw.substring(0, idx).trim(); try { int pt = Integer.parseInt(port, 16); if (pt == 0) { port = "*"; //$NON-NLS-1$ } else { port = String.valueOf(pt); } } catch (Exception e) { port = "?"; //$NON-NLS-1$ Log.e(NetStateManager.class.getName(), "Parsing raw port fail : " + raw); //$NON-NLS-1$ } if (ip.length() == 8) { try { int n1 = Integer.parseInt(ip.substring(6), 16); int n2 = Integer.parseInt(ip.substring(4, 6), 16); int n3 = Integer.parseInt(ip.substring(2, 4), 16); int n4 = Integer.parseInt(ip.substring(0, 2), 16); ip = n1 + "." + n2 + "." + n3 + "." + n4; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } catch (Exception e) { ip = "?"; //$NON-NLS-1$ Log.e(NetStateManager.class.getName(), "Parsing raw ip4 fail : " + raw); //$NON-NLS-1$ } } else if (ip.length() == 32) { try { int n1 = Integer.parseInt(ip.substring(30), 16); int n2 = Integer.parseInt(ip.substring(28, 30), 16); int n3 = Integer.parseInt(ip.substring(26, 28), 16); int n4 = Integer.parseInt(ip.substring(24, 26), 16); ip = n1 + "." + n2 + "." + n3 + "." + n4; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } catch (Exception e) { ip = "?"; //$NON-NLS-1$ Log.e(NetStateManager.class.getName(), "Parsing raw ip6 fail : " + raw); //$NON-NLS-1$ } } else { Log.e(NetStateManager.class.getName(), "Parsing raw ip fail : " + raw); //$NON-NLS-1$ } return ip + ':' + port; } } return raw; } static void showIpInfo(final IpInfo info, final Activity context) { if (info != null && !TextUtils.isEmpty(info.latitude) && !TextUtils.isEmpty(info.longitude)) { OnClickListener listener = new OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent it = new Intent(Intent.ACTION_VIEW); it.setData(Uri.parse("geo:0,0?q=" //$NON-NLS-1$ + info.latitude + "," //$NON-NLS-1$ + info.longitude + "&z=8")); //$NON-NLS-1$ it = Intent.createChooser(it, null); context.startActivity(it); } }; TextView txt = new TextView(context); txt.setPadding(15, 0, 15, 0); txt.setTextAppearance(context, android.R.style.TextAppearance_Medium); txt.setText(Html.fromHtml(context.getString( R.string.location_info, info.ip, info.host == null ? "" //$NON-NLS-1$ : ("<a href=\"http://" //$NON-NLS-1$ + info.host + "\">" //$NON-NLS-1$ + info.host + "</a><br>"), //$NON-NLS-1$ info.country == null ? "" : info.country, //$NON-NLS-1$ info.region == null ? "" : info.region, //$NON-NLS-1$ info.city == null ? "" : info.city))); //$NON-NLS-1$ txt.setMovementMethod(LinkMovementMethod.getInstance()); new AlertDialog.Builder(context).setTitle(R.string.ip_location) .setPositiveButton(R.string.view_map, listener).setNegativeButton(R.string.close, null) .setView(txt).create().show(); } else { Util.shortToast(context, R.string.no_ip_info); } } static IpInfo getIpInfo(IpInfo info) { if (info == null) { info = new IpInfo(); } InputStream input = null; try { URL url; if (info.ip == null) { url = new URL( "http://api.ipinfodb.com/v2/ip_query.php?key=a1d74831f68f12aa61307b387b0d17cf2501d9c368172a9c73ad120f149c73d4"); //$NON-NLS-1$ } else { url = new URL( "http://api.ipinfodb.com/v2/ip_query.php?key=a1d74831f68f12aa61307b387b0d17cf2501d9c368172a9c73ad120f149c73d4&ip=" //$NON-NLS-1$ + info.ip); } XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); input = url.openStream(); parser.setInput(input, null); String name, value; while (parser.next() != XmlPullParser.END_DOCUMENT) { if (parser.getEventType() == XmlPullParser.START_TAG) { name = parser.getName(); if (info.ip == null && "Ip".equals(name)) //$NON-NLS-1$ { info.ip = parser.nextText(); } else if ("Status".equals(name)) //$NON-NLS-1$ { value = parser.nextText(); if (!"OK".equals(value)) //$NON-NLS-1$ { Log.d(NetStateManager.class.getName(), "Status returned: [" //$NON-NLS-1$ + value + "] for ip: " //$NON-NLS-1$ + info.ip); break; } } else if ("CountryName".equals(name)) //$NON-NLS-1$ { value = parser.nextText(); if ("Reserved".equals(value)) //$NON-NLS-1$ { Log.d(NetStateManager.class.getName(), "Reserved ip?: " + info.ip); //$NON-NLS-1$ break; } info.country = value; } else if ("RegionName".equals(name)) //$NON-NLS-1$ { info.region = parser.nextText(); } else if ("City".equals(name)) //$NON-NLS-1$ { info.city = parser.nextText(); } else if ("Latitude".equals(name)) //$NON-NLS-1$ { info.latitude = parser.nextText(); } else if ("Longitude".equals(name)) //$NON-NLS-1$ { info.longitude = parser.nextText(); } } } if (info.ip != null) { String host = InetAddress.getByName(info.ip).getHostName(); if (!info.ip.equals(host)) { info.host = host; } } } catch (Exception e) { Log.e(NetStateManager.class.getName(), e.getLocalizedMessage(), e); } finally { if (input != null) { try { input.close(); } catch (IOException e) { Log.e(NetStateManager.class.getName(), e.getLocalizedMessage(), e); } } } return info; } /** * NetStateSettings */ public static final class NetStateSettings extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); setPreferenceScreen(getPreferenceManager().createPreferenceScreen(this)); PreferenceCategory pc = new PreferenceCategory(this); pc.setTitle(R.string.preference); getPreferenceScreen().addPreference(pc); Preference perfInterval = new Preference(this); perfInterval.setKey(PREF_KEY_REFRESH_INTERVAL); perfInterval.setTitle(R.string.update_speed); pc.addPreference(perfInterval); Preference perfRemote = new Preference(this); perfRemote.setKey(PREF_KEY_REMOTE_QUERY); perfRemote.setTitle(R.string.remote_query); pc.addPreference(perfRemote); CheckBoxPreference perfRemoteName = new CheckBoxPreference(this); perfRemoteName.setKey(PREF_KEY_SHOW_REMOTE_NAME); perfRemoteName.setTitle(R.string.display_remote_name); perfRemoteName.setSummary(R.string.show_remote_msg); pc.addPreference(perfRemoteName); CheckBoxPreference perfShowLocal = new CheckBoxPreference(this); perfShowLocal.setKey(PREF_KEY_SHOW_LOCAL_ADDRESS); perfShowLocal.setTitle(R.string.show_local_addr); perfShowLocal.setSummary(R.string.show_local_addr_sum); pc.addPreference(perfShowLocal); pc = new PreferenceCategory(this); pc.setTitle(R.string.sort); getPreferenceScreen().addPreference(pc); Preference perfSortType = new Preference(this); perfSortType.setKey(PREF_KEY_SORT_ORDER_TYPE); perfSortType.setTitle(R.string.sort_type); pc.addPreference(perfSortType); Preference perfSortDirection = new Preference(this); perfSortDirection.setKey(PREF_KEY_SORT_DIRECTION); perfSortDirection.setTitle(R.string.sort_direction); pc.addPreference(perfSortDirection); refreshInterval(); refreshRemoteQuery(); refreshBooleanOption(PREF_KEY_SHOW_REMOTE_NAME); refreshBooleanOption(PREF_KEY_SHOW_LOCAL_ADDRESS); refreshSortType(); refreshSortDirection(); setResult(RESULT_OK, getIntent()); } void refreshInterval() { int interval = getIntent().getIntExtra(PREF_KEY_REFRESH_INTERVAL, REFRESH_NORMAL); CharSequence label = getString(R.string.normal); switch (interval) { case REFRESH_HIGH: label = getString(R.string.high); break; case REFRESH_LOW: label = getString(R.string.low); break; case REFRESH_PAUSED: label = getString(R.string.paused); break; } findPreference(PREF_KEY_REFRESH_INTERVAL).setSummary(label); } void refreshRemoteQuery() { int state = getIntent().getIntExtra(PREF_KEY_REMOTE_QUERY, ENABLED); CharSequence label = getString(R.string.wifi_only); switch (state) { case DISABLED: label = getString(R.string.disabled); break; case ENABLED: label = getString(R.string.enabled); break; } findPreference(PREF_KEY_REMOTE_QUERY).setSummary(label); } void refreshBooleanOption(String key) { boolean val = getIntent().getBooleanExtra(key, true); ((CheckBoxPreference) findPreference(key)).setChecked(val); } void refreshSortType() { int type = getIntent().getIntExtra(PREF_KEY_SORT_ORDER_TYPE, ORDER_TYPE_PROTO); String label = null; switch (type) { case ORDER_TYPE_PROTO: label = getString(R.string.protocol); break; case ORDER_TYPE_LOCAL: label = getString(R.string.local_address); break; case ORDER_TYPE_REMOTE: label = getString(R.string.remote_address); break; case ORDER_TYPE_STATE: label = getString(R.string.state); break; } findPreference(PREF_KEY_SORT_ORDER_TYPE).setSummary(label); } void refreshSortDirection() { int type = getIntent().getIntExtra(PREF_KEY_SORT_DIRECTION, ORDER_ASC); String label = type == ORDER_ASC ? getString(R.string.ascending) : getString(R.string.descending); findPreference(PREF_KEY_SORT_DIRECTION).setSummary(label); } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { final Intent it = getIntent(); final String prefKey = preference.getKey(); if (PREF_KEY_REFRESH_INTERVAL.equals(prefKey)) { OnClickListener listener = new OnClickListener() { public void onClick(DialogInterface dialog, int which) { it.putExtra(PREF_KEY_REFRESH_INTERVAL, which); dialog.dismiss(); refreshInterval(); } }; new AlertDialog.Builder(this).setTitle(R.string.update_speed).setNeutralButton(R.string.close, null) .setSingleChoiceItems( new CharSequence[] { getString(R.string.high), getString(R.string.normal), getString(R.string.low), getString(R.string.paused), }, it.getIntExtra(PREF_KEY_REFRESH_INTERVAL, REFRESH_NORMAL), listener) .create().show(); return true; } else if (PREF_KEY_REMOTE_QUERY.equals(prefKey)) { OnClickListener listener = new OnClickListener() { public void onClick(DialogInterface dialog, int which) { it.putExtra(PREF_KEY_REMOTE_QUERY, which); dialog.dismiss(); refreshRemoteQuery(); } }; new AlertDialog.Builder(this).setTitle(R.string.remote_query).setNeutralButton(R.string.close, null) .setSingleChoiceItems( new CharSequence[] { getString(R.string.enabled), getString(R.string.disabled), getString(R.string.wifi_only), }, it.getIntExtra(PREF_KEY_REMOTE_QUERY, ENABLED), listener) .create().show(); return true; } else if (PREF_KEY_SHOW_REMOTE_NAME.equals(prefKey)) { it.putExtra(PREF_KEY_SHOW_REMOTE_NAME, ((CheckBoxPreference) findPreference(PREF_KEY_SHOW_REMOTE_NAME)).isChecked()); return true; } else if (PREF_KEY_SHOW_LOCAL_ADDRESS.equals(prefKey)) { it.putExtra(PREF_KEY_SHOW_LOCAL_ADDRESS, ((CheckBoxPreference) findPreference(PREF_KEY_SHOW_LOCAL_ADDRESS)).isChecked()); return true; } else if (PREF_KEY_SORT_ORDER_TYPE.equals(prefKey)) { OnClickListener listener = new OnClickListener() { public void onClick(DialogInterface dialog, int which) { it.putExtra(PREF_KEY_SORT_ORDER_TYPE, which); dialog.dismiss(); refreshSortType(); } }; new AlertDialog.Builder(this).setTitle(R.string.sort_type).setNeutralButton(R.string.close, null) .setSingleChoiceItems( new String[] { getString(R.string.protocol), getString(R.string.local_address), getString(R.string.remote_address), getString(R.string.state), }, it.getIntExtra(PREF_KEY_SORT_ORDER_TYPE, ORDER_TYPE_PROTO), listener) .create().show(); return true; } else if (PREF_KEY_SORT_DIRECTION.equals(prefKey)) { OnClickListener listener = new OnClickListener() { public void onClick(DialogInterface dialog, int which) { it.putExtra(PREF_KEY_SORT_DIRECTION, which == 0 ? ORDER_ASC : ORDER_DESC); dialog.dismiss(); refreshSortDirection(); } }; new AlertDialog.Builder(this).setTitle(R.string.sort_direction) .setNeutralButton(R.string.close, null) .setSingleChoiceItems( new String[] { getString(R.string.ascending), getString(R.string.descending), }, it.getIntExtra(PREF_KEY_SORT_DIRECTION, ORDER_ASC) == ORDER_ASC ? 0 : 1, listener) .create().show(); return true; } return false; } } /** * ConnectionItem */ private static final class ConnectionItem { String proto; String local; String remote; String remoteName; String state; ConnectionItem() { } } /** * IpInfo */ static final class IpInfo { String country, region, city; String latitude, longitude; String ip, host; } }