Java tutorial
/* * Copyright (C) 2009 Google Inc. All rights reserved. * * 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.google.android.apps.tvremote; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.DhcpInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.Settings; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import android.text.InputFilter; import android.text.InputType; import android.text.TextUtils; import android.text.method.NumberKeyListener; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.cnm.cnmrc.CnmPreferences; import com.cnm.cnmrc.R; import com.cnm.cnmrc.popup.PopupGtvManuallyInput; import com.cnm.cnmrc.popup.PopupGtvSearching; import com.cnm.cnmrc.popup.PopupGtvTimeout; /** * Device discovery with mDNS. */ public final class DeviceFinder extends FragmentActivity { private static final String LOG_TAG = "DeviceFinder"; /** * Request code used by wifi settings activity */ private static final int CODE_WIFI_SETTINGS = 1; private ProgressDialog progressDialog; private AlertDialog confirmationDialog; private RemoteDevice previousRemoteDevice; private List<RemoteDevice> recentlyConnectedDevices; private InetAddress broadcastAddress; private WifiManager wifiManager; private boolean active; /** * Handles used to pass data back to calling activities. */ public static final String EXTRA_REMOTE_DEVICE = "remote_device"; public static final String EXTRA_RECENTLY_CONNECTED = "recently_connected"; public DeviceFinder() { // deviceList = new ArrayList<DeviceInfo>(); // dataAdapter = new DeviceFinderListAdapter(this, deviceList); trackedDevices = new TrackedDevices(); } private boolean isPopupShowing = false; private final String TAG_FRAGMENT_POPUP = "tvremote-popup"; ArrayList<DeviceInfo> deviceList; static Context mContext; /** * Returns an intent that starts this activity. */ public static Intent createConnectIntent(Context ctx, RemoteDevice recentlyConnected, ArrayList<RemoteDevice> recentlyConnectedList) { mContext = ctx; Intent intent = new Intent(ctx, DeviceFinder.class); intent.putExtra(EXTRA_REMOTE_DEVICE, recentlyConnected); intent.putParcelableArrayListExtra(EXTRA_RECENTLY_CONNECTED, recentlyConnectedList); return intent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("hwang-tvremote", "DeviceFinder : onCreate()"); setContentView(R.layout.gtv_device_finder_layout); previousRemoteDevice = getIntent().getParcelableExtra(EXTRA_REMOTE_DEVICE); recentlyConnectedDevices = getIntent().getParcelableArrayListExtra(EXTRA_RECENTLY_CONNECTED); broadcastHandler = new BroadcastHandler(); wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); deviceList = new ArrayList<DeviceInfo>(); stbList = (ListView) findViewById(R.id.stb_list); stbList.setOnItemClickListener(selectHandler); stbList.setDivider(null); stbList.setDividerHeight(0); dataAdapter = new DeviceFinderListAdapter(this, R.layout.list_item_gtv_device_finder, deviceList); stbList.setAdapter(dataAdapter); findViewById(R.id.device_finder).setVisibility(View.INVISIBLE); // ((Button) findViewById(R.id.button_manual)).setOnClickListener(new View.OnClickListener() { // public void onClick(View v) { // buildManualIpDialog().show(); // } // }); // deviceList = new ArrayList<DeviceInfo>(); // // //ArrayList<DeviceInfo> deviceList = new ArrayList<DeviceInfo>(); // DeviceInfo deviceInfo; // // deviceInfo = new DeviceInfo("stb_catv_cnm-192-168-0-25", "192.168.0.21"); // deviceList.add(deviceInfo); // // deviceInfo = new DeviceInfo("IP ? .", ""); // deviceList.add(deviceInfo); // MyListAdapter myAdapter = new MyListAdapter(this, R.layout.list_item_gtv_device_finder, deviceList); // stbList.setAdapter(myAdapter); // DeviceFinderListAdapter dataAdapter1 = new DeviceFinderListAdapter(this, R.layout.list_item_gtv_device_finder, deviceList); // stbList.setAdapter(dataAdapter1); // dataAdapter.notifyDataSetChanged(); } @Override protected void onStart() { super.onStart(); Log.d("hwang-tvremote", "DeviceFinder : onStart()"); try { broadcastAddress = getBroadcastAddress(); Log.d("hwang-tvremote", "DeviceFinder : broadcastAddress : " + broadcastAddress); } catch (IOException e) { Log.e(LOG_TAG, "Failed to get broadcast address"); setResult(RESULT_CANCELED, null); finish(); } startBroadcast(); } private void startBroadcast() { if (!isWifiAvailable()) { //buildNoWifiDialog().show(); // hwang showPopupNoWifi(); return; } broadcastClient = new BroadcastDiscoveryClient(broadcastAddress, broadcastHandler); broadcastClientThread = new Thread(broadcastClient); broadcastClientThread.start(); Message message = DelayedMessage.BROADCAST_TIMEOUT.obtainMessage(broadcastHandler); broadcastHandler.sendMessageDelayed(message, getResources().getInteger(R.integer.broadcast_timeout)); showProgressDialog(buildBroadcastProgressDialog()); // hwang showPopupBroadcastSearching(); } private void showProgressDialog(ProgressDialog newDialog) { if ((progressDialog != null) && progressDialog.isShowing()) { progressDialog.dismiss(); } progressDialog = newDialog; //newDialog.show(); // hwang if (isPopupShowing) { Fragment f = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_POPUP); getSupportFragmentManager().beginTransaction().remove(f).commit(); isPopupShowing = false; } } @Override protected void onPause() { Log.d("hwang-tvremote", "DeviceFinder : onPause()"); active = false; broadcastHandler.removeMessages(DELAYED_MESSAGE); super.onPause(); } @Override protected void onResume() { super.onResume(); active = true; Log.d("hwang-tvremote", "DeviceFinder : onResume()"); } @Override protected void onStop() { Log.d("hwang-tvremote", "DeviceFinder : onStop()"); if (null != broadcastClient) { broadcastClient.stop(); broadcastClient = null; } super.onStop(); } @Override protected void onDestroy() { Log.d("hwang-tvremote", "DeviceFinder : onDestroy()"); super.onDestroy(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d(LOG_TAG, "ActivityResult: " + requestCode + ", " + resultCode); if (requestCode == CODE_WIFI_SETTINGS) { if (!isWifiAvailable()) { buildNoWifiDialog().show(); } else { startBroadcast(); } } } // -------------------- // No Wifi available // -------------------- private AlertDialog buildNoWifiDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.finder_wifi_not_available); builder.setCancelable(false); builder.setPositiveButton(R.string.finder_configure, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int id) { Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS); startActivityForResult(intent, CODE_WIFI_SETTINGS); } }); builder.setNegativeButton(R.string.finder_cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int id) { setResult(RESULT_CANCELED, null); finish(); } }); return builder.create(); } private void showPopupNoWifi() { Log.e("hwang-tvremote", "DeviceFinder : showPopupNoWifi (?)"); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); PopupGtvTimeout popupGtvTimeout = new PopupGtvTimeout(); popupGtvTimeout.show(ft, PopupGtvTimeout.class.getSimpleName()); } // -------------------- // Searching... // -------------------- private ProgressDialog buildBroadcastProgressDialog() { String message; String networkName = getNetworkName(); if (!TextUtils.isEmpty(networkName)) { message = getString(R.string.finder_searching_with_ssid, networkName); } else { message = getString(R.string.finder_searching); } return buildProgressDialog(message, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int which) { broadcastHandler.removeMessages(DELAYED_MESSAGE); showOtherDevices(); } }); } private ProgressDialog buildProgressDialog(String message, DialogInterface.OnClickListener cancelListener) { ProgressDialog dialog = new ProgressDialog(this); dialog.setMessage(message); dialog.setOnKeyListener(new DialogInterface.OnKeyListener() { public boolean onKey(DialogInterface dialogInterface, int which, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { finish(); return true; } return false; } }); dialog.setButton(getString(R.string.finder_cancel), cancelListener); return dialog; } private void showPopupBroadcastSearching() { String message; String networkName = getNetworkName(); if (!TextUtils.isEmpty(networkName)) { message = getString(R.string.finder_searching_with_ssid, networkName); } else { message = getString(R.string.finder_searching); } if (isPopupShowing) { Fragment f = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_POPUP); getSupportFragmentManager().beginTransaction().remove(f).commit(); isPopupShowing = false; } FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); PopupGtvSearching popupGtvSearching = new PopupGtvSearching(); popupGtvSearching.show(ft, TAG_FRAGMENT_POPUP); isPopupShowing = true; } public void removeDelayedMessage() { broadcastHandler.removeMessages(DELAYED_MESSAGE); // when cancel button is clicked!!! } // ----------------------- // ? // ----------------------- private AlertDialog buildConfirmationDialog(final RemoteDevice remoteDevice) { // hwang 2013-12-01 AlertDialog.Builder builder = new AlertDialog.Builder(this); // hwang 2013-12-01 // R.layout.device_info? ... View view = LayoutInflater.from(this).inflate(R.layout.device_info, null); final TextView ipTextView = (TextView) view.findViewById(R.id.device_info_ip_address); if (remoteDevice.getName() != null) { builder.setMessage(remoteDevice.getName()); } ipTextView.setText(remoteDevice.getAddress().getHostAddress()); return builder.setTitle(R.string.finder_label).setCancelable(false) .setPositiveButton(R.string.finder_connect, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int id) { connectToEntry(remoteDevice); // go to pairing } }).setNegativeButton(R.string.finder_add_other, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int id) { showOtherDevices(); } }).create(); } private void showConfirmation(final RemoteDevice remoteDevice) { findViewById(R.id.device_finder).setVisibility(View.VISIBLE); } // --------------------------- // No Google TV devices found // --------------------------- private AlertDialog buildBroadcastTimeoutDialog() { String message; String networkName = getNetworkName(); if (!TextUtils.isEmpty(networkName)) { message = getString(R.string.finder_no_devices_with_ssid, networkName); } else { message = getString(R.string.finder_no_devices); } return buildTimeoutDialog(message, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int id) { startBroadcast(); } }); } private AlertDialog buildTimeoutDialog(CharSequence message, DialogInterface.OnClickListener retryListener) { AlertDialog.Builder builder = new AlertDialog.Builder(this); return builder.setMessage(message).setCancelable(false) .setPositiveButton(R.string.finder_wait, retryListener) .setNegativeButton(R.string.finder_cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int id) { setResult(RESULT_CANCELED, null); finish(); } }).create(); } private void showPopupBroadcastTimeout() { // test remove below comment Log.e("hwang-tvremote", "DeviceFinder : showPopupBroadcastTimeout (?)"); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); PopupGtvTimeout popupGtvTimeout = new PopupGtvTimeout(); popupGtvTimeout.show(ft, PopupGtvTimeout.class.getSimpleName()); } // --------------------------- // pairing or mannually input // --------------------------- private OnItemClickListener selectHandler = new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // test remove below comment // RemoteDevice remoteDevice = (RemoteDevice) parent.getItemAtPosition(position); // if (remoteDevice != null) { // connectToEntry(remoteDevice); // } // pairing or mannually input if (position != deviceList.size() - 1) { // pairing RemoteDevice remoteDevice = (RemoteDevice) parent.getItemAtPosition(position); if (remoteDevice != null) { // hwang 2013-11-20 // pairing host address is reset. String hostAddress = remoteDevice.getAddress().getHostAddress(); CnmPreferences pref = CnmPreferences.getInstance(); pref.savePairingHostAddress(mContext, hostAddress); //String temp = pref.loadPairingHostAddress(mContext); connectToEntry(remoteDevice); } } else { // mannually input showPopupManuallyInput(); } } }; private AlertDialog buildManualIpDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); // hwang 2013-12-01 // R.layout.manual_ip? ... View view = LayoutInflater.from(this).inflate(R.layout.manual_ip, null); final EditText ipEditText = (EditText) view.findViewById(R.id.manual_ip_entry); ipEditText.setFilters(new InputFilter[] { new NumberKeyListener() { @Override protected char[] getAcceptedChars() { return "0123456789.:".toCharArray(); } public int getInputType() { return InputType.TYPE_CLASS_NUMBER; } } }); builder.setPositiveButton(R.string.manual_ip_connect, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { RemoteDevice remoteDevice = remoteDeviceFromString(ipEditText.getText().toString()); if (remoteDevice != null) { connectToEntry(remoteDevice); } else { Toast.makeText(DeviceFinder.this, getString(R.string.manual_ip_error_address), Toast.LENGTH_LONG).show(); } } }).setNegativeButton(R.string.manual_ip_cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // do nothing } }).setCancelable(true).setTitle(R.string.manual_ip_label).setMessage(R.string.manual_ip_entry_label) .setView(view); return builder.create(); } private void showPopupManuallyInput() { Log.e("hwang-tvremote", "DeviceFinder : manually input (?)"); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); PopupGtvManuallyInput popupGtvManuallyInput = new PopupGtvManuallyInput(); popupGtvManuallyInput.show(ft, PopupGtvManuallyInput.class.getSimpleName()); } /** * Connects to the chosen entry in the list. Finishes the activity and * returns the informations on the chosen box. * * @param remoteDevice * the listEntry representing the box you want to connect to */ public void connectToEntry(RemoteDevice remoteDevice) { Intent resultIntent = new Intent(); resultIntent.putExtra(EXTRA_REMOTE_DEVICE, remoteDevice); setResult(RESULT_OK, resultIntent); finish(); } private void showOtherDevices() { broadcastHandler.removeMessages(DELAYED_MESSAGE); if (progressDialog.isShowing()) { progressDialog.dismiss(); } // hwang if (isPopupShowing) { Fragment f = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_POPUP); getSupportFragmentManager().beginTransaction().remove(f).commit(); isPopupShowing = false; } if (confirmationDialog != null && confirmationDialog.isShowing()) { confirmationDialog.dismiss(); } findViewById(R.id.device_finder).setVisibility(View.VISIBLE); } private class DeviceFinderListAdapter extends BaseAdapter { LayoutInflater inflater; ArrayList<DeviceInfo> deviceList; int layout; public DeviceFinderListAdapter(Context context, int layout, ArrayList<DeviceInfo> deviceList) { inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.layout = layout; this.deviceList = deviceList; } public int getCount() { return deviceList.size(); } @Override public Object getItem(int position) { return getRemoteDevice(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { row = inflater.inflate(layout, parent, false); // row = inflater.inflate(R.layout.list_item_gtv_device_finder, null); // ??? } TextView name = (TextView) row.findViewById(R.id.device_list_item_name); TextView targetAddr = (TextView) row.findViewById(R.id.device_list_target_addr); TextView manually = (TextView) row.findViewById(R.id.ip_manually_input); LinearLayout deviceListLayout = (LinearLayout) row.findViewById(R.id.device_list); LinearLayout manuallyInputLayout = (LinearLayout) row.findViewById(R.id.manually_input); if (position != getCount() - 1) { if (null != name) name.setText(deviceList.get(position).name); if (null != targetAddr) targetAddr.setText(deviceList.get(position).targetAddr); deviceListLayout.setVisibility(View.VISIBLE); manuallyInputLayout.setVisibility(View.INVISIBLE); } else { if (null != manually) manually.setText(deviceList.get(position).name); deviceListLayout.setVisibility(View.INVISIBLE); manuallyInputLayout.setVisibility(View.VISIBLE); } return row; } private RemoteDevice getRemoteDevice(int position) { if (position < trackedDevices.size()) { return trackedDevices.get(position); } return null; } } private void makeDeviceList() { // deviceList.clear(); // DeviceInfo deviceInfo; // // deviceInfo = new DeviceInfo("stb_catv_cnm-192-168-0-25", "192.168.0.25"); // deviceList.add(deviceInfo); // // deviceInfo = new DeviceInfo("IP ? .", ""); // deviceList.add(deviceInfo); // test remove below comment if (trackedDevices.size() > 0) { for (int i = 0; i < trackedDevices.size(); i++) { //deviceList. DeviceInfo deviceInfo = new DeviceInfo(trackedDevices.get(0).getName(), trackedDevices.get(0).getAddress().getHostAddress()); deviceList.add(deviceInfo); } DeviceInfo deviceInfo = new DeviceInfo("IP ? .", "IP ? ."); deviceList.add(deviceInfo); } } private InetAddress getBroadcastAddress() throws IOException { WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); DhcpInfo dhcp = wifi.getDhcpInfo(); int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask; byte[] quads = new byte[4]; for (int k = 0; k < 4; k++) { quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); } return InetAddress.getByAddress(quads); } /** * Represents an entry in the box list. */ public static class ListEntryView extends RelativeLayout { public ListEntryView(Context context, AttributeSet attrs) { super(context, attrs); myContext = context; } public ListEntryView(Context context) { super(context); myContext = context; } @Override protected void onFinishInflate() { super.onFinishInflate(); tvName = (TextView) findViewById(R.id.device_list_item_name); tvTargetAddr = (TextView) findViewById(R.id.device_list_target_addr); } private void updateContents() { if (null != tvName) { String txt = myContext.getString(R.string.unkown_tgt_name); if ((null != listEntry) && (null != listEntry.getName())) { txt = listEntry.getName(); } tvName.setText(txt); } if (null != tvTargetAddr) { String txt = myContext.getString(R.string.unkown_tgt_addr); if ((null != listEntry) && (null != listEntry.getAddress())) { txt = listEntry.getAddress().getHostAddress(); } tvTargetAddr.setText(txt); } } public RemoteDevice getListEntry() { return listEntry; } public void setListEntry(RemoteDevice listEntry) { this.listEntry = listEntry; updateContents(); } private Context myContext = null; private RemoteDevice listEntry = null; private TextView tvName = null; private TextView tvTargetAddr = null; } private final class BroadcastHandler extends Handler { /** {inheritDoc} */ @Override public void handleMessage(Message msg) { if (msg.what == DELAYED_MESSAGE) { if (!active) { return; } switch ((DelayedMessage) msg.obj) { case BROADCAST_TIMEOUT: broadcastClient.stop(); if (progressDialog.isShowing()) { progressDialog.dismiss(); } // hwang if (isPopupShowing) { Fragment f = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_POPUP); getSupportFragmentManager().beginTransaction().remove(f).commit(); isPopupShowing = false; } // buildBroadcastTimeoutDialog().show(); showPopupBroadcastTimeout(); break; case GTV_DEVICE_FOUND: // Check if there is previously connected remote and suggest it // for connection: RemoteDevice toConnect = null; if (previousRemoteDevice != null) { Log.d(LOG_TAG, "Previous Remote Device: " + previousRemoteDevice); toConnect = trackedDevices.findRemoteDevice(previousRemoteDevice); } if (toConnect == null) { Log.d(LOG_TAG, "No previous device found."); // No default found - suggest any device toConnect = trackedDevices.get(0); } progressDialog.dismiss(); // hwang if (isPopupShowing) { Fragment f = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_POPUP); getSupportFragmentManager().beginTransaction().remove(f).commit(); isPopupShowing = false; } confirmationDialog = buildConfirmationDialog(toConnect); //confirmationDialog.show(); // hwang showConfirmation(toConnect); break; } } switch (msg.what) { case BROADCAST_RESPONSE: BroadcastAdvertisement advert = (BroadcastAdvertisement) msg.obj; RemoteDevice remoteDevice = new RemoteDevice(advert.getServiceName(), advert.getServiceAddress(), advert.getServicePort()); handleRemoteDeviceAdd(remoteDevice); break; } } } private void handleRemoteDeviceAdd(final RemoteDevice remoteDevice) { if (trackedDevices.add(remoteDevice)) { Log.v(LOG_TAG, "Adding new device: " + remoteDevice); // before notify data adapter, make device list for " " makeDeviceList(); // Notify data adapter and update title. dataAdapter.notifyDataSetChanged(); // Show confirmation dialog only for the first STB and only if progress // dialog is visible. if ((trackedDevices.size() == 1) && progressDialog.isShowing()) { broadcastHandler.removeMessages(DELAYED_MESSAGE); // delayed automatic adding Message message = DelayedMessage.GTV_DEVICE_FOUND.obtainMessage(broadcastHandler); broadcastHandler.sendMessageDelayed(message, getResources().getInteger(R.integer.gtv_finder_reconnect_delay)); } // hwang if ((trackedDevices.size() == 1) && isPopupShowing) { broadcastHandler.removeMessages(DELAYED_MESSAGE); // delayed automatic adding Message message = DelayedMessage.GTV_DEVICE_FOUND.obtainMessage(broadcastHandler); broadcastHandler.sendMessageDelayed(message, getResources().getInteger(R.integer.gtv_finder_reconnect_delay)); } } } public RemoteDevice remoteDeviceFromString(String text) { String[] ipPort = text.split(":"); int port; if (ipPort.length == 1) { port = getResources().getInteger(R.integer.manual_default_port); } else if (ipPort.length == 2) { try { port = Integer.parseInt(ipPort[1]); } catch (NumberFormatException e) { return null; } } else { return null; } try { InetAddress address = InetAddress.getByName(ipPort[0]); return new RemoteDevice(getString(R.string.manual_ip_default_box_name), address, port); } catch (UnknownHostException e) { } return null; } private ListView stbList; private DeviceFinderListAdapter dataAdapter; private BroadcastHandler broadcastHandler; private BroadcastDiscoveryClient broadcastClient; private Thread broadcastClientThread; private TrackedDevices trackedDevices; /** * Handler message number for a service update from broadcast client. */ public static final int BROADCAST_RESPONSE = 100; /** * Handler message number for all delayed messages */ private static final int DELAYED_MESSAGE = 101; private enum DelayedMessage { BROADCAST_TIMEOUT, GTV_DEVICE_FOUND; Message obtainMessage(Handler handler) { Message message = handler.obtainMessage(DELAYED_MESSAGE); message.obj = this; return message; } } private static class TrackedDevices implements Iterable<RemoteDevice> { private final Map<InetAddress, RemoteDevice> devicesByAddress; private final SortedSet<RemoteDevice> devices; private RemoteDevice[] deviceArray; private static Comparator<RemoteDevice> COMPARATOR = new Comparator<RemoteDevice>() { public int compare(RemoteDevice remote1, RemoteDevice remote2) { int result = remote1.getName().compareToIgnoreCase(remote2.getName()); if (result != 0) { return result; } return remote1.getAddress().getHostAddress().compareTo(remote2.getAddress().getHostAddress()); } }; TrackedDevices() { devicesByAddress = new HashMap<InetAddress, RemoteDevice>(); devices = new TreeSet<RemoteDevice>(COMPARATOR); } public boolean add(RemoteDevice remoteDevice) { InetAddress address = remoteDevice.getAddress(); if (!devicesByAddress.containsKey(address)) { devicesByAddress.put(address, remoteDevice); devices.add(remoteDevice); deviceArray = null; return true; } // address? return false; } public int size() { return devices.size(); } public RemoteDevice get(int index) { return getDeviceArray()[index]; } private RemoteDevice[] getDeviceArray() { if (deviceArray == null) { deviceArray = devices.toArray(new RemoteDevice[0]); } return deviceArray; } public Iterator<RemoteDevice> iterator() { return devices.iterator(); } public RemoteDevice findRemoteDevice(RemoteDevice remoteDevice) { RemoteDevice byIp = devicesByAddress.get(remoteDevice.getAddress()); if (byIp != null && byIp.getName().equals(remoteDevice.getName())) { return byIp; } for (RemoteDevice device : devices) { Log.d(LOG_TAG, "New device: " + device); if (remoteDevice.getName().equals(device.getName())) { return device; } } return byIp; } } private boolean isWifiAvailable() { if (!wifiManager.isWifiEnabled()) { return false; } WifiInfo info = wifiManager.getConnectionInfo(); return info != null && info.getIpAddress() != 0; } private String getNetworkName() { if (!isWifiAvailable()) { return null; } WifiInfo info = wifiManager.getConnectionInfo(); return info != null ? info.getSSID() : null; } // ? class DeviceInfo { DeviceInfo(String aName, String aTargetName) { name = aName; targetAddr = aTargetName; } String name; String targetAddr; } }