OSDN Git Service

Don't crash if there's no bluetooth functionality (such as in an emulator) do not...
[android-x86/packages-apps-Settings.git] / src / com / android / settings / bluetooth / BluetoothSettings.java
old mode 100644 (file)
new mode 100755 (executable)
index 76bf623..7c8cb6e
@@ -20,17 +20,26 @@ import android.app.ActionBar;
 import android.app.Activity;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.util.Log;
 import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.Switch;
+import android.widget.TextView;
 
 import com.android.settings.ProgressCategory;
 import com.android.settings.R;
@@ -43,12 +52,59 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
     private static final String TAG = "BluetoothSettings";
 
     private static final int MENU_ID_SCAN = Menu.FIRST;
-    private static final int MENU_ID_ADVANCED = Menu.FIRST + 1;
+    private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
+    private static final int MENU_ID_VISIBILITY_TIMEOUT = Menu.FIRST + 2;
+    private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 3;
+
+    /* Private intent to show the list of received files */
+    private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
+            "android.btopp.intent.action.OPEN_RECEIVED_FILES";
 
     private BluetoothEnabler mBluetoothEnabler;
 
-    private PreferenceGroup mFoundDevicesCategory;
-    private boolean mFoundDevicesCategoryIsPresent;
+    private BluetoothDiscoverableEnabler mDiscoverableEnabler;
+
+    private PreferenceGroup mPairedDevicesCategory;
+
+    private PreferenceGroup mAvailableDevicesCategory;
+    private boolean mAvailableDevicesCategoryIsPresent;
+    private boolean mActivityStarted;
+
+    private TextView mEmptyView;
+
+    private final IntentFilter mIntentFilter;
+
+    // accessed from inner class (not private to avoid thunks)
+    Preference mMyDevicePreference;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
+                updateDeviceName();
+            }
+        }
+
+        private void updateDeviceName() {
+            if (mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
+                mMyDevicePreference.setTitle(mLocalAdapter.getName());
+            }
+        }
+    };
+
+    public BluetoothSettings() {
+        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mActivityStarted = (savedInstanceState == null);    // don't auto start scan after rotation
+
+        mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
+        getListView().setEmptyView(mEmptyView);
+    }
 
     @Override
     void addPreferencesForActivity() {
@@ -75,39 +131,57 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
 
         mBluetoothEnabler = new BluetoothEnabler(activity, actionBarSwitch);
 
-        if (mLocalAdapter != null && mLocalAdapter.isEnabled()) {
-            activity.getActionBar().setSubtitle(mLocalAdapter.getName());
-        }
-
         setHasOptionsMenu(true);
     }
 
     @Override
     public void onResume() {
+        // resume BluetoothEnabler before calling super.onResume() so we don't get
+        // any onDeviceAdded() callbacks before setting up view in updateContent()
+        if (mBluetoothEnabler != null) {
+            mBluetoothEnabler.resume();
+        }
         super.onResume();
 
-        mBluetoothEnabler.resume();
-
-        updateContent(mLocalAdapter.getBluetoothState());
+        if (mDiscoverableEnabler != null) {
+            mDiscoverableEnabler.resume();
+        }
+        getActivity().registerReceiver(mReceiver, mIntentFilter);
+        if (mLocalAdapter != null) {
+            updateContent(mLocalAdapter.getBluetoothState(), mActivityStarted);
+        }
     }
 
     @Override
     public void onPause() {
         super.onPause();
-
-        mBluetoothEnabler.pause();
+        if (mBluetoothEnabler != null) {
+            mBluetoothEnabler.pause();
+        }
+        getActivity().unregisterReceiver(mReceiver);
+        if (mDiscoverableEnabler != null) {
+            mDiscoverableEnabler.pause();
+        }
     }
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        if (mLocalAdapter == null) return;
         boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
-        menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.bluetooth_scan_nearby_devices)
-                //.setIcon(R.drawable.ic_menu_scan_network)
-                .setEnabled(bluetoothIsEnabled && !mLocalAdapter.isDiscovering())
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-        menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.bluetooth_menu_advanced)
-                //.setIcon(android.R.drawable.ic_menu_manage)
+        boolean isDiscovering = mLocalAdapter.isDiscovering();
+        int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
+            R.string.bluetooth_search_for_devices;
+        menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
+                .setEnabled(bluetoothIsEnabled && !isDiscovering)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
+                .setEnabled(bluetoothIsEnabled)
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        menu.add(Menu.NONE, MENU_ID_VISIBILITY_TIMEOUT, 0, R.string.bluetooth_visibility_timeout)
+                .setEnabled(bluetoothIsEnabled)
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
     }
 
     @Override
@@ -118,24 +192,28 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
                     startScanning();
                 }
                 return true;
-            case MENU_ID_ADVANCED:
-                if (getActivity() instanceof PreferenceActivity) {
-                    ((PreferenceActivity) getActivity()).startPreferencePanel(
-                            AdvancedBluetoothSettings.class.getCanonicalName(),
-                            null,
-                            R.string.bluetooth_advanced_titlebar, null,
-                            this, 0);
-                } else {
-                    startFragment(this, AdvancedBluetoothSettings.class.getCanonicalName(), -1, null);
-                }
+
+            case MENU_ID_RENAME_DEVICE:
+                new BluetoothNameDialogFragment().show(
+                        getFragmentManager(), "rename device");
+                return true;
+
+            case MENU_ID_VISIBILITY_TIMEOUT:
+                new BluetoothVisibilityTimeoutFragment().show(
+                        getFragmentManager(), "visibility timeout");
+                return true;
+
+            case MENU_ID_SHOW_RECEIVED:
+                Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
+                getActivity().sendBroadcast(intent);
                 return true;
         }
         return super.onOptionsItemSelected(item);
     }
 
     private void startScanning() {
-        if (!mFoundDevicesCategoryIsPresent) {
-            getPreferenceScreen().addPreference(mFoundDevicesCategory);
+        if (!mAvailableDevicesCategoryIsPresent) {
+            getPreferenceScreen().addPreference(mAvailableDevicesCategory);
         }
         mLocalAdapter.startScanning(true);
     }
@@ -146,50 +224,95 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
         super.onDevicePreferenceClick(btPreference);
     }
 
-    private void updateContent(int bluetoothState) {
+    private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
+            BluetoothDeviceFilter.Filter filter) {
+        preferenceGroup.setTitle(titleId);
+        getPreferenceScreen().addPreference(preferenceGroup);
+        setFilter(filter);
+        setDeviceListGroup(preferenceGroup);
+        addCachedDevices();
+        preferenceGroup.setEnabled(true);
+    }
+
+    private void updateContent(int bluetoothState, boolean scanState) {
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        getActivity().invalidateOptionsMenu();
         int messageId = 0;
 
         switch (bluetoothState) {
             case BluetoothAdapter.STATE_ON:
                 preferenceScreen.removeAll();
-
-                // Add bonded devices from cache first
-                setFilter(BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
-                setDeviceListGroup(preferenceScreen);
                 preferenceScreen.setOrderingAsAdded(true);
+                mDevicePreferenceMap.clear();
 
-                addCachedDevices();
-                int numberOfPairedDevices = preferenceScreen.getPreferenceCount();
+                // This device
+                if (mMyDevicePreference == null) {
+                    mMyDevicePreference = new Preference(getActivity());
+                }
+                mMyDevicePreference.setTitle(mLocalAdapter.getName());
+                if (getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
+                    mMyDevicePreference.setIcon(R.drawable.ic_bt_cellphone);    // for phones
+                } else {
+                    mMyDevicePreference.setIcon(R.drawable.ic_bt_laptop);   // for tablets, etc.
+                }
+                mMyDevicePreference.setPersistent(false);
+                mMyDevicePreference.setEnabled(true);
+                preferenceScreen.addPreference(mMyDevicePreference);
+
+                if (mDiscoverableEnabler == null) {
+                    mDiscoverableEnabler = new BluetoothDiscoverableEnabler(getActivity(),
+                            mLocalAdapter, mMyDevicePreference);
+                    mDiscoverableEnabler.resume();
+                    LocalBluetoothManager.getInstance(getActivity()).setDiscoverableEnabler(
+                            mDiscoverableEnabler);
+                }
 
-                // Found devices category
-                mFoundDevicesCategory = new ProgressCategory(getActivity(), null);
-                mFoundDevicesCategory.setTitle(R.string.bluetooth_preference_found_devices);
-                preferenceScreen.addPreference(mFoundDevicesCategory);
-                mFoundDevicesCategoryIsPresent = true;
+                // Paired devices category
+                if (mPairedDevicesCategory == null) {
+                    mPairedDevicesCategory = new PreferenceCategory(getActivity());
+                } else {
+                    mPairedDevicesCategory.removeAll();
+                }
+                addDeviceCategory(mPairedDevicesCategory,
+                        R.string.bluetooth_preference_paired_devices,
+                        BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
+                int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
 
-                // Unbonded found devices from cache
-                setFilter(BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
-                setDeviceListGroup(mFoundDevicesCategory);
-                addCachedDevices();
+                mDiscoverableEnabler.setNumberOfPairedDevices(numberOfPairedDevices);
 
-                int numberOfUnpairedDevices = mFoundDevicesCategory.getPreferenceCount();
-                if (numberOfUnpairedDevices == 0) {
-                    preferenceScreen.removePreference(mFoundDevicesCategory);
-                    mFoundDevicesCategoryIsPresent = false;
+                // Available devices category
+                if (mAvailableDevicesCategory == null) {
+                    mAvailableDevicesCategory = new ProgressCategory(getActivity(), null);
+                } else {
+                    mAvailableDevicesCategory.removeAll();
+                }
+                addDeviceCategory(mAvailableDevicesCategory,
+                        R.string.bluetooth_preference_found_devices,
+                        BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
+                int numberOfAvailableDevices = mAvailableDevicesCategory.getPreferenceCount();
+                mAvailableDevicesCategoryIsPresent = true;
+
+                if (numberOfAvailableDevices == 0) {
+                    preferenceScreen.removePreference(mAvailableDevicesCategory);
+                    mAvailableDevicesCategoryIsPresent = false;
                 }
 
-                if (numberOfPairedDevices == 0) startScanning();
-
-                return;
+                if (numberOfPairedDevices == 0) {
+                    preferenceScreen.removePreference(mPairedDevicesCategory);
+                    if (scanState == true) {
+                        mActivityStarted = false;
+                        startScanning();
+                    } else {
+                        if (!mAvailableDevicesCategoryIsPresent) {
+                            getPreferenceScreen().addPreference(mAvailableDevicesCategory);
+                        }
+                    }
+                }
+                getActivity().invalidateOptionsMenu();
+                return; // not break
 
             case BluetoothAdapter.STATE_TURNING_OFF:
-                int preferenceCount = preferenceScreen.getPreferenceCount();
-                for (int i = 0; i < preferenceCount; i++) {
-                    preferenceScreen.getPreference(i).setEnabled(false);
-                }
-                return;
+                messageId = R.string.bluetooth_turning_off;
+                break;
 
             case BluetoothAdapter.STATE_OFF:
                 messageId = R.string.bluetooth_empty_list_bluetooth_off;
@@ -202,30 +325,27 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
 
         setDeviceListGroup(preferenceScreen);
         removeAllDevices();
-
-        // TODO: from xml, add top padding. Same as in wifi
-        Preference emptyListPreference = new Preference(getActivity());
-        emptyListPreference.setTitle(messageId);
-        preferenceScreen.addPreference(emptyListPreference);
+        mEmptyView.setText(messageId);
+        getActivity().invalidateOptionsMenu();
     }
 
     @Override
     public void onBluetoothStateChanged(int bluetoothState) {
         super.onBluetoothStateChanged(bluetoothState);
-        updateContent(bluetoothState);
+        updateContent(bluetoothState, true);
     }
 
     @Override
     public void onScanningStateChanged(boolean started) {
         super.onScanningStateChanged(started);
-        // Update 'Scan' option enabled state
+        // Update options' enabled state
         getActivity().invalidateOptionsMenu();
     }
 
     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
         setDeviceListGroup(getPreferenceScreen());
         removeAllDevices();
-        updateContent(mLocalAdapter.getBluetoothState());
+        updateContent(mLocalAdapter.getBluetoothState(), false);
     }
 
     private final View.OnClickListener mDeviceProfilesListener = new View.OnClickListener() {
@@ -234,13 +354,12 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
             if (v.getTag() instanceof CachedBluetoothDevice) {
                 CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
 
-                Preference pref = new Preference(getActivity());
-                pref.setTitle(device.getName());
-                pref.setFragment(DeviceProfilesSettings.class.getName());
-                pref.getExtras().putParcelable(DeviceProfilesSettings.EXTRA_DEVICE,
-                        device.getDevice());
-                ((PreferenceActivity) getActivity()).onPreferenceStartFragment(
-                        BluetoothSettings.this, pref);
+                Bundle args = new Bundle(1);
+                args.putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, device.getDevice());
+
+                ((PreferenceActivity) getActivity()).startPreferencePanel(
+                        DeviceProfilesSettings.class.getName(), args,
+                        R.string.bluetooth_device_advanced_title, null, null, 0);
             } else {
                 Log.w(TAG, "onClick() called for other View: " + v); // TODO remove
             }