BluetoothHeadsetpublic final class BluetoothHeadset extends Object implements BluetoothProfilePublic API for controlling the Bluetooth Headset Service. This includes both
Bluetooth Headset and Handsfree (v1.5) profiles.
BluetoothHeadset is a proxy object for controlling the Bluetooth Headset
Service via IPC.
Use {@link BluetoothAdapter#getProfileProxy} to get
the BluetoothHeadset proxy object. Use
{@link BluetoothAdapter#closeProfileProxy} to close the service connection.
Android only supports one connected Bluetooth Headset at a time.
Each method is protected with its appropriate permission. |
Fields Summary |
---|
private static final String | TAG | private static final boolean | DBG | private static final boolean | VDBG | public static final String | ACTION_CONNECTION_STATE_CHANGEDIntent used to broadcast the change in connection state of the Headset
profile.
This intent will have 3 extras:
- {@link #EXTRA_STATE} - The current state of the profile.
- {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
- {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
{@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
{@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
Requires {@link android.Manifest.permission#BLUETOOTH} permission to
receive. | public static final String | ACTION_AUDIO_STATE_CHANGEDIntent used to broadcast the change in the Audio Connection state of the
A2DP profile.
This intent will have 3 extras:
- {@link #EXTRA_STATE} - The current state of the profile.
- {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
- {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
{@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED},
Requires {@link android.Manifest.permission#BLUETOOTH} permission
to receive. | public static final String | ACTION_VENDOR_SPECIFIC_HEADSET_EVENTIntent used to broadcast that the headset has posted a
vendor-specific event.
This intent will have 4 extras and 1 category.
- {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device
- {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor
specific command
- {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT
command type which can be one of {@link #AT_CMD_TYPE_READ},
{@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET},
{@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}.
- {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command
arguments.
The category is the Company ID of the vendor defining the
vendor-specific command. {@link BluetoothAssignedNumbers}
For example, for Plantronics specific events
Category will be {@link #VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY}.55
For example, an AT+XEVENT=foo,3 will get translated into
- EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT
- EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET
- EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3
Requires {@link android.Manifest.permission#BLUETOOTH} permission
to receive. | public static final String | EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMDA String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
intents that contains the name of the vendor-specific command. | public static final String | EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPEAn int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
intents that contains the AT command type of the vendor-specific command. | public static final int | AT_CMD_TYPE_READAT command type READ used with
{@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
For example, AT+VGM?. There are no arguments for this command type. | public static final int | AT_CMD_TYPE_TESTAT command type TEST used with
{@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
For example, AT+VGM=?. There are no arguments for this command type. | public static final int | AT_CMD_TYPE_SETAT command type SET used with
{@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
For example, AT+VGM=. | public static final int | AT_CMD_TYPE_BASICAT command type BASIC used with
{@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
For example, ATD. Single character commands and everything following the
character are arguments. | public static final int | AT_CMD_TYPE_ACTIONAT command type ACTION used with
{@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
For example, AT+CHUP. There are no arguments for action commands. | public static final String | EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGSA Parcelable String array extra field in
{@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains
the arguments to the vendor-specific command. | public static final String | VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORYThe intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
for the companyId | public static final String | VENDOR_RESULT_CODE_COMMAND_ANDROIDA vendor-specific command for unsolicited result code. | public static final int | STATE_AUDIO_DISCONNECTEDHeadset state when SCO audio is not connected.
This state can be one of
{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
{@link #ACTION_AUDIO_STATE_CHANGED} intent. | public static final int | STATE_AUDIO_CONNECTINGHeadset state when SCO audio is connecting.
This state can be one of
{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
{@link #ACTION_AUDIO_STATE_CHANGED} intent. | public static final int | STATE_AUDIO_CONNECTEDHeadset state when SCO audio is connected.
This state can be one of
{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
{@link #ACTION_AUDIO_STATE_CHANGED} intent. | private static final int | MESSAGE_HEADSET_SERVICE_CONNECTED | private static final int | MESSAGE_HEADSET_SERVICE_DISCONNECTED | private android.content.Context | mContext | private ServiceListener | mServiceListener | private IBluetoothHeadset | mService | private BluetoothAdapter | mAdapter | private final IBluetoothStateChangeCallback | mBluetoothStateChangeCallback | private final IBluetoothProfileServiceConnection | mConnection | private final android.os.Handler | mHandler |
Constructors Summary |
---|
BluetoothHeadset(android.content.Context context, ServiceListener l)Create a BluetoothHeadset proxy object.
/*package*/
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
doBind();
|
Methods Summary |
---|
public boolean | acceptIncomingConnect(BluetoothDevice device)Accept the incoming connection.
Note: This is an internal function and shouldn't be exposed
if (DBG) log("acceptIncomingConnect");
if (mService != null && isEnabled()) {
try {
return mService.acceptIncomingConnect(device);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public void | clccResponse(int index, int direction, int status, int mode, boolean mpty, java.lang.String number, int type)Send Headset of CLCC response
if (mService != null && isEnabled()) {
try {
mService.clccResponse(index, direction, status, mode, mpty, number, type);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
| void | close()Close the connection to the backing service.
Other public functions of BluetoothHeadset will return default error
results once close() has been called. Multiple invocations of close()
are ok.
if (VDBG) log("close()");
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG,"",e);
}
}
mServiceListener = null;
doUnbind();
| public boolean | connect(BluetoothDevice device)Initiate connection to a profile of the remote bluetooth device.
Currently, the system supports only 1 connection to the
headset/handsfree profile. The API will automatically disconnect connected
devices before connecting.
This API returns false in scenarios like the profile on the
device is already connected or Bluetooth is not turned on.
When this API returns true, it is guaranteed that
connection state intent for the profile will be broadcasted with
the state. Users can get the connection state of the profile
from this intent.
Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
permission.
if (DBG) log("connect(" + device + ")");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
| public boolean | connectAudio()Initiates a connection of headset audio.
It setup SCO channel with remote connected headset device.
if (mService != null && isEnabled()) {
try {
return mService.connectAudio();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public boolean | disableWBS()disable WBS codec settting. It set NBS codec.
if (mService != null && isEnabled()) {
try {
return mService.disableWBS();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public boolean | disconnect(BluetoothDevice device)Initiate disconnection from a profile
This API will return false in scenarios like the profile on the
Bluetooth device is not in connected state etc. When this API returns,
true, it is guaranteed that the connection state change
intent will be broadcasted with the state. Users can get the
disconnection state of the profile from this intent.
If the disconnection is initiated by a remote device, the state
will transition from {@link #STATE_CONNECTED} to
{@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
host (local) device the state will transition from
{@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
state {@link #STATE_DISCONNECTED}. The transition to
{@link #STATE_DISCONNECTING} can be used to distinguish between the
two scenarios.
Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
permission.
if (DBG) log("disconnect(" + device + ")");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
| public boolean | disconnectAudio()Initiates a disconnection of headset audio.
It tears down the SCO channel from remote headset device.
if (mService != null && isEnabled()) {
try {
return mService.disconnectAudio();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| boolean | doBind()
try {
return mAdapter.getBluetoothManager().bindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG, "Unable to bind HeadsetService", e);
}
return false;
| void | doUnbind()
synchronized (mConnection) {
if (mService != null) {
try {
mAdapter.getBluetoothManager().unbindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG,"Unable to unbind HeadsetService", e);
}
}
}
| public boolean | enableWBS()enable WBS codec setting.
if (mService != null && isEnabled()) {
try {
return mService.enableWBS();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public int | getAudioState(BluetoothDevice device)Get the current audio state of the Headset.
Note: This is an internal function and shouldn't be exposed
if (VDBG) log("getAudioState");
if (mService != null && !isDisabled()) {
try {
return mService.getAudioState(device);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
| public int | getBatteryUsageHint(BluetoothDevice device)Get battery usage hint for Bluetooth Headset service.
This is a monotonically increasing integer. Wraps to 0 at
Integer.MAX_INT, and at boot.
Current implementation returns the number of AT commands handled since
boot. This is a good indicator for spammy headset/handsfree units that
can keep the device awake by polling for cellular status updates. As a
rule of thumb, each AT command prevents the CPU from sleeping for 500 ms
if (VDBG) log("getBatteryUsageHint()");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.getBatteryUsageHint(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return -1;
| public java.util.List | getConnectedDevices(){@inheritDoc}
if (VDBG) log("getConnectedDevices()");
if (mService != null && isEnabled()) {
try {
return mService.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
| public int | getConnectionState(BluetoothDevice device){@inheritDoc}
if (VDBG) log("getConnectionState(" + device + ")");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
| public java.util.List | getDevicesMatchingConnectionStates(int[] states){@inheritDoc}
if (VDBG) log("getDevicesMatchingStates()");
if (mService != null && isEnabled()) {
try {
return mService.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
| public int | getPriority(BluetoothDevice device)Get the priority of the profile.
The priority can be any of:
{@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
{@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
Requires {@link android.Manifest.permission#BLUETOOTH} permission.
if (VDBG) log("getPriority(" + device + ")");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return PRIORITY_OFF;
| public boolean | isAudioConnected(BluetoothDevice device)Check if Bluetooth SCO audio is connected.
Requires {@link android.Manifest.permission#BLUETOOTH} permission.
if (VDBG) log("isAudioConnected()");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.isAudioConnected(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
| public boolean | isAudioOn()Check if Bluetooth SCO audio is connected.
Requires {@link android.Manifest.permission#BLUETOOTH} permission.
if (VDBG) log("isAudioOn()");
if (mService != null && isEnabled()) {
try {
return mService.isAudioOn();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
| public static boolean | isBluetoothVoiceDialingEnabled(android.content.Context context)Indicates if current platform supports voice dialing over bluetooth SCO.
return context.getResources().getBoolean(
com.android.internal.R.bool.config_bluetooth_sco_off_call);
| private boolean | isDisabled()
if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true;
return false;
| private boolean | isEnabled()
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;
| private boolean | isValidDevice(BluetoothDevice device)
if (device == null) return false;
if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
return false;
| private static void | log(java.lang.String msg)
Log.d(TAG, msg);
| public void | phoneStateChanged(int numActive, int numHeld, int callState, java.lang.String number, int type)Notify Headset of phone state change.
This is a backdoor for phone app to call BluetoothHeadset since
there is currently not a good way to get precise call state change outside
of phone app.
if (mService != null && isEnabled()) {
try {
mService.phoneStateChanged(numActive, numHeld, callState, number, type);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
| public boolean | rejectIncomingConnect(BluetoothDevice device)Reject the incoming connection.
if (DBG) log("rejectIncomingConnect");
if (mService != null) {
try {
return mService.rejectIncomingConnect(device);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public boolean | sendVendorSpecificResultCode(BluetoothDevice device, java.lang.String command, java.lang.String arg)Sends a vendor-specific unsolicited result code to the headset.
The actual string to be sent is command + ": " + arg .
For example, if {@code command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg}
is {@code "0"}, the string "+ANDROID: 0" will be sent.
Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}.
Requires {@link android.Manifest.permission#BLUETOOTH} permission.
if (DBG) {
log("sendVendorSpecificResultCode()");
}
if (command == null) {
throw new IllegalArgumentException("command is null");
}
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.sendVendorSpecificResultCode(device, command, arg);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
if (mService == null) {
Log.w(TAG, "Proxy not attached to service");
}
return false;
| public boolean | setPriority(BluetoothDevice device, int priority)Set priority of the profile
The device should already be paired.
Priority can be one of {@link #PRIORITY_ON} or
{@link #PRIORITY_OFF},
Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
permission.
if (DBG) log("setPriority(" + device + ", " + priority + ")");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF &&
priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
return mService.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
| public boolean | startScoUsingVirtualVoiceCall(BluetoothDevice device)Initiates a SCO channel connection with the headset (if connected).
Also initiates a virtual voice call for Handsfree devices as many devices
do not accept SCO audio without a call.
This API allows the handsfree device to be used for routing non-cellular
call audio.
if (DBG) log("startScoUsingVirtualVoiceCall()");
if (mService != null && isEnabled() && isValidDevice(device)) {
try {
return mService.startScoUsingVirtualVoiceCall(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public boolean | startVoiceRecognition(BluetoothDevice device)Start Bluetooth voice recognition. This methods sends the voice
recognition AT command to the headset and establishes the
audio connection.
Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
If this function returns true, this intent will be broadcasted with
{@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
{@link #EXTRA_STATE} will transition from
{@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
in case of failure to establish the audio connection.
Requires {@link android.Manifest.permission#BLUETOOTH} permission.
if (DBG) log("startVoiceRecognition()");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.startVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
| public boolean | stopScoUsingVirtualVoiceCall(BluetoothDevice device)Terminates an ongoing SCO connection and the associated virtual
call.
if (DBG) log("stopScoUsingVirtualVoiceCall()");
if (mService != null && isEnabled() && isValidDevice(device)) {
try {
return mService.stopScoUsingVirtualVoiceCall(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
} else {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
return false;
| public boolean | stopVoiceRecognition(BluetoothDevice device)Stop Bluetooth Voice Recognition mode, and shut down the
Bluetooth audio path.
Requires {@link android.Manifest.permission#BLUETOOTH} permission.
if (DBG) log("stopVoiceRecognition()");
if (mService != null && isEnabled() &&
isValidDevice(device)) {
try {
return mService.stopVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
|
|