1e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan/* 2e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * Copyright (C) 2009 The Android Open Source Project 3e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * 4e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 5e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * you may not use this file except in compliance with the License. 6e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * You may obtain a copy of the License at 7e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * 8e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * http://www.apache.org/licenses/LICENSE-2.0 9e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * 10e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * Unless required by applicable law or agreed to in writing, software 11e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * distributed under the License is distributed on an "AS IS" BASIS, 12e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * See the License for the specific language governing permissions and 14e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * limitations under the License. 15e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan */ 16e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 17e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanpackage com.android.settings.bluetooth; 18e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 190cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.annotation.NonNull; 20834e5993e4f2f34d5aceb3196601b30231d00b07Michael Chanimport android.app.Activity; 21a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chanimport android.app.AlertDialog; 22e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.bluetooth.BluetoothAdapter; 23e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.bluetooth.BluetoothDevice; 24e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.BroadcastReceiver; 25e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.Context; 26e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.DialogInterface; 27e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.Intent; 28e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.IntentFilter; 290cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.content.pm.ApplicationInfo; 300cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.content.pm.PackageManager; 31e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.os.Bundle; 320cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.text.TextUtils; 33e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.util.Log; 34e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 35f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settings.R; 36f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver; 37f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settingslib.bluetooth.LocalBluetoothAdapter; 38f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settingslib.bluetooth.LocalBluetoothManager; 39f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monk 40e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan/** 4117d2124c1ccb1bd46393f70252d06d866646e97dWei Wang * RequestPermissionActivity asks the user whether to enable discovery. This is 4217d2124c1ccb1bd46393f70252d06d866646e97dWei Wang * usually started by an application wanted to start bluetooth and or discovery 43e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan */ 44a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chanpublic class RequestPermissionActivity extends Activity implements 45e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan DialogInterface.OnClickListener { 46e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan // Command line to test this 47e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan // adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE 48e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE 49b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISABLE 50e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 51e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan private static final String TAG = "RequestPermissionActivity"; 52e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 53d955af8461b845a1ce4f9beba9decfc2cffb0966Jaikumar Ganesh private static final int MAX_DISCOVERABLE_TIMEOUT = 3600; // 1 hr 54e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 55b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov static final int REQUEST_ENABLE = 1; 56b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov static final int REQUEST_ENABLE_DISCOVERABLE = 2; 57b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov static final int REQUEST_DISABLE = 3; 58e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private LocalBluetoothAdapter mLocalAdapter; 60e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 61e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT; 62e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 63b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov private int mRequest; 64e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private AlertDialog mDialog; 66a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan 67b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov private BroadcastReceiver mReceiver; 68e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 690cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov private @NonNull CharSequence mAppLabel; 700cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov 71e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan @Override 72e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan protected void onCreate(Bundle savedInstanceState) { 73e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan super.onCreate(savedInstanceState); 74e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 75b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov setResult(Activity.RESULT_CANCELED); 76b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Note: initializes mLocalAdapter and returns true on error 78e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan if (parseIntent()) { 79e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan finish(); 80e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan return; 81e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 82e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int btState = mLocalAdapter.getState(); 84e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 85b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mRequest == REQUEST_DISABLE) { 86b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov switch (btState) { 87b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_OFF: 88b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_TURNING_OFF: { 89eb56b9ccb8fa70a6c567d0bcd02f821e4de4bf7bWei Wang proceedAndFinish(); 90b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 91b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 92b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_ON: 93b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_TURNING_ON: { 94b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov Intent intent = new Intent(this, RequestPermissionHelperActivity.class); 950cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel); 96b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov intent.setAction(RequestPermissionHelperActivity 97b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov .ACTION_INTERNAL_REQUEST_BT_OFF); 980cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov 99b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov startActivityForResult(intent, 0); 100b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 101b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 102b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov default: { 103b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov Log.e(TAG, "Unknown adapter state: " + btState); 104b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov cancelAndFinish(); 105b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 106b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 107b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } else { 108b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov switch (btState) { 109b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_OFF: 110b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_TURNING_OFF: 111b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_TURNING_ON: { 112b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov /* 113b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * Strictly speaking STATE_TURNING_ON belong with STATE_ON; 114b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * however, BT may not be ready when the user clicks yes and we 115b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * would fail to turn on discovery mode. By kicking this to the 116b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * RequestPermissionHelperActivity, this class will handle that 117b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * case via the broadcast receiver. 118b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov */ 119b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 120b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov /* 121b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * Start the helper activity to: 122b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * 1) ask the user about enabling bt AND discovery 123b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov * 2) enable BT upon confirmation 124b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov */ 125b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov Intent intent = new Intent(this, RequestPermissionHelperActivity.class); 126b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON); 1270cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel); 128b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mRequest == REQUEST_ENABLE_DISCOVERABLE) { 129b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout); 130b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 131b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov startActivityForResult(intent, 0); 132b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 133b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 134b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case BluetoothAdapter.STATE_ON: { 135b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mRequest == REQUEST_ENABLE) { 136b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // Nothing to do. Already enabled. 137b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov proceedAndFinish(); 138b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } else { 139b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // Ask the user about enabling discovery mode 140b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov createDialog(); 141b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 142b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 143b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 144b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov default: { 145b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov Log.e(TAG, "Unknown adapter state: " + btState); 146b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov cancelAndFinish(); 147b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 148b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 149e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 150e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 151e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 152e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan private void createDialog() { 153b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (getResources().getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) { 154b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov onClick(null, DialogInterface.BUTTON_POSITIVE); 155b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov return; 156b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 157b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 158a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan AlertDialog.Builder builder = new AlertDialog.Builder(this); 159e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 160b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // Non-null receiver means we are toggling 161b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mReceiver != null) { 162b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov switch (mRequest) { 163b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_ENABLE: 164b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_ENABLE_DISCOVERABLE: { 165b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov builder.setMessage(getString(R.string.bluetooth_turning_on)); 166b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 167b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 168b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov default: { 169b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov builder.setMessage(getString(R.string.bluetooth_turning_off)); 170b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 171b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 172a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan builder.setCancelable(false); 17317d2124c1ccb1bd46393f70252d06d866646e97dWei Wang } else { 174e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan // Ask the user whether to turn on discovery mode or not 1751b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren // For lasting discoverable mode there is a different message 1761b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) { 1770cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov CharSequence message = mAppLabel != null 1780cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov ? getString(R.string.bluetooth_ask_lasting_discovery, mAppLabel) 1790cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov : getString(R.string.bluetooth_ask_lasting_discovery_no_name); 1800cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov builder.setMessage(message); 1811b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren } else { 1820cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov CharSequence message = mAppLabel != null 183ebbfce0bf1cebf74525c9cceeeedcd1fe6012b60Jack He ? getString(R.string.bluetooth_ask_discovery, mAppLabel, mTimeout) 184ebbfce0bf1cebf74525c9cceeeedcd1fe6012b60Jack He : getString(R.string.bluetooth_ask_discovery_no_name, mTimeout); 1850cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov builder.setMessage(message); 1861b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren } 18795c1003f1c6ea957065fa752d89c9f64b599461cJake Hamby builder.setPositiveButton(getString(R.string.allow), this); 18895c1003f1c6ea957065fa752d89c9f64b599461cJake Hamby builder.setNegativeButton(getString(R.string.deny), this); 189e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 190e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 191a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan mDialog = builder.create(); 192a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan mDialog.show(); 193e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 194e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 195e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan @Override 196e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan protected void onActivityResult(int requestCode, int resultCode, Intent data) { 197b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (resultCode != Activity.RESULT_OK) { 198b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov cancelAndFinish(); 199a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan return; 200e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 201e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 202b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov switch (mRequest) { 203b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_ENABLE: 204b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_ENABLE_DISCOVERABLE: { 205b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) { 206b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov proceedAndFinish(); 207b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } else { 208b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // If BT is not up yet, show "Turning on Bluetooth..." 209b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov mReceiver = new StateChangeReceiver(); 210b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov registerReceiver(mReceiver, new IntentFilter( 211b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov BluetoothAdapter.ACTION_STATE_CHANGED)); 212b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov createDialog(); 213b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 214b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 215e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 216b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_DISABLE: { 217b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_OFF) { 218b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov proceedAndFinish(); 219b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } else { 220b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // If BT is not up yet, show "Turning off Bluetooth..." 221b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov mReceiver = new StateChangeReceiver(); 222b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov registerReceiver(mReceiver, new IntentFilter( 223b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov BluetoothAdapter.ACTION_STATE_CHANGED)); 224b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov createDialog(); 225b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 226b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 227b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 228b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov default: { 229b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov cancelAndFinish(); 230b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 231e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 232e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 233e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 234e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan public void onClick(DialogInterface dialog, int which) { 235e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan switch (which) { 236e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan case DialogInterface.BUTTON_POSITIVE: 237a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan proceedAndFinish(); 238e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan break; 239e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 240e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan case DialogInterface.BUTTON_NEGATIVE: 241436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby setResult(RESULT_CANCELED); 242a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan finish(); 243e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan break; 244e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 245e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 246e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 247a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan private void proceedAndFinish() { 248e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan int returnCode; 249e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 250b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mRequest == REQUEST_ENABLE || mRequest == REQUEST_DISABLE) { 251b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov // BT toggled. Done 252436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby returnCode = RESULT_OK; 25317d2124c1ccb1bd46393f70252d06d866646e97dWei Wang } else if (mLocalAdapter.setScanMode( 254e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) { 255e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan // If already in discoverable mode, this will extend the timeout. 2564bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala long endTime = System.currentTimeMillis() + (long) mTimeout * 1000; 257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothPreferences.persistDiscoverableEndTimestamp( 2584bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala this, endTime); 2594bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala if (0 < mTimeout) { 2604bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(this, endTime); 2614bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala } 262e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan returnCode = mTimeout; 263834e5993e4f2f34d5aceb3196601b30231d00b07Michael Chan // Activity.RESULT_FIRST_USER should be 1 264436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (returnCode < RESULT_FIRST_USER) { 265436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby returnCode = RESULT_FIRST_USER; 266834e5993e4f2f34d5aceb3196601b30231d00b07Michael Chan } 267e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } else { 268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby returnCode = RESULT_CANCELED; 269e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 270e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 271a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan if (mDialog != null) { 272a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan mDialog.dismiss(); 273e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 274a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan 275a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan setResult(returnCode); 276a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan finish(); 277e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 278e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 279b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov private void cancelAndFinish() { 280b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov setResult(Activity.RESULT_CANCELED); 281b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov finish(); 282b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 283b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 284436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby /** 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Parse the received Intent and initialize mLocalBluetoothAdapter. 286436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * @return true if an error occurred; false otherwise 287436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 288e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan private boolean parseIntent() { 289e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan Intent intent = getIntent(); 290b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (intent == null) { 291b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov return true; 292b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 293b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) { 294b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov mRequest = REQUEST_ENABLE; 295b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } else if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)) { 296b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov mRequest = REQUEST_DISABLE; 297b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } else if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) { 298b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov mRequest = REQUEST_ENABLE_DISCOVERABLE; 299e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT); 301e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 302d955af8461b845a1ce4f9beba9decfc2cffb0966Jaikumar Ganesh Log.d(TAG, "Setting Bluetooth Discoverable Timeout = " + mTimeout); 303e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 3046dcab67c0ccf5d9a644059260a16f46a07043eeeAjay Panicker if (mTimeout < 1 || mTimeout > MAX_DISCOVERABLE_TIMEOUT) { 305e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT; 306e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 307e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } else { 308e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan Log.e(TAG, "Error: this activity may be started only with intent " 309e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan + BluetoothAdapter.ACTION_REQUEST_ENABLE + " or " 310e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan + BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); 311436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby setResult(RESULT_CANCELED); 312e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan return true; 313e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 314e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 315f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monk LocalBluetoothManager manager = Utils.getLocalBtManager(this); 316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (manager == null) { 317436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "Error: there's a problem starting Bluetooth"); 318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby setResult(RESULT_CANCELED); 319e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan return true; 320e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 3210cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov 3220cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov String packageName = getCallingPackage(); 3230cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov if (TextUtils.isEmpty(packageName)) { 3240cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); 3250cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov } 3260cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov if (!TextUtils.isEmpty(packageName)) { 3270cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov try { 3280cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo( 3290cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov packageName, 0); 3300cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov mAppLabel = applicationInfo.loadSafeLabel(getPackageManager()); 3310cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov } catch (PackageManager.NameNotFoundException e) { 3320cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov Log.e(TAG, "Couldn't find app with package name " + packageName); 3330cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov setResult(RESULT_CANCELED); 3340cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov return true; 3350cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov } 3360cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov } 3370cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov 338436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = manager.getBluetoothAdapter(); 339e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 340e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan return false; 341e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 342e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 343e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan @Override 344e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan protected void onDestroy() { 345e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan super.onDestroy(); 346b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (mReceiver != null) { 347436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby unregisterReceiver(mReceiver); 348b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov mReceiver = null; 349436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 350e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 351e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan 352e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan @Override 353e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan public void onBackPressed() { 354436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby setResult(RESULT_CANCELED); 355e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan super.onBackPressed(); 356e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan } 357b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 358b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov private final class StateChangeReceiver extends BroadcastReceiver { 359b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov private static final long TOGGLE_TIMEOUT_MILLIS = 10000; // 10 sec 360b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 361b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov public StateChangeReceiver() { 362b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov getWindow().getDecorView().postDelayed(() -> { 363b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (!isFinishing() && !isDestroyed()) { 364b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov cancelAndFinish(); 365b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 366b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov }, TOGGLE_TIMEOUT_MILLIS); 367b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 368b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 369b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov public void onReceive(Context context, Intent intent) { 370b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (intent == null) { 371b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov return; 372b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 373b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov final int currentState = intent.getIntExtra( 374b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov BluetoothAdapter.EXTRA_STATE, BluetoothDevice.ERROR); 375b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov switch (mRequest) { 376b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_ENABLE: 377b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_ENABLE_DISCOVERABLE: { 378b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (currentState == BluetoothAdapter.STATE_ON) { 379b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov proceedAndFinish(); 380b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 381b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 382b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov 383b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov case REQUEST_DISABLE: { 384b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov if (currentState == BluetoothAdapter.STATE_OFF) { 385b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov proceedAndFinish(); 386b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 387b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } break; 388b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 389b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 390b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov } 391e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan} 392