Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2009 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 com.android.settings.R;
     20 
     21 import android.app.Activity;
     22 import android.app.AlertDialog;
     23 import android.bluetooth.BluetoothAdapter;
     24 import android.bluetooth.BluetoothDevice;
     25 import android.content.BroadcastReceiver;
     26 import android.content.Context;
     27 import android.content.DialogInterface;
     28 import android.content.Intent;
     29 import android.content.IntentFilter;
     30 import android.content.SharedPreferences;
     31 import android.os.Bundle;
     32 import android.util.Log;
     33 
     34 /**
     35  * RequestPermissionActivity asks the user whether to enable discovery. This is
     36  * usually started by an application wanted to start bluetooth and or discovery
     37  */
     38 public class RequestPermissionActivity extends Activity implements
     39         DialogInterface.OnClickListener {
     40     // Command line to test this
     41     // adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE
     42     // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE
     43 
     44     private static final String TAG = "RequestPermissionActivity";
     45 
     46     private static final int MAX_DISCOVERABLE_TIMEOUT = 300;
     47 
     48     // Non-error return code: BT is starting or has started successfully. Used
     49     // by this Activity and RequestPermissionHelperActivity
     50     /* package */ static final int RESULT_BT_STARTING_OR_STARTED = -1000;
     51 
     52     private static final int REQUEST_CODE_START_BT = 1;
     53 
     54     private LocalBluetoothManager mLocalManager;
     55 
     56     private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
     57 
     58     /*
     59      * True if bluetooth wasn't enabled and RequestPermissionHelperActivity was
     60      * started to ask the user and start bt.
     61      *
     62      * If/when that activity returns successfully, display please wait msg then
     63      * go away when bt has started and discovery mode has been enabled.
     64      */
     65     private boolean mNeededToEnableBluetooth;
     66 
     67     // True if requesting BT to be turned on
     68     // False if requesting BT to be turned on + discoverable mode
     69     private boolean mEnableOnly = false;
     70 
     71     private boolean mUserConfirmed = false;
     72 
     73     private AlertDialog mDialog = null;
     74 
     75     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
     76 
     77         @Override
     78         public void onReceive(Context context, Intent intent) {
     79             if (intent == null)
     80                 return;
     81             if (mNeededToEnableBluetooth
     82                     && BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
     83                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothDevice.ERROR);
     84                 if (state == BluetoothAdapter.STATE_ON) {
     85                     if (mUserConfirmed) {
     86                         proceedAndFinish();
     87                     }
     88                 }
     89             }
     90         }
     91     };
     92 
     93     @Override
     94     protected void onCreate(Bundle savedInstanceState) {
     95         super.onCreate(savedInstanceState);
     96 
     97         if (parseIntent()) {
     98             finish();
     99             return;
    100         }
    101 
    102         int btState = mLocalManager.getBluetoothState();
    103 
    104         switch (btState) {
    105             case BluetoothAdapter.STATE_OFF:
    106             case BluetoothAdapter.STATE_TURNING_OFF:
    107             case BluetoothAdapter.STATE_TURNING_ON:
    108                 /*
    109                  * Strictly speaking STATE_TURNING_ON belong with STATE_ON;
    110                  * however, BT may not be ready when the user clicks yes and we
    111                  * would fail to turn on discovery mode. By kicking this to the
    112                  * RequestPermissionHelperActivity, this class will handle that
    113                  * case via the broadcast receiver.
    114                  */
    115 
    116                 /*
    117                  * Start the helper activity to:
    118                  * 1) ask the user about enabling bt AND discovery
    119                  * 2) enable BT upon confirmation
    120                  */
    121                 registerReceiver(mReceiver,
    122                         new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
    123                 Intent i = new Intent();
    124                 i.setClass(this, RequestPermissionHelperActivity.class);
    125                 if (mEnableOnly) {
    126                     i.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON);
    127                 } else {
    128                     i.setAction(RequestPermissionHelperActivity.
    129                             ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE);
    130                     i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout);
    131                 }
    132                 startActivityForResult(i, REQUEST_CODE_START_BT);
    133                 mNeededToEnableBluetooth = true;
    134                 break;
    135             case BluetoothAdapter.STATE_ON:
    136                 if (mEnableOnly) {
    137                     // Nothing to do. Already enabled.
    138                     proceedAndFinish();
    139                     return;
    140                 } else {
    141                     // Ask the user about enabling discovery mode
    142                     createDialog();
    143                     break;
    144                 }
    145         }
    146     }
    147 
    148     private void createDialog() {
    149         AlertDialog.Builder builder = new AlertDialog.Builder(this);
    150         builder.setIcon(android.R.drawable.ic_dialog_info);
    151         builder.setTitle(getString(R.string.bluetooth_permission_request));
    152 
    153         if (mNeededToEnableBluetooth) {
    154             // RequestPermissionHelperActivity has gotten confirmation from user
    155             // to turn on BT
    156             builder.setMessage(getString(R.string.bluetooth_turning_on));
    157             builder.setCancelable(false);
    158         } else {
    159             // Ask the user whether to turn on discovery mode or not
    160             builder.setMessage(getString(R.string.bluetooth_ask_enablement_and_discovery, mTimeout));
    161             builder.setPositiveButton(getString(R.string.yes), this);
    162             builder.setNegativeButton(getString(R.string.no), this);
    163         }
    164 
    165         mDialog = builder.create();
    166         mDialog.show();
    167     }
    168 
    169     @Override
    170     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    171         if (requestCode != REQUEST_CODE_START_BT) {
    172             Log.e(TAG, "Unexpected onActivityResult " + requestCode + " " + resultCode);
    173             setResult(Activity.RESULT_CANCELED);
    174             finish();
    175             return;
    176         }
    177         if (resultCode != RESULT_BT_STARTING_OR_STARTED) {
    178             setResult(resultCode);
    179             finish();
    180             return;
    181         }
    182 
    183         // Back from RequestPermissionHelperActivity. User confirmed to enable
    184         // BT and discoverable mode.
    185         mUserConfirmed = true;
    186 
    187         if (mLocalManager.getBluetoothState() == BluetoothAdapter.STATE_ON) {
    188             proceedAndFinish();
    189         } else {
    190             // If BT is not up yet, show "Turning on Bluetooth..."
    191             createDialog();
    192         }
    193     }
    194 
    195     public void onClick(DialogInterface dialog, int which) {
    196         switch (which) {
    197             case DialogInterface.BUTTON_POSITIVE:
    198                 proceedAndFinish();
    199                 break;
    200 
    201             case DialogInterface.BUTTON_NEGATIVE:
    202                 setResult(Activity.RESULT_CANCELED);
    203                 finish();
    204                 break;
    205         }
    206     }
    207 
    208     private void proceedAndFinish() {
    209         int returnCode;
    210 
    211         if (mEnableOnly) {
    212             // BT enabled. Done
    213             returnCode = Activity.RESULT_OK;
    214         } else if (mLocalManager.getBluetoothAdapter().setScanMode(
    215                 BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) {
    216             // If already in discoverable mode, this will extend the timeout.
    217             persistDiscoverableEndTimestamp(System.currentTimeMillis() + mTimeout * 1000);
    218             returnCode = mTimeout;
    219             // Activity.RESULT_FIRST_USER should be 1
    220             if (returnCode < Activity.RESULT_FIRST_USER) {
    221                 returnCode = Activity.RESULT_FIRST_USER;
    222             }
    223         } else {
    224             returnCode = Activity.RESULT_CANCELED;
    225         }
    226 
    227         if (mDialog != null) {
    228             mDialog.dismiss();
    229         }
    230 
    231         setResult(returnCode);
    232         finish();
    233     }
    234 
    235     private boolean parseIntent() {
    236         Intent intent = getIntent();
    237         if (intent != null && intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
    238             mEnableOnly = true;
    239         } else if (intent != null
    240                 && intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) {
    241             mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
    242                     BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);
    243 
    244             Log.e(TAG, "Timeout = " + mTimeout);
    245 
    246             if (mTimeout > MAX_DISCOVERABLE_TIMEOUT) {
    247                 mTimeout = MAX_DISCOVERABLE_TIMEOUT;
    248             } else if (mTimeout <= 0) {
    249                 mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
    250             }
    251         } else {
    252             Log.e(TAG, "Error: this activity may be started only with intent "
    253                     + BluetoothAdapter.ACTION_REQUEST_ENABLE + " or "
    254                     + BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
    255             setResult(Activity.RESULT_CANCELED);
    256             return true;
    257         }
    258 
    259         mLocalManager = LocalBluetoothManager.getInstance(this);
    260         if (mLocalManager == null) {
    261             Log.e(TAG, "Error: there's a problem starting bluetooth");
    262             setResult(Activity.RESULT_CANCELED);
    263             return true;
    264         }
    265 
    266         return false;
    267     }
    268 
    269     @Override
    270     protected void onDestroy() {
    271         super.onDestroy();
    272         if (mNeededToEnableBluetooth) unregisterReceiver(mReceiver);
    273     }
    274 
    275     private void persistDiscoverableEndTimestamp(long endTimestamp) {
    276         SharedPreferences.Editor editor = mLocalManager.getSharedPreferences().edit();
    277         editor.putLong(
    278                 BluetoothDiscoverableEnabler.SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP,
    279                 endTimestamp);
    280         editor.commit();
    281     }
    282 
    283     @Override
    284     public void onBackPressed() {
    285         setResult(Activity.RESULT_CANCELED);
    286         super.onBackPressed();
    287     }
    288 }
    289