/*
* Copyright (C) 2010 beworx.com
*
* 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.bwx.bequick.handlers;
import static com.bwx.bequick.Constants.TAG;
import java.lang.reflect.Method;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.provider.Settings;
import android.util.Log;
import com.bwx.bequick.MainSettingsActivity;
import com.bwx.bequick.R;
import com.bwx.bequick.fwk.Setting;
import com.bwx.bequick.fwk.SettingHandler;
public class BluetoothSettingHandler extends SettingHandler {
public static String BLUETOOTH_ACTION_STATE_CHANGED;
public static String BLUETOOTH_EXTRA_STATE;
// BT state abstraction
public static int BLUETOOTH_STATE_UNKNOWN;
public static int BLUETOOTH_STATE_OFF;
public static int BLUETOOTH_STATE_TURNING_ON;
public static int BLUETOOTH_STATE_ON;
public static int BLUETOOTH_STATE_TURNING_OFF;
class BluetoothStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(BLUETOOTH_EXTRA_STATE, BLUETOOTH_STATE_UNKNOWN);
onBluetoothStateChanged(state);
}
}
interface BluetoothControl {
void setEnabled(boolean enabled);
int getBluetoothState();
}
class BluetoothControl20 implements BluetoothControl {
private BluetoothAdapter mAdapter;
public BluetoothControl20() {
// cache adaptor
mAdapter = BluetoothAdapter.getDefaultAdapter();
if (mAdapter == null) throw new UnsupportedOperationException("No default bluetooth adapter");
// initialize state
BLUETOOTH_STATE_UNKNOWN = -1;
BLUETOOTH_STATE_OFF = BluetoothAdapter.STATE_OFF;
BLUETOOTH_STATE_TURNING_ON = BluetoothAdapter.STATE_TURNING_ON;
BLUETOOTH_STATE_ON = BluetoothAdapter.STATE_ON;
BLUETOOTH_STATE_TURNING_OFF = BluetoothAdapter.STATE_TURNING_OFF;
BLUETOOTH_ACTION_STATE_CHANGED = BluetoothAdapter.ACTION_STATE_CHANGED;
BLUETOOTH_EXTRA_STATE = BluetoothAdapter.EXTRA_STATE;
}
public int getBluetoothState() {
return mAdapter.getState();
}
public void setEnabled(boolean enabled) {
if (enabled) {
mAdapter.enable();
} else {
mAdapter.disable();
}
}
}
class BluetoothControl16 implements BluetoothControl {
private Object mService;
private Method[] mMethods = new Method[3]; // [0] enable, [1] disable, [2] getBluetoothState
public BluetoothControl16() throws Exception {
mService = mActivity.getSystemService("bluetooth"); // bluetooth
Method[] methods = mMethods;
if (mService == null) throw new IllegalStateException("bluetooth service not found");
Method method;
// get enabled
method = mService.getClass().getMethod("enable");
if (method != null) method.setAccessible(true);
methods[0] = method;
// get disabled
method = mService.getClass().getMethod("disable");
if (method != null) method.setAccessible(true);
methods[1] = method;
method = mService.getClass().getMethod("getBluetoothState");
if (method != null) method.setAccessible(true);
methods[2] = method;
// initialize state
BLUETOOTH_STATE_UNKNOWN = -1;
BLUETOOTH_STATE_OFF = 0;
BLUETOOTH_STATE_TURNING_ON = 1;
BLUETOOTH_STATE_ON = 2;
BLUETOOTH_STATE_TURNING_OFF = 3;
BLUETOOTH_ACTION_STATE_CHANGED = "android.bluetooth.intent.action.BLUETOOTH_STATE_CHANGED";
BLUETOOTH_EXTRA_STATE = "android.bluetooth.intent.BLUETOOTH_STATE";
}
public void setEnabled(boolean enabled) {
try {
Method method = mMethods[enabled ? 0 : 1];
method.invoke(mService);
return;
} catch (Exception e) {
Log.e(TAG, "cannot enable/disable bluetooth", e);
}
return;
}
public int getBluetoothState() {
try {
Method method = mMethods[2];
Integer state = (Integer) method.invoke(mService);
return state.intValue();
} catch (Exception e) {
Log.e(TAG, "cannot getBluetoothState", e);
}
return BLUETOOTH_STATE_UNKNOWN;
}
}
private BluetoothControl mBluetoothControl;
private BluetoothStateReceiver mReceiver;
public BluetoothSettingHandler(Setting setting) {
super(setting);
}
@Override
public void activate(MainSettingsActivity activity) throws Exception {
mActivity = activity;
// create bluetooth control
try {
// try with 1.6
mBluetoothControl = new BluetoothControl16();
} catch(Exception e) {
mBluetoothControl = new BluetoothControl20(); // 2.0+ adapter
}
// get state pro-actively, as we won't be notified immediately
onBluetoothStateChanged(mBluetoothControl.getBluetoothState());
// register bluetooth event receiver
IntentFilter filter = new IntentFilter(BLUETOOTH_ACTION_STATE_CHANGED);
if (mReceiver == null) mReceiver = new BluetoothStateReceiver();
activity.registerReceiver(mReceiver, filter);
}
@Override
public void deactivate() {
mActivity.unregisterReceiver(mReceiver);
}
@Override
public void onSelected(int buttonIndex) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.android.settings", "com.android.settings.bluetooth.BluetoothSettings");
mActivity.startActivitiesSafely(intent, new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
@Override
public void onSwitched(boolean isSwitched) {
mBluetoothControl.setEnabled(isSwitched);
}
@Override
public void onValueChanged(int value) {
// do nothing
}
/**
* Handles state and updates description, check- and enable-states
* @param state
*/
private void onBluetoothStateChanged(int state) {
Setting setting = mSetting;
int stateText = R.string.txt_status_unknown;
boolean enabled = false;
if (state == BLUETOOTH_STATE_OFF) {
setting.checked = false;
enabled = true;
stateText = R.string.txt_status_turned_off;
} else if (state == BLUETOOTH_STATE_TURNING_OFF) {
stateText = R.string.txt_status_turning_off;
} else if (state == BLUETOOTH_STATE_ON) {
setting.checked = true;
enabled = true;
stateText = R.string.txt_status_turned_on;
} else if (state == BLUETOOTH_STATE_TURNING_ON) {
stateText = R.string.txt_status_turning_on;
}
setting.enabled = enabled;
setting.descr = mActivity.getString(stateText);
setting.updateView();
}
}