1 /* 2 * Copyright (C) 2010 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 android.bluetooth.BluetoothAdapter; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.provider.Settings; 27 import android.widget.CompoundButton; 28 import android.widget.Switch; 29 import android.widget.Toast; 30 31 import com.android.settings.R; 32 import com.android.settings.WirelessSettings; 33 import com.android.settings.search.Index; 34 import com.android.settings.widget.SwitchBar; 35 36 /** 37 * BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox 38 * preference. It turns on/off Bluetooth and ensures the summary of the 39 * preference reflects the current state. 40 */ 41 public final class BluetoothEnabler implements SwitchBar.OnSwitchChangeListener { 42 private Context mContext; 43 private Switch mSwitch; 44 private SwitchBar mSwitchBar; 45 private boolean mValidListener; 46 private final LocalBluetoothAdapter mLocalAdapter; 47 private final IntentFilter mIntentFilter; 48 49 private static final String EVENT_DATA_IS_BT_ON = "is_bluetooth_on"; 50 private static final int EVENT_UPDATE_INDEX = 0; 51 52 private Handler mHandler = new Handler() { 53 @Override 54 public void handleMessage(Message msg) { 55 switch (msg.what) { 56 case EVENT_UPDATE_INDEX: 57 final boolean isBluetoothOn = msg.getData().getBoolean(EVENT_DATA_IS_BT_ON); 58 Index.getInstance(mContext).updateFromClassNameResource( 59 BluetoothSettings.class.getName(), true, isBluetoothOn); 60 break; 61 } 62 } 63 }; 64 65 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 66 @Override 67 public void onReceive(Context context, Intent intent) { 68 // Broadcast receiver is always running on the UI thread here, 69 // so we don't need consider thread synchronization. 70 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 71 handleStateChanged(state); 72 } 73 }; 74 75 public BluetoothEnabler(Context context, SwitchBar switchBar) { 76 mContext = context; 77 mSwitchBar = switchBar; 78 mSwitch = switchBar.getSwitch(); 79 mValidListener = false; 80 81 LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context); 82 if (manager == null) { 83 // Bluetooth is not supported 84 mLocalAdapter = null; 85 mSwitch.setEnabled(false); 86 } else { 87 mLocalAdapter = manager.getBluetoothAdapter(); 88 } 89 mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 90 } 91 92 public void setupSwitchBar() { 93 mSwitchBar.show(); 94 } 95 96 public void teardownSwitchBar() { 97 mSwitchBar.hide(); 98 } 99 100 public void resume(Context context) { 101 if (mLocalAdapter == null) { 102 mSwitch.setEnabled(false); 103 return; 104 } 105 106 if (mContext != context) { 107 mContext = context; 108 } 109 110 // Bluetooth state is not sticky, so set it manually 111 handleStateChanged(mLocalAdapter.getBluetoothState()); 112 113 mSwitchBar.addOnSwitchChangeListener(this); 114 mContext.registerReceiver(mReceiver, mIntentFilter); 115 mValidListener = true; 116 } 117 118 public void pause() { 119 if (mLocalAdapter == null) { 120 return; 121 } 122 123 mSwitchBar.removeOnSwitchChangeListener(this); 124 mContext.unregisterReceiver(mReceiver); 125 mValidListener = false; 126 } 127 128 void handleStateChanged(int state) { 129 switch (state) { 130 case BluetoothAdapter.STATE_TURNING_ON: 131 mSwitch.setEnabled(false); 132 break; 133 case BluetoothAdapter.STATE_ON: 134 setChecked(true); 135 mSwitch.setEnabled(true); 136 updateSearchIndex(true); 137 break; 138 case BluetoothAdapter.STATE_TURNING_OFF: 139 mSwitch.setEnabled(false); 140 break; 141 case BluetoothAdapter.STATE_OFF: 142 setChecked(false); 143 mSwitch.setEnabled(true); 144 updateSearchIndex(false); 145 break; 146 default: 147 setChecked(false); 148 mSwitch.setEnabled(true); 149 updateSearchIndex(false); 150 } 151 } 152 153 private void setChecked(boolean isChecked) { 154 if (isChecked != mSwitch.isChecked()) { 155 // set listener to null, so onCheckedChanged won't be called 156 // if the checked status on Switch isn't changed by user click 157 if (mValidListener) { 158 mSwitchBar.removeOnSwitchChangeListener(this); 159 } 160 mSwitch.setChecked(isChecked); 161 if (mValidListener) { 162 mSwitchBar.addOnSwitchChangeListener(this); 163 } 164 } 165 } 166 167 private void updateSearchIndex(boolean isBluetoothOn) { 168 mHandler.removeMessages(EVENT_UPDATE_INDEX); 169 170 Message msg = new Message(); 171 msg.what = EVENT_UPDATE_INDEX; 172 msg.getData().putBoolean(EVENT_DATA_IS_BT_ON, isBluetoothOn); 173 mHandler.sendMessage(msg); 174 } 175 176 @Override 177 public void onSwitchChanged(Switch switchView, boolean isChecked) { 178 // Show toast message if Bluetooth is not allowed in airplane mode 179 if (isChecked && 180 !WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) { 181 Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); 182 // Reset switch to off 183 switchView.setChecked(false); 184 } 185 186 if (mLocalAdapter != null) { 187 mLocalAdapter.setBluetoothEnabled(isChecked); 188 } 189 mSwitch.setEnabled(false); 190 } 191 } 192