Java tutorial
/*- * Copyright (C) 2009 Peter Baldwin * * 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.peterbaldwin.vlcremote.app; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.NetworkInfo; import android.net.wifi.SupplicantState; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Looper; import android.os.SystemClock; import android.support.v4.app.FragmentActivity; import android.view.Menu; import android.view.MenuItem; import org.peterbaldwin.client.android.vlcremote.R; import org.peterbaldwin.vlcremote.fragment.PickServerFragment; import org.peterbaldwin.vlcremote.fragment.ServerInfoDialog; import org.peterbaldwin.vlcremote.model.Server; import org.peterbaldwin.vlcremote.sweep.PortSweeper; public final class PickServerActivity extends FragmentActivity implements ServerInfoDialog.ServerInfoDialogListener { private static final String TAG = "PickServer"; public static final String STATE_HOSTS = "hosts"; public static final int DEFAULT_WORKERS = 16; private static final int MENU_SCAN = Menu.FIRST; private static byte[] toByteArray(int i) { int i4 = (i >> 24) & 0xFF; int i3 = (i >> 16) & 0xFF; int i2 = (i >> 8) & 0xFF; int i1 = i & 0xFF; return new byte[] { (byte) i1, (byte) i2, (byte) i3, (byte) i4 }; } private PortSweeper mPortSweeper; private BroadcastReceiver mReceiver; private ServerInfoDialog.ServerInfoDialogListener mServerInfoListener; private String mFile; private int mPort; private int mWorkers; private long mCreateTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PickServerFragment fragment = findOrReplaceFragment(android.R.id.content, TAG, PickServerFragment.class); getActionBar().setDisplayHomeAsUpEnabled(true); mPort = getIntent().getIntExtra(PortSweeper.EXTRA_PORT, 0); if (mPort == 0) { throw new IllegalArgumentException("Port must be specified"); } mFile = getIntent().getStringExtra(PortSweeper.EXTRA_FILE); if (mFile == null) { throw new IllegalArgumentException("File must be specified"); } mWorkers = getIntent().getIntExtra(PortSweeper.EXTRA_WORKERS, DEFAULT_WORKERS); mPortSweeper = createPortSweeper(fragment); startSweep(); // Registering the receiver triggers a broadcast with the initial state. // To tell the difference between a broadcast triggered by registering a // receiver and a broadcast triggered by a true network event, note the // time and ignore all broadcasts for one second. mCreateTime = SystemClock.uptimeMillis(); mReceiver = new MyBroadcastReceiver(); // For robustness, update the connection status for all types of events. IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); registerReceiver(mReceiver, filter); } private boolean isInitialBroadcast() { return (SystemClock.uptimeMillis() - mCreateTime) < 1000; } @Override protected void onDestroy() { unregisterReceiver(mReceiver); mReceiver = null; if (mPortSweeper != null) { mPortSweeper.destroy(); } super.onDestroy(); } private PortSweeper createPortSweeper(PortSweeper.Callback callback) { return new PortSweeper(mPort, mFile, mWorkers, callback, Looper.myLooper()); } private WifiInfo getConnectionInfo() { Object service = getSystemService(WIFI_SERVICE); WifiManager manager = (WifiManager) service; WifiInfo info = manager.getConnectionInfo(); if (info != null) { SupplicantState state = info.getSupplicantState(); if (state.equals(SupplicantState.COMPLETED)) { return info; } } return null; } private byte[] getIpAddress() { WifiInfo info = getConnectionInfo(); if (info != null) { return toByteArray(info.getIpAddress()); } return null; } private void startSweep() { byte[] ipAddress = getIpAddress(); if (ipAddress != null) { mPortSweeper.sweep(ipAddress); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuItem scan = menu.add(0, MENU_SCAN, 0, R.string.scan); scan.setIcon(R.drawable.ic_menu_scan_network); scan.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_SCAN: startSweep(); return true; case android.R.id.home: finish(); default: return super.onOptionsItemSelected(item); } } public void setServerInfoDialogListener(ServerInfoDialog.ServerInfoDialogListener l) { mServerInfoListener = l; } public void onAddServer(Server server) { mServerInfoListener.onAddServer(server); } public void onEditServer(Server newServer, String oldServerKey) { mServerInfoListener.onEditServer(newServer, oldServerKey); startSweep(); } private class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Bundle extras = intent.getExtras(); if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { NetworkInfo networkInfo = extras.getParcelable(WifiManager.EXTRA_NETWORK_INFO); NetworkInfo.State state = networkInfo.getState(); if (state == NetworkInfo.State.CONNECTED) { if (isInitialBroadcast()) { // Don't perform a sweep if the broadcast was triggered // as a result of a receiver being registered. } else { startSweep(); } } } } } @SuppressWarnings("unchecked") public <T extends android.app.Fragment> T findOrReplaceFragment(int res, String tag, Class<T> fragmentClass) { try { FragmentManager fm = getFragmentManager(); T fragment = (T) fm.findFragmentByTag(tag); if (fragment == null) { fragment = fragmentClass.newInstance(); FragmentTransaction fragmentTransaction = fm.beginTransaction(); fragmentTransaction.replace(res, fragment, tag); fragmentTransaction.commit(); fm.executePendingTransactions(); } return fragment; } catch (InstantiationException e) { throw new IllegalArgumentException(e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } }