Bluetooth settings revamp

Added a separate scanning screen.
UI changes to not require long-press options.
Needs TODOs to be filled by BT team.

Bug: 3038327
This commit is contained in:
Amith Yamasani
2010-10-26 13:44:33 -07:00
parent 4a5f889f80
commit 48e9000283
19 changed files with 637 additions and 187 deletions

View File

@@ -19,16 +19,22 @@ package com.android.settings.bluetooth;
import com.android.settings.R;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.preference.Preference;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
/**
* BluetoothDevicePreference is the preference type used to display each remote
* Bluetooth device in the Bluetooth Settings screen.
*/
public class BluetoothDevicePreference extends Preference implements CachedBluetoothDevice.Callback {
public class BluetoothDevicePreference extends Preference implements
CachedBluetoothDevice.Callback, OnClickListener {
private static final String TAG = "BluetoothDevicePreference";
private static int sDimAlpha = Integer.MIN_VALUE;
@@ -36,6 +42,9 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
private CachedBluetoothDevice mCachedDevice;
private int mAccessibleProfile;
private ImageView mDeviceSettings;
private OnClickListener mOnSettingsClickListener;
/**
* Cached local copy of whether the device is busy. This is only updated
* from {@link #onDeviceAttributesChanged(CachedBluetoothDevice)}.
@@ -66,6 +75,10 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
return mCachedDevice;
}
public void setOnSettingsClickListener(OnClickListener listener) {
mOnSettingsClickListener = listener;
}
@Override
protected void onPrepareForRemoval() {
super.onPrepareForRemoval();
@@ -117,6 +130,34 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
ImageView btClass = (ImageView) view.findViewById(R.id.btClass);
btClass.setImageResource(mCachedDevice.getBtClassDrawable());
btClass.setAlpha(isEnabled() ? 255 : sDimAlpha);
mDeviceSettings = (ImageView) view.findViewById(R.id.deviceDetails);
if (mOnSettingsClickListener != null) {
mDeviceSettings.setOnClickListener(this);
mDeviceSettings.setTag(mCachedDevice);
} else { // Hide the settings icon and divider
mDeviceSettings.setVisibility(View.GONE);
ImageView divider = (ImageView) view.findViewById(R.id.divider);
if (divider != null) {
divider.setVisibility(View.GONE);
}
}
LayoutInflater inflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup profilesGroup = (ViewGroup) view.findViewById(R.id.profileIcons);
for (Drawable icon : mCachedDevice.getProfileIcons()) {
inflater.inflate(R.layout.profile_icon_small, profilesGroup, true);
ImageView imageView =
(ImageView) profilesGroup.getChildAt(profilesGroup.getChildCount() - 1);
imageView.setImageDrawable(icon);
}
}
public void onClick(View v) {
if (v == mDeviceSettings) {
if (mOnSettingsClickListener != null) mOnSettingsClickListener.onClick(v);
}
}
@Override

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.settings.bluetooth;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import com.android.settings.R;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.preference.Preference;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
/**
* BluetoothProfilePreference is the preference type used to display each profile for a
* particular bluetooth device.
*/
public class BluetoothProfilePreference extends Preference implements OnClickListener {
private static final String TAG = "BluetoothProfilePreference";
private Drawable mProfileDrawable;
private boolean mExpanded;
private ImageView mProfileExpandView;
private Profile mProfile;
private OnClickListener mOnExpandClickListener;
public BluetoothProfilePreference(Context context, Profile profile) {
super(context);
mProfile = profile;
setLayoutResource(R.layout.preference_bluetooth_profile);
setExpanded(false);
}
public void setOnExpandClickListener(OnClickListener listener) {
mOnExpandClickListener = listener;
}
public void setExpanded(boolean expanded) {
mExpanded = expanded;
notifyChanged();
}
public boolean isExpanded() {
return mExpanded;
}
public void setProfileDrawable(Drawable drawable) {
mProfileDrawable = drawable;
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
ImageView btProfile = (ImageView) view.findViewById(R.id.profileIcon);
btProfile.setImageDrawable(mProfileDrawable);
mProfileExpandView = (ImageView) view.findViewById(R.id.profileExpand);
mProfileExpandView.setOnClickListener(this);
mProfileExpandView.setTag(mProfile);
mProfileExpandView.setImageResource(mExpanded ? R.drawable.ic_preferences_expanded
: R.drawable.ic_preferences_collapsed);
}
public void onClick(View v) {
if (v == mProfileExpandView) {
if (mOnExpandClickListener != null) {
setExpanded(!mExpanded);
mOnExpandClickListener.onClick(v);
}
}
}
}

View File

@@ -16,11 +16,11 @@
package com.android.settings.bluetooth;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import com.android.settings.ProgressCategory;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.UserLeaveHintListener;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import android.app.Activity;
import android.app.AlertDialog;
@@ -39,6 +39,7 @@ import android.os.Bundle;
import android.os.ParcelUuid;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.view.ContextMenu;
@@ -55,7 +56,7 @@ import java.util.WeakHashMap;
* connection management.
*/
public class BluetoothSettings extends SettingsPreferenceFragment
implements LocalBluetoothManager.Callback, UserLeaveHintListener {
implements LocalBluetoothManager.Callback, UserLeaveHintListener, View.OnClickListener {
private static final String TAG = "BluetoothSettings";
@@ -64,14 +65,18 @@ public class BluetoothSettings extends SettingsPreferenceFragment
private static final String KEY_BT_DEVICE_LIST = "bt_device_list";
private static final String KEY_BT_NAME = "bt_name";
private static final String KEY_BT_SCAN = "bt_scan";
private static final String KEY_BT_FIND_NEARBY = "bt_find_nearby";
private static final int SCREEN_TYPE_SETTINGS = 0;
private static final int SCREEN_TYPE_DEVICEPICKER = 1;
private static final int SCREEN_TYPE_TETHERING = 2;
private static final int SCREEN_TYPE_SCAN = 3;
public static final String ACTION = "bluetooth_action";
public static final String ACTION_LAUNCH_TETHER_PICKER =
"com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER";
"com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER";
public static final String ACTION_LAUNCH_SCAN_MODE =
"com.android.settings.bluetooth.action.LAUNCH_SCAN_MODE";
private int mScreenType;
private int mFilterType;
@@ -88,7 +93,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
private BluetoothNamePreference mNamePreference;
private ProgressCategory mDeviceList;
private PreferenceCategory mDeviceList;
private WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
@@ -96,11 +101,11 @@ public class BluetoothSettings extends SettingsPreferenceFragment
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: put this in callback instead of receiving
if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
onBluetoothStateChanged(mLocalManager.getBluetoothState());
} else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
// TODO: If this is a scanning screen, maybe return on successful pairing
int bondState = intent
.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -153,6 +158,8 @@ public class BluetoothSettings extends SettingsPreferenceFragment
action = intent.getAction();
}
if (getPreferenceScreen() != null) getPreferenceScreen().removeAll();
if (action.equals(BluetoothDevicePicker.ACTION_LAUNCH)) {
mScreenType = SCREEN_TYPE_DEVICEPICKER;
mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
@@ -168,6 +175,10 @@ public class BluetoothSettings extends SettingsPreferenceFragment
mFilterType = BluetoothDevicePicker.FILTER_TYPE_PANU;
activity.setTitle(activity.getString(R.string.device_picker));
addPreferencesFromResource(R.xml.device_picker);
} else if (action.equals(ACTION_LAUNCH_SCAN_MODE)) {
mScreenType = SCREEN_TYPE_SCAN;
addPreferencesFromResource(R.xml.device_picker);
} else {
addPreferencesFromResource(R.xml.bluetooth_settings);
@@ -182,10 +193,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment
mNamePreference = (BluetoothNamePreference) findPreference(KEY_BT_NAME);
mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
}
mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
mDeviceList = (PreferenceCategory) findPreference(KEY_BT_DEVICE_LIST);
registerForContextMenu(getListView());
@@ -200,7 +210,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment
// bluetooth manager
mDevicePreferenceMap.clear();
mDeviceList.removeAll();
addDevices();
if (mScreenType != SCREEN_TYPE_SCAN) {
addDevices();
}
if (mScreenType == SCREEN_TYPE_SETTINGS) {
mEnabler.resume();
@@ -210,8 +222,11 @@ public class BluetoothSettings extends SettingsPreferenceFragment
mLocalManager.registerCallback(this);
mDeviceList.setProgress(mLocalManager.getBluetoothAdapter().isDiscovering());
mLocalManager.startScanning(false);
updateProgressUi(mLocalManager.getBluetoothAdapter().isDiscovering());
if (mScreenType != SCREEN_TYPE_SETTINGS) {
mLocalManager.startScanning(true);
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
@@ -249,6 +264,13 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
}
public void onClick(View v) {
if (v.getTag() instanceof CachedBluetoothDevice) {
CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
device.onClickedAdvancedOptions(this);
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
@@ -260,7 +282,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
if (preference instanceof BluetoothDevicePreference) {
BluetoothDevicePreference btPreference = (BluetoothDevicePreference)preference;
if (mScreenType == SCREEN_TYPE_SETTINGS) {
if (mScreenType == SCREEN_TYPE_SETTINGS || mScreenType == SCREEN_TYPE_SCAN) {
btPreference.getCachedDevice().onClicked();
} else if (mScreenType == SCREEN_TYPE_DEVICEPICKER) {
CachedBluetoothDevice device = btPreference.getCachedDevice();
@@ -312,7 +334,7 @@ public class BluetoothSettings extends SettingsPreferenceFragment
CachedBluetoothDevice cachedDevice = getDeviceFromMenuInfo(item.getMenuInfo());
if (cachedDevice == null) return false;
cachedDevice.onContextItemSelected(item);
cachedDevice.onContextItemSelected(item, this);
return true;
}
@@ -337,8 +359,11 @@ public class BluetoothSettings extends SettingsPreferenceFragment
throw new IllegalStateException("Got onDeviceAdded, but cachedDevice already exists");
}
if (addDevicePreference(cachedDevice)) {
createDevicePreference(cachedDevice);
if (mScreenType != SCREEN_TYPE_SETTINGS
|| cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
if (addDevicePreference(cachedDevice)) {
createDevicePreference(cachedDevice);
}
}
}
@@ -406,6 +431,9 @@ public class BluetoothSettings extends SettingsPreferenceFragment
preference = new BluetoothDevicePreference(
getActivity(), cachedDevice, CachedBluetoothDevice.OTHER_PROFILES);
}
if (mScreenType == SCREEN_TYPE_SETTINGS) {
preference.setOnSettingsClickListener(this);
}
mDeviceList.addPreference(preference);
mDevicePreferenceMap.put(cachedDevice, preference);
}
@@ -418,16 +446,23 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
public void onScanningStateChanged(boolean started) {
mDeviceList.setProgress(started);
updateProgressUi(started);
}
private void updateProgressUi(boolean start) {
if (mDeviceList instanceof ProgressCategory) {
((ProgressCategory) mDeviceList).setProgress(start);
}
}
private void onBluetoothStateChanged(int bluetoothState) {
// When bluetooth is enabled (and we are in the activity, which we are),
// we should start a scan
if (bluetoothState == BluetoothAdapter.STATE_ON) {
mLocalManager.startScanning(false);
if (mScreenType != SCREEN_TYPE_SETTINGS) {
mLocalManager.startScanning(false);
}
} else if (bluetoothState == BluetoothAdapter.STATE_OFF) {
mDeviceList.setProgress(false);
updateProgressUi(false);
}
}
@@ -480,4 +515,22 @@ public class BluetoothSettings extends SettingsPreferenceFragment
}
getActivity().sendBroadcast(intent);
}
public static class FindNearby extends BluetoothSettings {
public FindNearby() {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
Bundle args = super.getArguments();
if (args == null) {
args = new Bundle();
setArguments(args);
}
args.putString(ACTION, ACTION_LAUNCH_SCAN_MODE);
super.onActivityCreated(savedInstanceState);
}
}
}

View File

@@ -16,28 +16,31 @@
package com.android.settings.bluetooth;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.ParcelUuid;
import android.os.SystemClock;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* CachedBluetoothDevice represents a remote Bluetooth device. It contains
@@ -63,6 +66,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
private String mName;
private short mRssi;
private BluetoothClass mBtClass;
private Context mContext;
private List<Profile> mProfiles = new ArrayList<Profile>();
@@ -138,6 +142,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
mDevice = device;
mContext = context;
fillData();
}
@@ -655,6 +660,20 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
return SettingsBtStatus.getPairingStatusSummary(getBondState());
}
public List<Drawable> getProfileIcons() {
ArrayList<Drawable> drawables = new ArrayList<Drawable>();
for (Profile profile : mProfiles) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, profile);
int iconResource = profileManager.getDrawableResource();
if (iconResource != 0) {
drawables.add(mContext.getResources().getDrawable(iconResource));
}
}
return drawables;
}
/**
* We have special summaries when particular profiles are connected. This
* checks for those states and returns an applicable summary.
@@ -781,7 +800,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
*
* @param item The item that was clicked.
*/
public void onContextItemSelected(MenuItem item) {
public void onContextItemSelected(MenuItem item, SettingsPreferenceFragment fragment) {
switch (item.getItemId()) {
case CONTEXT_ITEM_DISCONNECT:
disconnect();
@@ -796,21 +815,34 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
break;
case CONTEXT_ITEM_CONNECT_ADVANCED:
Intent intent = new Intent();
// Need an activity context to open this in our task
Context context = mLocalManager.getForegroundActivity();
if (context == null) {
// Fallback on application context, and open in a new task
context = mLocalManager.getContext();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
intent.setClass(context, ConnectSpecificProfilesActivity.class);
intent.putExtra(ConnectSpecificProfilesActivity.EXTRA_DEVICE, mDevice);
context.startActivity(intent);
onClickedAdvancedOptions(fragment);
break;
}
}
public void onClickedAdvancedOptions(SettingsPreferenceFragment fragment) {
// TODO: Verify if there really is a case when there's no foreground
// activity
// Intent intent = new Intent();
// // Need an activity context to open this in our task
// Context context = mLocalManager.getForegroundActivity();
// if (context == null) {
// // Fallback on application context, and open in a new task
// context = mLocalManager.getContext();
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// }
// intent.setClass(context, ConnectSpecificProfilesActivity.class);
// intent.putExtra(ConnectSpecificProfilesActivity.EXTRA_DEVICE,
// mDevice);
// context.startActivity(intent);
Preference pref = new Preference(fragment.getActivity());
pref.setTitle(getName());
pref.setFragment(DeviceProfilesSettings.class.getName());
pref.getExtras().putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, mDevice);
((PreferenceActivity) fragment.getActivity()).onPreferenceStartFragment(fragment, pref);
}
public void registerCallback(Callback callback) {
synchronized (mCallbacks) {
mCallbacks.add(callback);

View File

@@ -16,31 +16,41 @@
package com.android.settings.bluetooth;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.Context;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
import java.util.HashMap;
/**
* ConnectSpecificProfilesActivity presents the user with all of the profiles
* for a particular device, and allows him to choose which should be connected
* (or disconnected).
*/
public class ConnectSpecificProfilesActivity extends PreferenceActivity
implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener {
private static final String TAG = "ConnectSpecificProfilesActivity";
public class DeviceProfilesSettings extends SettingsPreferenceFragment
implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener,
View.OnClickListener {
private static final String TAG = "DeviceProfilesSettings";
private static final String KEY_ONLINE_MODE = "online_mode";
private static final String KEY_TITLE = "title";
private static final String KEY_RENAME_DEVICE = "rename_device";
private static final String KEY_PROFILE_CONTAINER = "profile_container";
private static final String KEY_UNPAIR = "unpair";
private static final String KEY_ALLOW_INCOMING = "allow_incoming";
private static final String AUTO_CONNECT_KEY_SUFFIX = "X";
public static final String EXTRA_DEVICE = "device";
@@ -48,27 +58,21 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
private CachedBluetoothDevice mCachedDevice;
private PreferenceGroup mProfileContainer;
private CheckBoxPreference mOnlineModePreference;
/**
* The current mode of this activity and its checkboxes (either online mode
* or offline mode). In online mode, user interactions with the profile
* checkboxes will also toggle the profile's connectivity. In offline mode,
* they will not, and only the preferred state will be saved for the
* profile.
*/
private boolean mOnlineMode;
private CheckBoxPreference mAllowIncomingPref;
private EditTextPreference mDeviceNamePref;
private HashMap<String,CheckBoxPreference> mAutoConnectPrefs
= new HashMap<String,CheckBoxPreference>();
@Override
protected void onCreate(Bundle savedInstanceState) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BluetoothDevice device;
if (savedInstanceState != null) {
device = savedInstanceState.getParcelable(EXTRA_DEVICE);
} else {
Intent intent = getIntent();
device = intent.getParcelableExtra(EXTRA_DEVICE);
Bundle args = getArguments();
device = args.getParcelable(EXTRA_DEVICE);
}
if (device == null) {
@@ -76,7 +80,7 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
finish();
}
mManager = LocalBluetoothManager.getInstance(this);
mManager = LocalBluetoothManager.getInstance(getActivity());
mCachedDevice = mManager.getCachedDeviceManager().findDevice(device);
if (mCachedDevice == null) {
Log.w(TAG, "Device not found, cannot connect to it");
@@ -84,39 +88,43 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
addPreferencesFromResource(R.xml.bluetooth_device_advanced);
getPreferenceScreen().setOrderingAsAdded(false);
mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER);
mAllowIncomingPref = (CheckBoxPreference) findPreference(KEY_ALLOW_INCOMING);
mAllowIncomingPref.setChecked(isIncomingFileTransfersAllowed());
mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE);
mDeviceNamePref.setSummary(mCachedDevice.getName());
mDeviceNamePref.setText(mCachedDevice.getName());
// Set the title of the screen
findPreference(KEY_TITLE).setTitle(
getString(R.string.bluetooth_device_advanced_title, mCachedDevice.getName()));
// Listen for check/uncheck of the online mode checkbox
mOnlineModePreference = (CheckBoxPreference) findPreference(KEY_ONLINE_MODE);
mOnlineModePreference.setOnPreferenceChangeListener(this);
findPreference(KEY_TITLE).setTitle(getResources()
.getString(R.string.bluetooth_device_advanced_title, mCachedDevice.getName()));
// Add a preference for each profile
addPreferencesForProfiles();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(EXTRA_DEVICE, mCachedDevice.getDevice());
}
@Override
protected void onResume() {
public void onResume() {
super.onResume();
mManager.setForegroundActivity(this);
mManager.setForegroundActivity(getActivity());
mCachedDevice.registerCallback(this);
refresh();
}
@Override
protected void onPause() {
public void onPause() {
super.onPause();
mCachedDevice.unregisterCallback(this);
@@ -138,18 +146,20 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
* @return A preference that allows the user to choose whether this profile
* will be connected to.
*/
private CheckBoxPreference createProfilePreference(Profile profile) {
CheckBoxPreference pref = new CheckBoxPreference(this);
private Preference createProfilePreference(Profile profile) {
BluetoothProfilePreference pref = new BluetoothProfilePreference(getActivity(), profile);
pref.setKey(profile.toString());
pref.setTitle(profile.localizedString);
pref.setExpanded(false);
pref.setPersistent(false);
pref.setOnPreferenceChangeListener(this);
pref.setOrder(getProfilePreferenceIndex(profile));
pref.setOnExpandClickListener(this);
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mManager, profile);
/**
* Gray out checkbox while connecting and disconnecting
* Gray out profile while connecting and disconnecting
*/
pref.setEnabled(!mCachedDevice.isBusy());
@@ -158,37 +168,46 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
return pref;
}
public boolean onPreferenceChange(Preference preference, Object newValue) {
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
String key = preference.getKey();
if (TextUtils.isEmpty(key) || newValue == null) return true;
if (preference instanceof BluetoothProfilePreference) {
onProfileClicked(preference, Profile.valueOf(key));
return true;
} else if (key.equals(KEY_UNPAIR)) {
unpairDevice();
finish();
return true;
}
if (key.equals(KEY_ONLINE_MODE)) {
onOnlineModeCheckedStateChanged((Boolean) newValue);
return false;
}
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mAllowIncomingPref) {
setIncomingFileTransfersAllowed(mAllowIncomingPref.isChecked());
} else if (preference == mDeviceNamePref) {
// TODO: Verify and check for error conditions
mCachedDevice.setName(mDeviceNamePref.getText());
} else {
Profile profile = getProfileOf(preference);
if (profile == null) return false;
onProfileCheckedStateChanged(profile, (Boolean) newValue);
return false;
}
return true;
}
private void onOnlineModeCheckedStateChanged(boolean checked) {
setOnlineMode(checked, true);
}
private void onProfileCheckedStateChanged(Profile profile, boolean checked) {
private void onProfileClicked(Preference preference, Profile profile) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mManager, profile);
profileManager.setPreferred(mCachedDevice.getDevice(), checked);
if (mOnlineMode) {
if (checked) {
mCachedDevice.connect(profile);
} else {
mCachedDevice.disconnect(profile);
}
}
// TODO: Get the current state and flip it, updating the summary for the preference
// profileManager.setPreferred(mCachedDevice.getDevice(), checked);
//
// if (checked) {
// mCachedDevice.connect(profile);
// } else {
// mCachedDevice.disconnect(profile);
// }
}
public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) {
@@ -196,51 +215,12 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
private void refresh() {
// We are in 'online mode' if we are connected, connecting, or disconnecting
setOnlineMode(mCachedDevice.isConnected() || mCachedDevice.isBusy(), false);
refreshProfiles();
}
/**
* Switches between online/offline mode.
*
* @param onlineMode Whether to be in online mode, or offline mode.
* @param takeAction Whether to take action (i.e., connect or disconnect)
* based on the new online mode.
*/
private void setOnlineMode(boolean onlineMode, boolean takeAction) {
mOnlineMode = onlineMode;
if (takeAction) {
if (onlineMode) {
mCachedDevice.connect();
} else {
mCachedDevice.disconnect();
}
}
refreshOnlineModePreference();
}
private void refreshOnlineModePreference() {
mOnlineModePreference.setChecked(mOnlineMode);
/* Gray out checkbox while connecting and disconnecting */
mOnlineModePreference.setEnabled(!mCachedDevice.isBusy());
/**
* If the device is online, show status. Otherwise, show a summary that
* describes what the checkbox does.
*/
mOnlineModePreference.setSummary(mOnlineMode ?
mCachedDevice.getSummary(CachedBluetoothDevice.OTHER_PROFILES)
: R.string.bluetooth_device_advanced_online_mode_summary);
}
private void refreshProfiles() {
for (Profile profile : mCachedDevice.getConnectableProfiles()) {
CheckBoxPreference profilePref =
(CheckBoxPreference) findPreference(profile.toString());
Preference profilePref = findPreference(profile.toString());
if (profilePref == null) {
profilePref = createProfilePreference(profile);
mProfileContainer.addPreference(profilePref);
@@ -250,7 +230,7 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
}
private void refreshProfilePreference(CheckBoxPreference profilePref, Profile profile) {
private void refreshProfilePreference(Preference profilePref, Profile profile) {
BluetoothDevice device = mCachedDevice.getDevice();
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mManager, profile);
@@ -262,9 +242,9 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
*/
profilePref.setEnabled(!mCachedDevice.isBusy());
profilePref.setSummary(getProfileSummary(profileManager, profile, device,
connectionStatus, mOnlineMode));
profilePref.setChecked(profileManager.isPreferred(device));
connectionStatus, isDeviceOnline()));
// TODO:
//profilePref.setChecked(profileManager.isPreferred(device));
}
private Profile getProfileOf(Preference pref) {
@@ -307,4 +287,60 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
}
public void onClick(View v) {
if (v.getTag() instanceof Profile) {
Profile prof = (Profile) v.getTag();
CheckBoxPreference autoConnectPref = mAutoConnectPrefs.get(prof.toString());
if (autoConnectPref == null) {
autoConnectPref = new CheckBoxPreference(getActivity());
autoConnectPref.setKey(prof.toString() + AUTO_CONNECT_KEY_SUFFIX);
autoConnectPref.setTitle(getCheckBoxTitle(prof));
autoConnectPref.setOrder(getProfilePreferenceIndex(prof) + 1);
autoConnectPref.setChecked(getAutoConnect(prof));
mAutoConnectPrefs.put(prof.name(), autoConnectPref);
}
BluetoothProfilePreference profilePref =
(BluetoothProfilePreference) findPreference(prof.toString());
if (profilePref != null) {
if (profilePref.isExpanded()) {
mProfileContainer.addPreference(autoConnectPref);
} else {
mProfileContainer.removePreference(autoConnectPref);
}
}
}
}
private int getProfilePreferenceIndex(Profile prof) {
return mProfileContainer.getOrder() + prof.ordinal() * 10;
}
private void unpairDevice() {
mCachedDevice.unpair();
}
private boolean isDeviceOnline() {
// TODO: Verify
return mCachedDevice.isConnected() || mCachedDevice.isBusy();
}
private void setIncomingFileTransfersAllowed(boolean allow) {
// TODO:
Log.d(TAG, "Set allow incoming = " + allow);
}
private boolean isIncomingFileTransfersAllowed() {
// TODO:
return true;
}
private String getCheckBoxTitle(Profile prof) {
// TODO: Use resources and base it on profile if necessary
return "Auto connect";
}
private boolean getAutoConnect(Profile prof) {
// TODO: Get the auto connect toggle state for the profile
return true;
}
}

View File

@@ -47,7 +47,7 @@ public class LocalBluetoothManager {
private static final String SHARED_PREFERENCES_NAME = "bluetooth_settings";
/** Singleton instance. */
private static LocalBluetoothManager INSTANCE;
private static LocalBluetoothManager sInstance;
private boolean mInitialized;
private Context mContext;
@@ -87,17 +87,17 @@ public class LocalBluetoothManager {
public static LocalBluetoothManager getInstance(Context context) {
synchronized (LocalBluetoothManager.class) {
if (INSTANCE == null) {
INSTANCE = new LocalBluetoothManager();
if (sInstance == null) {
sInstance = new LocalBluetoothManager();
}
if (!INSTANCE.init(context)) {
if (!sInstance.init(context)) {
return null;
}
LocalBluetoothProfileManager.init(INSTANCE);
LocalBluetoothProfileManager.init(sInstance);
return INSTANCE;
return sInstance;
}
}

View File

@@ -31,12 +31,10 @@ import android.os.ParcelUuid;
import android.util.Log;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* LocalBluetoothProfileManager is an abstract class defining the basic
@@ -123,7 +121,8 @@ public abstract class LocalBluetoothProfileManager {
}
}
private static LinkedList<ServiceListener> mServiceListeners = new LinkedList<ServiceListener>();
private static LinkedList<ServiceListener> mServiceListeners =
new LinkedList<ServiceListener>();
public static void addServiceListener(ServiceListener l) {
mServiceListeners.add(l);
@@ -221,6 +220,10 @@ public abstract class LocalBluetoothProfileManager {
public abstract boolean isProfileReady();
public int getDrawableResource() {
return R.drawable.ic_bt_headphones_a2dp;
}
// TODO: int instead of enum
public enum Profile {
HEADSET(R.string.bluetooth_profile_headset),
@@ -347,6 +350,11 @@ public abstract class LocalBluetoothProfileManager {
public boolean isProfileReady() {
return true;
}
@Override
public int getDrawableResource() {
return R.drawable.ic_bt_headphones_a2dp;
}
}
/**
@@ -489,6 +497,11 @@ public abstract class LocalBluetoothProfileManager {
return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN;
}
}
@Override
public int getDrawableResource() {
return R.drawable.ic_bt_headset_hfp;
}
}
/**
@@ -563,6 +576,12 @@ public abstract class LocalBluetoothProfileManager {
return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN;
}
}
@Override
public int getDrawableResource() {
// TODO:
return 0;
}
}
private static class HidProfileManager extends LocalBluetoothProfileManager {
@@ -645,6 +664,12 @@ public abstract class LocalBluetoothProfileManager {
mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_OFF);
}
}
@Override
public int getDrawableResource() {
// TODO:
return 0;
}
}
private static class PanProfileManager extends LocalBluetoothProfileManager {
@@ -721,5 +746,11 @@ public abstract class LocalBluetoothProfileManager {
public void setPreferred(BluetoothDevice device, boolean preferred) {
return;
}
@Override
public int getDrawableResource() {
// TODO:
return 0;
}
}
}