org.peterbaldwin.vlcremote.app.PickServerActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.peterbaldwin.vlcremote.app.PickServerActivity.java

Source

/*-
 *  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);
        }
    }
}