OSDN Git Service

Merge "Import revised translations."
[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         // resume BluetoothEnabler before calling super.onResume() so we don't get
146         // any onDeviceAdded() callbacks before setting up view in updateContent()
147         mBluetoothEnabler.resume();
148         super.onResume();
149
150         if (mDiscoverableEnabler != null) {
151             mDiscoverableEnabler.resume();
152         }
153         getActivity().registerReceiver(mReceiver, mIntentFilter);
154
155         updateContent(mLocalAdapter.getBluetoothState());
156     }
157
158     @Override
159     public void onPause() {
160         super.onPause();
161         mBluetoothEnabler.pause();
162         getActivity().unregisterReceiver(mReceiver);
163         if (mDiscoverableEnabler != null) {
164             mDiscoverableEnabler.pause();
165         }
166     }
167
168     @Override
169     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
170         boolean bluetoothIsEnabled = mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON;
171         boolean isDiscovering = mLocalAdapter.isDiscovering();
172         int textId = isDiscovering ? R.string.bluetooth_searching_for_devices :
173             R.string.bluetooth_search_for_devices;
174         menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
175                 .setEnabled(bluetoothIsEnabled && !isDiscovering)
176                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
177         menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
178                 .setEnabled(bluetoothIsEnabled)
179                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
180         menu.add(Menu.NONE, MENU_ID_VISIBILITY_TIMEOUT, 0, R.string.bluetooth_visibility_timeout)
181                 .setEnabled(bluetoothIsEnabled)
182                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
183         menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
184                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
185     }
186
187     @Override
188     public boolean onOptionsItemSelected(MenuItem item) {
189         switch (item.getItemId()) {
190             case MENU_ID_SCAN:
191                 if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
192                     startScanning();
193                 }
194                 return true;
195
196             case MENU_ID_RENAME_DEVICE:
197                 new BluetoothNameDialogFragment(mLocalAdapter).show(
198                         getFragmentManager(), "rename device");
199                 return true;
200
201             case MENU_ID_VISIBILITY_TIMEOUT:
202                 new BluetoothVisibilityTimeoutFragment(mDiscoverableEnabler).show(
203                         getFragmentManager(), "visibility timeout");
204                 return true;
205
206             case MENU_ID_SHOW_RECEIVED:
207                 Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
208                 getActivity().sendBroadcast(intent);
209                 return true;
210         }
211         return super.onOptionsItemSelected(item);
212     }
213
214     private void startScanning() {
215         if (!mAvailableDevicesCategoryIsPresent) {
216             getPreferenceScreen().addPreference(mAvailableDevicesCategory);
217         }
218         mLocalAdapter.startScanning(true);
219     }
220
221     @Override
222     void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
223         mLocalAdapter.stopScanning();
224         super.onDevicePreferenceClick(btPreference);
225     }
226
227     private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
228             BluetoothDeviceFilter.Filter filter) {
229         preferenceGroup.setTitle(titleId);
230         getPreferenceScreen().addPreference(preferenceGroup);
231         setFilter(filter);
232         setDeviceListGroup(preferenceGroup);
233         addCachedDevices();
234         preferenceGroup.setEnabled(true);
235     }
236
237     private void updateContent(int bluetoothState) {
238         final PreferenceScreen preferenceScreen = getPreferenceScreen();
239         int messageId = 0;
240
241         switch (bluetoothState) {
242             case BluetoothAdapter.STATE_ON:
243                 preferenceScreen.removeAll();
244                 preferenceScreen.setOrderingAsAdded(true);
245
246                 // This device
247                 if (mMyDevicePreference == null) {
248                     mMyDevicePreference = new Preference(getActivity());
249                 }
250                 mMyDevicePreference.setTitle(mLocalAdapter.getName());
251                 if (getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
252                     mMyDevicePreference.setIcon(R.drawable.ic_bt_cellphone);    // for phones
253                 } else {
254                     mMyDevicePreference.setIcon(R.drawable.ic_bt_laptop);   // for tablets, etc.
255                 }
256                 mMyDevicePreference.setPersistent(false);
257                 mMyDevicePreference.setEnabled(true);
258                 preferenceScreen.addPreference(mMyDevicePreference);
259
260                 if (mDiscoverableEnabler == null) {
261                     mDiscoverableEnabler = new BluetoothDiscoverableEnabler(getActivity(),
262                             mLocalAdapter, mMyDevicePreference);
263                     mDiscoverableEnabler.resume();
264                 }
265
266                 // Paired devices category
267                 if (mPairedDevicesCategory == null) {
268                     mPairedDevicesCategory = new PreferenceCategory(getActivity());
269                 } else {
270                     mPairedDevicesCategory.removeAll();
271                 }
272                 addDeviceCategory(mPairedDevicesCategory,
273                         R.string.bluetooth_preference_paired_devices,
274                         BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
275                 int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
276
277                 mDiscoverableEnabler.setNumberOfPairedDevices(numberOfPairedDevices);
278
279                 // Available devices category
280                 if (mAvailableDevicesCategory == null) {
281                     mAvailableDevicesCategory = new ProgressCategory(getActivity(), null);
282                 } else {
283                     mAvailableDevicesCategory.removeAll();
284                 }
285                 addDeviceCategory(mAvailableDevicesCategory,
286                         R.string.bluetooth_preference_found_devices,
287                         BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
288                 int numberOfAvailableDevices = mAvailableDevicesCategory.getPreferenceCount();
289                 mAvailableDevicesCategoryIsPresent = true;
290
291                 if (numberOfAvailableDevices == 0) {
292                     preferenceScreen.removePreference(mAvailableDevicesCategory);
293                     mAvailableDevicesCategoryIsPresent = false;
294                 }
295
296                 if (numberOfPairedDevices == 0) {
297                     preferenceScreen.removePreference(mPairedDevicesCategory);
298                     startScanning();
299                 }
300                 getActivity().invalidateOptionsMenu();
301                 return; // not break
302
303             case BluetoothAdapter.STATE_TURNING_OFF:
304                 messageId = R.string.bluetooth_turning_off;
305                 break;
306
307             case BluetoothAdapter.STATE_OFF:
308                 messageId = R.string.bluetooth_empty_list_bluetooth_off;
309                 break;
310
311             case BluetoothAdapter.STATE_TURNING_ON:
312                 messageId = R.string.bluetooth_turning_on;
313                 break;
314         }
315
316         setDeviceListGroup(preferenceScreen);
317         removeAllDevices();
318         mEmptyView.setText(messageId);
319         getActivity().invalidateOptionsMenu();
320     }
321
322     @Override
323     public void onBluetoothStateChanged(int bluetoothState) {
324         super.onBluetoothStateChanged(bluetoothState);
325         updateContent(bluetoothState);
326     }
327
328     @Override
329     public void onScanningStateChanged(boolean started) {
330         super.onScanningStateChanged(started);
331         // Update options' enabled state
332         getActivity().invalidateOptionsMenu();
333     }
334
335     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
336         setDeviceListGroup(getPreferenceScreen());
337         removeAllDevices();
338         updateContent(mLocalAdapter.getBluetoothState());
339     }
340
341     private final View.OnClickListener mDeviceProfilesListener = new View.OnClickListener() {
342         public void onClick(View v) {
343             // User clicked on advanced options icon for a device in the list
344             if (v.getTag() instanceof CachedBluetoothDevice) {
345                 CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
346
347                 Bundle args = new Bundle(1);
348                 args.putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, device.getDevice());
349
350                 ((PreferenceActivity) getActivity()).startPreferencePanel(
351                         DeviceProfilesSettings.class.getName(), args,
352                         R.string.bluetooth_device_advanced_title, null, null, 0);
353             } else {
354                 Log.w(TAG, "onClick() called for other View: " + v); // TODO remove
355             }
356         }
357     };
358
359     /**
360      * Add a listener, which enables the advanced settings icon.
361      * @param preference the newly added preference
362      */
363     @Override
364     void initDevicePreference(BluetoothDevicePreference preference) {
365         CachedBluetoothDevice cachedDevice = preference.getCachedDevice();
366         if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
367             // Only paired device have an associated advanced settings screen
368             preference.setOnSettingsClickListener(mDeviceProfilesListener);
369         }
370     }
371 }