1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.bluetooth; 18 19 import com.android.settings.ProgressCategory; 20 import com.android.settings.R; 21 22 import java.util.List; 23 import java.util.WeakHashMap; 24 25 import android.bluetooth.BluetoothDevice; 26 import android.bluetooth.BluetoothIntent; 27 import android.content.BroadcastReceiver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.os.Bundle; 32 import android.preference.CheckBoxPreference; 33 import android.preference.Preference; 34 import android.preference.PreferenceActivity; 35 import android.preference.PreferenceScreen; 36 import android.view.ContextMenu; 37 import android.view.Menu; 38 import android.view.MenuItem; 39 import android.view.View; 40 import android.view.ContextMenu.ContextMenuInfo; 41 import android.widget.AdapterView.AdapterContextMenuInfo; 42 43 /** 44 * BluetoothSettings is the Settings screen for Bluetooth configuration and 45 * connection management. 46 */ 47 public class BluetoothSettings extends PreferenceActivity 48 implements LocalBluetoothManager.Callback { 49 50 private static final String TAG = "BluetoothSettings"; 51 52 private static final int MENU_SCAN = Menu.FIRST; 53 54 private static final String KEY_BT_CHECKBOX = "bt_checkbox"; 55 private static final String KEY_BT_DISCOVERABLE = "bt_discoverable"; 56 private static final String KEY_BT_DEVICE_LIST = "bt_device_list"; 57 private static final String KEY_BT_NAME = "bt_name"; 58 private static final String KEY_BT_SCAN = "bt_scan"; 59 60 private LocalBluetoothManager mLocalManager; 61 62 private BluetoothEnabler mEnabler; 63 private BluetoothDiscoverableEnabler mDiscoverableEnabler; 64 65 private BluetoothNamePreference mNamePreference; 66 67 private ProgressCategory mDeviceList; 68 69 private WeakHashMap<LocalBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap = 70 new WeakHashMap<LocalBluetoothDevice, BluetoothDevicePreference>(); 71 72 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 73 @Override 74 public void onReceive(Context context, Intent intent) { 75 // TODO: put this in callback instead of receiving 76 onBluetoothStateChanged(mLocalManager.getBluetoothState()); 77 } 78 }; 79 80 @Override onCreate(Bundle savedInstanceState)81 protected void onCreate(Bundle savedInstanceState) { 82 super.onCreate(savedInstanceState); 83 84 mLocalManager = LocalBluetoothManager.getInstance(this); 85 if (mLocalManager == null) finish(); 86 87 addPreferencesFromResource(R.xml.bluetooth_settings); 88 89 mEnabler = new BluetoothEnabler( 90 this, 91 (CheckBoxPreference) findPreference(KEY_BT_CHECKBOX)); 92 93 mDiscoverableEnabler = new BluetoothDiscoverableEnabler( 94 this, 95 (CheckBoxPreference) findPreference(KEY_BT_DISCOVERABLE)); 96 97 mNamePreference = (BluetoothNamePreference) findPreference(KEY_BT_NAME); 98 99 mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST); 100 101 registerForContextMenu(getListView()); 102 } 103 104 @Override onResume()105 protected void onResume() { 106 super.onResume(); 107 108 // Repopulate (which isn't too bad since it's cached in the settings 109 // bluetooth manager 110 mDevicePreferenceMap.clear(); 111 mDeviceList.removeAll(); 112 addDevices(); 113 114 mEnabler.resume(); 115 mDiscoverableEnabler.resume(); 116 mNamePreference.resume(); 117 mLocalManager.registerCallback(this); 118 119 mLocalManager.startScanning(false); 120 121 registerReceiver(mReceiver, 122 new IntentFilter(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)); 123 124 mLocalManager.setForegroundActivity(this); 125 } 126 127 @Override onPause()128 protected void onPause() { 129 super.onPause(); 130 131 mLocalManager.setForegroundActivity(null); 132 133 unregisterReceiver(mReceiver); 134 135 mLocalManager.unregisterCallback(this); 136 mNamePreference.pause(); 137 mDiscoverableEnabler.pause(); 138 mEnabler.pause(); 139 } 140 addDevices()141 private void addDevices() { 142 List<LocalBluetoothDevice> devices = mLocalManager.getLocalDeviceManager().getDevicesCopy(); 143 for (LocalBluetoothDevice device : devices) { 144 onDeviceAdded(device); 145 } 146 } 147 148 @Override onCreateOptionsMenu(Menu menu)149 public boolean onCreateOptionsMenu(Menu menu) { 150 menu.add(0, MENU_SCAN, 0, R.string.bluetooth_scan_for_devices) 151 .setIcon(com.android.internal.R.drawable.ic_menu_refresh) 152 .setAlphabeticShortcut('r'); 153 return true; 154 } 155 156 @Override onPrepareOptionsMenu(Menu menu)157 public boolean onPrepareOptionsMenu(Menu menu) { 158 menu.findItem(MENU_SCAN).setEnabled(mLocalManager.getBluetoothManager().isEnabled()); 159 return true; 160 } 161 162 @Override onOptionsItemSelected(MenuItem item)163 public boolean onOptionsItemSelected(MenuItem item) { 164 switch (item.getItemId()) { 165 166 case MENU_SCAN: 167 mLocalManager.startScanning(true); 168 return true; 169 170 default: 171 return false; 172 } 173 } 174 175 @Override onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)176 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 177 Preference preference) { 178 179 if (KEY_BT_SCAN.equals(preference.getKey())) { 180 mLocalManager.startScanning(true); 181 return true; 182 } 183 184 if (preference instanceof BluetoothDevicePreference) { 185 BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference; 186 btPreference.getDevice().onClicked(); 187 return true; 188 } 189 190 return super.onPreferenceTreeClick(preferenceScreen, preference); 191 } 192 193 @Override onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)194 public void onCreateContextMenu(ContextMenu menu, View v, 195 ContextMenuInfo menuInfo) { 196 LocalBluetoothDevice device = getDeviceFromMenuInfo(menuInfo); 197 if (device == null) return; 198 199 device.onCreateContextMenu(menu); 200 } 201 202 @Override onContextItemSelected(MenuItem item)203 public boolean onContextItemSelected(MenuItem item) { 204 LocalBluetoothDevice device = getDeviceFromMenuInfo(item.getMenuInfo()); 205 if (device == null) return false; 206 207 device.onContextItemSelected(item); 208 return true; 209 } 210 getDeviceFromMenuInfo(ContextMenuInfo menuInfo)211 private LocalBluetoothDevice getDeviceFromMenuInfo(ContextMenuInfo menuInfo) { 212 if ((menuInfo == null) || !(menuInfo instanceof AdapterContextMenuInfo)) { 213 return null; 214 } 215 216 AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo; 217 Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem( 218 adapterMenuInfo.position); 219 if (pref == null || !(pref instanceof BluetoothDevicePreference)) { 220 return null; 221 } 222 223 return ((BluetoothDevicePreference) pref).getDevice(); 224 } 225 onDeviceAdded(LocalBluetoothDevice device)226 public void onDeviceAdded(LocalBluetoothDevice device) { 227 228 if (mDevicePreferenceMap.get(device) != null) { 229 throw new IllegalStateException("Got onDeviceAdded, but device already exists"); 230 } 231 232 createDevicePreference(device); 233 } 234 createDevicePreference(LocalBluetoothDevice device)235 private void createDevicePreference(LocalBluetoothDevice device) { 236 BluetoothDevicePreference preference = new BluetoothDevicePreference(this, device); 237 mDeviceList.addPreference(preference); 238 mDevicePreferenceMap.put(device, preference); 239 } 240 onDeviceDeleted(LocalBluetoothDevice device)241 public void onDeviceDeleted(LocalBluetoothDevice device) { 242 BluetoothDevicePreference preference = mDevicePreferenceMap.remove(device); 243 if (preference != null) { 244 mDeviceList.removePreference(preference); 245 } 246 } 247 onScanningStateChanged(boolean started)248 public void onScanningStateChanged(boolean started) { 249 mDeviceList.setProgress(started); 250 } 251 onBluetoothStateChanged(int bluetoothState)252 private void onBluetoothStateChanged(int bluetoothState) { 253 // When bluetooth is enabled (and we are in the activity, which we are), 254 // we should start a scan 255 if (bluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON) { 256 mLocalManager.startScanning(false); 257 } else if (bluetoothState == BluetoothDevice.BLUETOOTH_STATE_OFF) { 258 mDeviceList.setProgress(false); 259 } 260 } 261 } 262