OSDN Git Service

Merge "Bluetooth : fix for crashing alertDialogbox"
[android-x86/packages-apps-Settings.git] / src / com / android / settings / bluetooth / BluetoothSettings.java
1 /*
2  * Copyright (C) 2011 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.app.ActionBar;
20 import android.app.Activity;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.os.Bundle;
28 import android.preference.Preference;
29 import android.preference.PreferenceActivity;
30 import android.preference.PreferenceCategory;
31 import android.preference.PreferenceGroup;
32 import android.preference.PreferenceScreen;
33 import android.util.Log;
34 import android.view.Gravity;
35 import android.view.LayoutInflater;
36 import android.view.Menu;
37 import android.view.MenuInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.ViewGroup;
41 import android.widget.Switch;
42 import android.widget.TextView;
43
44 import com.android.settings.ProgressCategory;
45 import com.android.settings.R;
46
47 /**
48  * BluetoothSettings is the Settings screen for Bluetooth configuration and
49  * connection management.
50  */
51 public final class BluetoothSettings extends DeviceListPreferenceFragment {
52     private static final String TAG = "BluetoothSettings";
53
54     private static final int MENU_ID_SCAN = Menu.FIRST;
55     private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
56     private static final int MENU_ID_VISIBILITY_TIMEOUT = Menu.FIRST + 2;
57     private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 3;
58
59     /* Private intent to show the list of received files */
60     private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
61             "android.btopp.intent.action.OPEN_RECEIVED_FILES";
62
63     private BluetoothEnabler mBluetoothEnabler;
64
65     private BluetoothDiscoverableEnabler mDiscoverableEnabler;
66
67     private PreferenceGroup mPairedDevicesCategory;
68
69     private PreferenceGroup mAvailableDevicesCategory;
70     private boolean mAvailableDevicesCategoryIsPresent;
71
72     private View mView;
73     private TextView mEmptyView;
74
75     private final IntentFilter mIntentFilter;
76
77     // accessed from inner class (not private to avoid thunks)
78     Preference mMyDevicePreference;
79
80     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
81         @Override
82         public void onReceive(Context context, Intent intent) {
83             String action = intent.getAction();
84             if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
85                 updateDeviceName();
86             }
87         }
88
89         private void updateDeviceName() {
90             if (mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
91                 mMyDevicePreference.setTitle(mLocalAdapter.getName());
92             }
93         }
94     };
95
96     public BluetoothSettings() {
97         mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
98     }
99
100     @Override
101     public View onCreateView(LayoutInflater inflater, ViewGroup container,
102             Bundle savedInstanceState) {
103         mView = inflater.inflate(R.layout.custom_preference_list_fragment, container, false);
104         return mView;
105     }
106
107     @Override
108     public void onActivityCreated(Bundle savedInstanceState) {
109         super.onActivityCreated(savedInstanceState);
110
111         mEmptyView = (TextView) mView.findViewById(R.id.empty);
112         getListView().setEmptyView(mEmptyView);
113     }
114
115     @Override
116     void addPreferencesForActivity() {
117         addPreferencesFromResource(R.xml.bluetooth_settings);
118
119         Activity activity = getActivity();
120
121         Switch actionBarSwitch = new Switch(activity);
122
123         if (activity instanceof PreferenceActivity) {
124             PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
125             if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {
126                 final int padding = activity.getResources().getDimensionPixelSize(
127                         R.dimen.action_bar_switch_padding);
128                 actionBarSwitch.setPadding(0, 0, padding, 0);
129                 activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
130                         ActionBar.DISPLAY_SHOW_CUSTOM);
131                 activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(
132                         ActionBar.LayoutParams.WRAP_CONTENT,
133                         ActionBar.LayoutParams.WRAP_CONTENT,
134                         Gravity.CENTER_VERTICAL | Gravity.RIGHT));
135             }
136         }
137
138         mBluetoothEnabler = new BluetoothEnabler(activity, actionBarSwitch);
139
140         setHasOptionsMenu(true);
141     }
142
143     @Override
144     public void onResume() {
145         super.onResume();
146
147         mBluetoothEnabler.resume();
148         if (mDiscoverableEnabler != null) {
149             mDiscoverableEnabler.resume();
150         }
151         getActivity().registerReceiver(mReceiver, mIntentFilter);
152
153         updateContent(mLocalAdapter.getBluetoothState());
154     }
155
156     @Override
157     public void onPause() {
158         super.onPause();
159         mBluetoothEnabler.pause();
160         getActivity().unregisterReceiver(mReceiver);
161         if (mDiscoverableEnabler != null) {
162             mDiscoverableEnabler.pause();
163         }
164     }
165
166     @Override
167     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
168         boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
169         boolean isDiscovering = mLocalAdapter.isDiscovering();
170         int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
171             R.string.bluetooth_search_for_devices;
172         menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
173                 .setEnabled(bluetoothIsEnabled && !isDiscovering)
174                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
175         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
176                 .setEnabled(bluetoothIsEnabled)
177                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
178         menu.add(Menu.NONE, MENU_ID_VISIBILITY_TIMEOUT, 0, R.string.bluetooth_visibility_timeout)
179                 .setEnabled(bluetoothIsEnabled)
180                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
181         menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
182                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
183     }
184
185     @Override
186     public boolean onOptionsItemSelected(MenuItem item) {
187         switch (item.getItemId()) {
188             case MENU_ID_SCAN:
189                 if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
190                     startScanning();
191                 }
192                 return true;
193
194             case MENU_ID_RENAME_DEVICE:
195                 new BluetoothNameDialogFragment(mLocalAdapter).show(
196                         getFragmentManager(), "rename device");
197                 return true;
198
199             case MENU_ID_VISIBILITY_TIMEOUT:
200                 new BluetoothVisibilityTimeoutFragment(mDiscoverableEnabler).show(
201                         getFragmentManager(), "visibility timeout");
202                 return true;
203
204             case MENU_ID_SHOW_RECEIVED:
205                 Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
206                 getActivity().sendBroadcast(intent);
207                 return true;
208         }
209         return super.onOptionsItemSelected(item);
210     }
211
212     private void startScanning() {
213         if (!mAvailableDevicesCategoryIsPresent) {
214             getPreferenceScreen().addPreference(mAvailableDevicesCategory);
215         }
216         mLocalAdapter.startScanning(true);
217     }
218
219     @Override
220     void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
221         mLocalAdapter.stopScanning();
222         super.onDevicePreferenceClick(btPreference);
223     }
224
225     private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
226             BluetoothDeviceFilter.Filter filter) {
227         preferenceGroup.setTitle(titleId);
228         getPreferenceScreen().addPreference(preferenceGroup);
229         setFilter(filter);
230         setDeviceListGroup(preferenceGroup);
231         addCachedDevices();
232         preferenceGroup.setEnabled(true);
233     }
234
235     private void updateContent(int bluetoothState) {
236         final PreferenceScreen preferenceScreen = getPreferenceScreen();
237         int messageId = 0;
238
239         switch (bluetoothState) {
240             case BluetoothAdapter.STATE_ON:
241                 preferenceScreen.removeAll();
242                 preferenceScreen.setOrderingAsAdded(true);
243
244                 // This device
245                 if (mMyDevicePreference == null) {
246                     mMyDevicePreference = new Preference(getActivity());
247                 }
248                 mMyDevicePreference.setTitle(mLocalAdapter.getName());
249                 mMyDevicePreference.setPersistent(false);
250                 mMyDevicePreference.setEnabled(true);
251                 preferenceScreen.addPreference(mMyDevicePreference);
252
253                 if (mDiscoverableEnabler == null) {
254                     mDiscoverableEnabler = new BluetoothDiscoverableEnabler(getActivity(),
255                             mLocalAdapter, mMyDevicePreference);
256                     mDiscoverableEnabler.resume();
257                 }
258
259                 // Paired devices category
260                 if (mPairedDevicesCategory == null) {
261                     mPairedDevicesCategory = new PreferenceCategory(getActivity());
262                 } else {
263                     mPairedDevicesCategory.removeAll();
264                 }
265                 addDeviceCategory(mPairedDevicesCategory,
266                         R.string.bluetooth_preference_paired_devices,
267                         BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
268                 int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
269
270                 mDiscoverableEnabler.setNumberOfPairedDevices(numberOfPairedDevices);
271
272                 // Available devices category
273                 if (mAvailableDevicesCategory == null) {
274                     mAvailableDevicesCategory = new ProgressCategory(getActivity(), null);
275                 } else {
276                     mAvailableDevicesCategory.removeAll();
277                 }
278                 addDeviceCategory(mAvailableDevicesCategory,
279                         R.string.bluetooth_preference_found_devices,
280                         BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
281                 int numberOfAvailableDevices = mAvailableDevicesCategory.getPreferenceCount();
282                 mAvailableDevicesCategoryIsPresent = true;
283
284                 if (numberOfAvailableDevices == 0) {
285                     preferenceScreen.removePreference(mAvailableDevicesCategory);
286                     mAvailableDevicesCategoryIsPresent = false;
287                 }
288
289                 if (numberOfPairedDevices == 0) {
290                     preferenceScreen.removePreference(mPairedDevicesCategory);
291                     startScanning();
292                 }
293                 getActivity().invalidateOptionsMenu();
294                 return; // not break
295
296             case BluetoothAdapter.STATE_TURNING_OFF:
297                 messageId = R.string.bluetooth_turning_off;
298                 break;
299
300             case BluetoothAdapter.STATE_OFF:
301                 messageId = R.string.bluetooth_empty_list_bluetooth_off;
302                 break;
303
304             case BluetoothAdapter.STATE_TURNING_ON:
305                 messageId = R.string.bluetooth_turning_on;
306                 break;
307         }
308
309         setDeviceListGroup(preferenceScreen);
310         removeAllDevices();
311         mEmptyView.setText(messageId);
312         getActivity().invalidateOptionsMenu();
313     }
314
315     @Override
316     public void onBluetoothStateChanged(int bluetoothState) {
317         super.onBluetoothStateChanged(bluetoothState);
318         updateContent(bluetoothState);
319     }
320
321     @Override
322     public void onScanningStateChanged(boolean started) {
323         super.onScanningStateChanged(started);
324         // Update options' enabled state
325         getActivity().invalidateOptionsMenu();
326     }
327
328     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
329         setDeviceListGroup(getPreferenceScreen());
330         removeAllDevices();
331         updateContent(mLocalAdapter.getBluetoothState());
332     }
333
334     private final View.OnClickListener mDeviceProfilesListener = new View.OnClickListener() {
335         public void onClick(View v) {
336             // User clicked on advanced options icon for a device in the list
337             if (v.getTag() instanceof CachedBluetoothDevice) {
338                 CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
339
340                 Preference pref = new Preference(getActivity());
341                 pref.setTitle(device.getName());
342                 pref.setFragment(DeviceProfilesSettings.class.getName());
343                 pref.getExtras().putParcelable(DeviceProfilesSettings.EXTRA_DEVICE,
344                         device.getDevice());
345                 ((PreferenceActivity) getActivity()).onPreferenceStartFragment(
346                         BluetoothSettings.this, pref);
347             } else {
348                 Log.w(TAG, "onClick() called for other View: " + v); // TODO remove
349             }
350         }
351     };
352
353     /**
354      * Add a listener, which enables the advanced settings icon.
355      * @param preference the newly added preference
356      */
357     @Override
358     void initDevicePreference(BluetoothDevicePreference preference) {
359         CachedBluetoothDevice cachedDevice = preference.getCachedDevice();
360         if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
361             // Only paired device have an associated advanced settings screen
362             preference.setOnSettingsClickListener(mDeviceProfilesListener);
363         }
364     }
365 }