/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.bluetooth; import com.android.settings.R; import android.app.Activity; import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; /** * RequestPermissionActivity asks the user whether to enable discovery. This is * usually started by an application wanted to start bluetooth and or discovery */ public class RequestPermissionActivity extends Activity implements DialogInterface.OnClickListener { // Command line to test this // adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE private static final String TAG = "RequestPermissionActivity"; private static final int MAX_DISCOVERABLE_TIMEOUT = 3600; // 1 hr // Non-error return code: BT is starting or has started successfully. Used // by this Activity and RequestPermissionHelperActivity /* package */ static final int RESULT_BT_STARTING_OR_STARTED = -1000; private static final int REQUEST_CODE_START_BT = 1; private LocalBluetoothAdapter mLocalAdapter; private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT; /* * True if bluetooth wasn't enabled and RequestPermissionHelperActivity was * started to ask the user and start bt. * * If/when that activity returns successfully, display please wait msg then * go away when bt has started and discovery mode has been enabled. */ private boolean mNeededToEnableBluetooth; // True if requesting BT to be turned on // False if requesting BT to be turned on + discoverable mode private boolean mEnableOnly; private boolean mUserConfirmed; private AlertDialog mDialog; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent == null) { return; } if (mNeededToEnableBluetooth && BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothDevice.ERROR); if (state == BluetoothAdapter.STATE_ON) { if (mUserConfirmed) { proceedAndFinish(); } } } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Note: initializes mLocalAdapter and returns true on error if (parseIntent()) { finish(); return; } int btState = mLocalAdapter.getState(); switch (btState) { case BluetoothAdapter.STATE_OFF: case BluetoothAdapter.STATE_TURNING_OFF: case BluetoothAdapter.STATE_TURNING_ON: /* * Strictly speaking STATE_TURNING_ON belong with STATE_ON; * however, BT may not be ready when the user clicks yes and we * would fail to turn on discovery mode. By kicking this to the * RequestPermissionHelperActivity, this class will handle that * case via the broadcast receiver. */ /* * Start the helper activity to: * 1) ask the user about enabling bt AND discovery * 2) enable BT upon confirmation */ registerReceiver(mReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); Intent intent = new Intent(); intent.setClass(this, RequestPermissionHelperActivity.class); if (mEnableOnly) { intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON); } else { intent.setAction(RequestPermissionHelperActivity. ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE); intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout); } startActivityForResult(intent, REQUEST_CODE_START_BT); mNeededToEnableBluetooth = true; break; case BluetoothAdapter.STATE_ON: if (mEnableOnly) { // Nothing to do. Already enabled. proceedAndFinish(); } else { // Ask the user about enabling discovery mode createDialog(); } break; default: Log.e(TAG, "Unknown adapter state: " + btState); } } private void createDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setTitle(getString(R.string.bluetooth_permission_request)); if (mNeededToEnableBluetooth) { // RequestPermissionHelperActivity has gotten confirmation from user // to turn on BT builder.setMessage(getString(R.string.bluetooth_turning_on)); builder.setCancelable(false); } else { // Ask the user whether to turn on discovery mode or not // For lasting discoverable mode there is a different message if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) { builder.setMessage( getString(R.string.bluetooth_ask_lasting_discovery)); } else { builder.setMessage( getString(R.string.bluetooth_ask_discovery, mTimeout)); } builder.setPositiveButton(getString(R.string.yes), this); builder.setNegativeButton(getString(R.string.no), this); } mDialog = builder.create(); mDialog.show(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode != REQUEST_CODE_START_BT) { Log.e(TAG, "Unexpected onActivityResult " + requestCode + ' ' + resultCode); setResult(RESULT_CANCELED); finish(); return; } if (resultCode != RESULT_BT_STARTING_OR_STARTED) { setResult(resultCode); finish(); return; } // Back from RequestPermissionHelperActivity. User confirmed to enable // BT and discoverable mode. mUserConfirmed = true; if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) { proceedAndFinish(); } else { // If BT is not up yet, show "Turning on Bluetooth..." createDialog(); } } public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: proceedAndFinish(); break; case DialogInterface.BUTTON_NEGATIVE: setResult(RESULT_CANCELED); finish(); break; } } private void proceedAndFinish() { int returnCode; if (mEnableOnly) { // BT enabled. Done returnCode = RESULT_OK; } else if (mLocalAdapter.setScanMode( BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) { // If already in discoverable mode, this will extend the timeout. LocalBluetoothPreferences.persistDiscoverableEndTimestamp( this, System.currentTimeMillis() + (long) mTimeout * 1000); returnCode = mTimeout; // Activity.RESULT_FIRST_USER should be 1 if (returnCode < RESULT_FIRST_USER) { returnCode = RESULT_FIRST_USER; } } else { returnCode = RESULT_CANCELED; } if (mDialog != null) { mDialog.dismiss(); } setResult(returnCode); finish(); } /** * Parse the received Intent and initialize mLocalBluetoothAdapter. * @return true if an error occurred; false otherwise */ private boolean parseIntent() { Intent intent = getIntent(); if (intent != null && intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) { mEnableOnly = true; } else if (intent != null && intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) { mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT); Log.d(TAG, "Setting Bluetooth Discoverable Timeout = " + mTimeout); if (mTimeout < 0 || mTimeout > MAX_DISCOVERABLE_TIMEOUT) { mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT; } } else { Log.e(TAG, "Error: this activity may be started only with intent " + BluetoothAdapter.ACTION_REQUEST_ENABLE + " or " + BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); setResult(RESULT_CANCELED); return true; } LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this); if (manager == null) { Log.e(TAG, "Error: there's a problem starting Bluetooth"); setResult(RESULT_CANCELED); return true; } mLocalAdapter = manager.getBluetoothAdapter(); return false; } @Override protected void onDestroy() { super.onDestroy(); if (mNeededToEnableBluetooth) { unregisterReceiver(mReceiver); } } @Override public void onBackPressed() { setResult(RESULT_CANCELED); super.onBackPressed(); } }