1,工具类
package com.win16.bluetoothclass5;
import java.util.List;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Build;
import android.os.CountDownTimer;
/**
* @Description:
* @author eandroidhu
* @date 2014年10月17日 上午10:56:47
*/
public abstract class BluetoothHeadsetUtils {
private Context mContext;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothHeadset mBluetoothHeadset;
private BluetoothDevice mConnectedHeadset;
private AudioManager mAudioManager;
private boolean mIsOnHeadsetSco;
private boolean mIsStarted;
/**
* Constructor
*
* @param context
*/
public BluetoothHeadsetUtils(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
}
/**
* Call this to start BluetoothHeadsetUtils functionalities.
*
* @return The return value of startBluetooth() or startBluetooth11()
*/
public boolean start() {
if (mBluetoothAdapter.isEnabled() == false){
mIsStarted = false;
return mIsStarted;
}
if (!mIsStarted) {
mIsStarted = true;
mIsStarted = startBluetooth();
}
return mIsStarted;
}
/**
* Should call this on onResume or onDestroy. Unregister broadcast receivers
* and stop Sco audio connection and cancel count down.
*/
public void stop() {
if (mIsStarted) {
mIsStarted = false;
stopBluetooth();
}
}
/**
*
* @return true if audio is connected through headset.
*/
public boolean isOnHeadsetSco() {
return mIsOnHeadsetSco;
}
public abstract void onHeadsetDisconnected();
public abstract void onHeadsetConnected();
public abstract void onScoAudioDisconnected();
public abstract void onScoAudioConnected();
/**
* Register a headset profile listener
*
* @return false if device does not support bluetooth or current platform
* does not supports use of SCO for off call or error in getting
* profile proxy.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private boolean startBluetooth() {
// Device support bluetooth
if (mBluetoothAdapter != null) {
if (mAudioManager.isBluetoothScoAvailableOffCall()) {
// All the detection and audio connection are done in
// mHeadsetProfileListener
if (mBluetoothAdapter.getProfileProxy(mContext, mHeadsetProfileListener, BluetoothProfile.HEADSET)) {
return true;
}
}
}
return false;
}
/**
* API >= 11 Unregister broadcast receivers and stop Sco audio connection
* and cancel count down.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
protected void stopBluetooth() {
if (mBluetoothHeadset != null) {
// Need to call stopVoiceRecognition here when the app
// change orientation or close with headset still turns on.
mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
mContext.unregisterReceiver(mHeadsetBroadcastReceiver);
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
mBluetoothHeadset = null;
}
}
/**
* API >= 11 Check for already connected headset and if so start audio
* connection. Register for broadcast of headset and Sco audio connection
* states.
*/
private BluetoothProfile.ServiceListener mHeadsetProfileListener = new BluetoothProfile.ServiceListener() {
/**
* This method is never called, even when we closeProfileProxy on
* onPause. When or will it ever be called???
*/
@Override
public void onServiceDisconnected(int profile) {
stopBluetooth();
}
@SuppressWarnings("synthetic-access")
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
// mBluetoothHeadset is just a headset profile,
// it does not represent a headset device.
mBluetoothHeadset = (BluetoothHeadset) proxy;
// If a headset is connected before this application starts,
// ACTION_CONNECTION_STATE_CHANGED will not be broadcast.
// So we need to check for already connected headset.
List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
if (devices.size() > 0) {
// Only one headset can be connected at a time,
// so the connected headset is at index 0.
mConnectedHeadset = devices.get(0);
onHeadsetConnected();
}
// During the active life time of the app, a user may turn on and
// off the headset.
// So register for broadcast of connection states.
mContext.registerReceiver(mHeadsetBroadcastReceiver, new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
// Calling startVoiceRecognition does not result in immediate audio
// connection.
// So register for broadcast of audio connection states. This
// broadcast will
// only be sent if startVoiceRecognition returns true.
mContext.registerReceiver(mHeadsetBroadcastReceiver, new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
}
};
/**
* API >= 11 Handle headset and Sco audio connection states.
*/
private BroadcastReceiver mHeadsetBroadcastReceiver = new BroadcastReceiver() {
@SuppressWarnings("synthetic-access")
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
int state;
if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
if (state == BluetoothHeadset.STATE_CONNECTED) {
mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Calling startVoiceRecognition always returns false here,
// that why a count down timer is implemented to call
// startVoiceRecognition in the onTick.
// override this if you want to do other thing when the
// device is connected.
onHeadsetConnected();
} else if (state == BluetoothHeadset.STATE_DISCONNECTED) {
mConnectedHeadset = null;
// override this if you want to do other thing when the
// device is disconnected.
onHeadsetDisconnected();
}
} else // audio
{
state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
// override this if you want to do other thing when headset
// audio is connected.
onScoAudioConnected();
} else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
mIsOnHeadsetSco = false;
// override this if you want to do other thing when headset
// audio is disconnected.
onScoAudioDisconnected();
}
}
}
};
}
2,帮助类
package com.win16.bluetoothclass5;
import android.content.Context;
import android.media.AudioManager;
/**
* @Description:
* @author eandroidhu
* @date 2014年10月17日 上午11:00:02
*/
public class BluetoothHelper extends BluetoothHeadsetUtils {
private final static String TAG = BluetoothHelper.class.getSimpleName();
Context mContext;
int mCallvol;
// int mMediaVol;
AudioManager mAudioManager;
public BluetoothHelper(Context context) {
super(context);
mContext = context;
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mCallvol = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
// mMediaVol = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
}
@Override
public void onHeadsetDisconnected() {
mAudioManager.setBluetoothScoOn(false);
}
@Override
public void onHeadsetConnected() {
mAudioManager.setBluetoothScoOn(true); // 打开SCO
// mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
}
@Override
public void onScoAudioDisconnected() {
mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, mCallvol, 0);
// mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mMediaVol, 0);
}
@Override
public void onScoAudioConnected() {
mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0);
// mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
}
}
3,源码下载