在Android程序中可以实现自动扫描蓝牙、配对蓝牙、建立数据通道。
蓝牙分不同类型,可以参考(http://gqdy365.iteye.com/admin/blogs/2229304)

可以入下面方法获取蓝牙设备支持的类型:

  1. BluetoothDevice device;
  2. Arrays.toString(device.getUuids());

我的蓝牙音箱支持的类型有:

  1. 0000111e-0000-1000-8000-00805f9b34fb:Handsfree
  2. 0000110b-0000-1000-8000-00805f9b34fb:AudioSink
  3. 0000110e-0000-1000-8000-00805f9b34fb:AVRemoteControl
  4. 00001203-0000-1000-8000-00805f9b34fb:GenericFileTransfer

这篇文字只讨论如何与蓝牙耳机(蓝牙音箱)连接。

蓝牙耳机一般都支持A2DP(蓝牙立体声,用于音乐播放)、HFP协议(通话),参考:http://gqdy365.iteye.com/admin/blogs/2231553

所以下面操作要同时操作A2DP和HFP,两个都连接成功,才算连接成功;

一、A2DP的操作可以分三步:

1、扫描蓝牙设备:

注册并监听广播:

  1. BluetoothAdapter.ACTION_DISCOVERY_STARTED
  2. BluetoothDevice.ACTION_FOUND
  3. BluetoothAdapter.ACTION_DISCOVERY_FINISHED

启动扫描:

  1. BluetoothAdapter.getDefaultAdapter().startDiscovery();

对扫描的结果按类型进行筛选,只保留我们需要的蓝牙耳机:

  1. if(device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET
  2. || device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE){
  3. //蓝牙耳机
  4. }

2、配对指定的蓝牙设备:

这个跟配对普通蓝牙一样,方法如下:

  1. public static  boolean createBond(BluetoothDevice btDevice){
  2. boolean result = false;
  3. try{
  4. Method m = btDevice.getClass().getDeclaredMethod("createBond",new Class[]{});
  5. m.setAccessible(true);
  6. Boolean originalResult = (Boolean) m.invoke(btDevice);
  7. result = originalResult.booleanValue();
  8. }catch(Exception ex){
  9. }
  10. return result;
  11. }

等配对完成之后就是要建立数据连接;

3、建立数据连接:

if you SDK between 11 and 16.call a2dp.connectSink(btDevice) or a2dp.connect(btDevice)

  1. private static IBluetoothA2dp getIBluetoothA2dp() {
  2. IBluetoothA2dp ibta = null;
  3. try {
  4. final Class serviceManager = Class.forName("android.os.ServiceManager");
  5. final Method getService = serviceManager.getDeclaredMethod("getService", String.class);
  6. final IBinder iBinder = (IBinder) getService.invoke(null, "bluetooth_a2dp");
  7. final Class iBluetoothA2dp = Class.forName("android.bluetooth.IBluetoothA2dp");
  8. final Class[] declaredClasses = iBluetoothA2dp.getDeclaredClasses();
  9. final Class c = declaredClasses[0];
  10. final Method asInterface = c.getDeclaredMethod("asInterface", IBinder.class);
  11. asInterface.setAccessible(true);
  12. ibta = (IBluetoothA2dp) asInterface.invoke(null, iBinder);
  13. } catch (final Exception e) {
  14. Log.e("Error " + e.getMessage());
  15. }
  16. return ibta;
  17. }

参考:http://stackoverflow.com/questions/8467178/working-around-a2dp-and-hfp-limitations-of-android-pre-honeycomb

如果API大于16需要用如下的方法:

  1. private void initA2dpService(){
  2. //      Intent i = getExplicitIntent(mContext,new Intent(IBluetoothA2dp.class.getName()));//5.0以上系统需要显示intent
  3. //详细参考http://blog.csdn.net/l2show/article/details/47421961
  4. Intent i = new Intent(IBluetoothA2dp.class.getName());
  5. boolean success = mContext.bindService(i, mConnection, Context.BIND_AUTO_CREATE);
  6. if (success) {
  7. } else {
  8. }
  9. }
  10. public ServiceConnection mConnection = new ServiceConnection() {
  11. @Override
  12. public void onServiceConnected(ComponentName name, IBinder service) {
  13. try {
  14. mA2dpService = IBluetoothA2dp.Stub.asInterface(service);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. @Override
  20. public void onServiceDisconnected(ComponentName name) {
  21. // TODO Auto-generated method stub
  22. }
  23. };
  24. public Intent getExplicitIntent(Context context, Intent implicitIntent) {
  25. // Retrieve all services that can match the given intent
  26. PackageManager pm = context.getPackageManager();
  27. List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
  28. // Make sure only one match was found
  29. if (resolveInfo == null || resolveInfo.size() != 1) {
  30. return null;
  31. }
  32. // Get component info and create ComponentName
  33. ResolveInfo serviceInfo = resolveInfo.get(0);
  34. String packageName = serviceInfo.serviceInfo.packageName;
  35. String className = serviceInfo.serviceInfo.name;
  36. ComponentName component = new ComponentName(packageName, className);
  37. // Create a new intent. Use the old one for extras and such reuse
  38. Intent explicitIntent = new Intent(implicitIntent);
  39. // Set the component to be explicit
  40. explicitIntent.setComponent(component);
  41. return explicitIntent;
  42. }

建立连接:mA2dpService.connect(device);

断开连接:mA2dpService.disconnect(device);

参考:http://stackoverflow.com/questions/14705167/how-connect-paired-bluetooth-a2dp-device-on-android-4-2-using-reflection

http://blog.csdn.net/qs_csu/article/details/45114251

二、HFP操作:

下面只针对4.0及以上版本;

1、初始化:

  1. private void initOrCloseBtCheck(boolean init){
  2. if(init){
  3. mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  4. mBluetoothAdapter.getProfileProxy(mContext, new ServiceListener() {
  5. public void onServiceConnected(int profile, BluetoothProfile proxy) {
  6. if (profile == BluetoothProfile.HEADSET) {
  7. mBluetoothHeadset = (BluetoothHeadset) proxy;
  8. }
  9. }
  10. public void onServiceDisconnected(int profile) {
  11. if (profile == BluetoothProfile.HEADSET) {
  12. mBluetoothHeadset = null;
  13. }
  14. }
  15. },BluetoothProfile.HEADSET);
  16. }else{
  17. mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET,mBluetoothHeadset);
  18. }
  19. }

建立连接:

  1. Method m = mBluetoothHeadset.getClass().getDeclaredMethod("connect",BluetoothDevice.class);
  2. m.setAccessible(true);
  3. //连接Headset
  4. boolean successHeadset = (Boolean)m.invoke(mBluetoothHeadset, device);

断开连接:

  1. Method m = mBluetoothHeadset.getClass().getDeclaredMethod("disconnect",BluetoothDevice.class);
  2. m.setAccessible(true);
  3. m.invoke(mBluetoothHeadset, device);

三、状态判断:

蓝牙耳机连接成功:

  1. mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_DISCONNECTED && mBluetoothHeadset.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED

断开成功:

    1. (mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED || mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_PLAYING)
    2. && mBluetoothHeadset.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED

Android实现主动连接蓝牙耳机的更多相关文章

  1. Android 检测是否连接蓝牙耳机

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  2. Android连接蓝牙耳机播放音乐

    参考: Android实现主动连接蓝牙耳机 具体实现: private static final String TAG = "BluetoothA2DPTest"; private ...

  3. Android怎样监听蓝牙耳机的按键事件

    Android怎样监听蓝牙耳机的按键事件 写在前面: 直接想要代码非常easy,你直接把滚动栏拉到最底端就能够看到.假设想要十分地了解为什么,那就依照我规划的一步一步来理解.下面測试环境以手头上有的「 ...

  4. 71.Android之长连接实现

    转载:http://blog.csdn.net/qq_23547831/article/details/51690047 本文中我们将讲解一下App的长连接实现.一般而言长连接已经是App的标配了,推 ...

  5. Android自己主动化測试之Monkeyrunner用法及实例

    眼下android SDK里自带的现成的測试工具有monkey 和 monkeyrunner两个.大家别看这俩兄弟名字相像,但事实上是完全然全不同的两个工具,应用在不同的測试领域.总的来说,monke ...

  6. Android如何监听蓝牙耳机的按键事件(转)

    源: Android如何监听蓝牙耳机的按键事件 写在前面: 直接想要代码很简单,你直接把滚动条拉到最底端就可以看到.如果想要十分地了解为什么,那就按照我规划的一步一步来理解.以下测试环境以手头上有的「 ...

  7. Android蓝牙A2DP连接实现

    代码地址如下:http://www.demodashi.com/demo/14624.html 开发环境: 开发工具:Androidstudio 适配机型:honor8(Android6.0), 坚果 ...

  8. [转]Android TCP长连接 心跳机制及实现

    背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...

  9. Android自己主动化測试解决方式

    如今,已经有大量的Android自己主动化測试架构或工具可供我们使用,当中包含:Activity Instrumentation, MonkeyRunner, Robotium, 以及Robolect ...

随机推荐

  1. Rails + rabl

    当我们使用rails generate scaffold的方式生成MVC的时候,rails会自己主动给我们生成一系列的文件,包含了怎样用json显示model的view.这样事实上默认了你的系统是一个 ...

  2. AVEVA PDMS Text Tool

    AVEVA PDMS Text Tool eryar@163.com 网上有个文字工具插件,可以在PDMS中创建三维的字母.数字,不过不能创建中文.所以开发一个小工具,可以在PDMS中创建任意文字,如 ...

  3. [python]CompressionError: bz2 module is not available

    事情是这种,在centos6 上本来是python2.6 然后我下载了一个python2.7.5 安装之后,把默认python改动为python2.7.5版本号. 使用pip安装twisted的时候出 ...

  4. 56.如何清除已经设置的npm config配置

    npm config delete registry npm config delete disturl 或者 npm config edit 找到淘宝那两行,删除

  5. 洛谷P2192 HXY玩卡片

    题目描述 HXY得到了一些卡片,这些卡片上标有数字0或5.现在她可以选择其中一些卡片排成一列,使得排出的一列数字组成的数最大,且满足被90整除这个条件.同时这个数不能含有前导0,即0不能作为这串数的首 ...

  6. C++ 补课 (三)

    1,枚举类型 —— 下标自0开始 enum 枚举类型名 { 常数表 } 2,C++ 的异常处理机制实际上是一种运行时通知机制 3,delete p;只是删除指针p指向内存区,并不是删除指针p,所以p还 ...

  7. Codefroces Round #429Div2 (A,B,C)

    A. Generous Kefa time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  8. tree ---树状显示

    tree命令以树状图列出目录的内容. 语法 tree(选项)(参数) 选项 -a:显示所有文件和目录: -A:使用ASNI绘图字符显示树状图而非以ASCII字符组合: -C:在文件和目录清单加上色彩, ...

  9. Java中Thread源码剖析

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 关于线程,用很长时间了,主线程下的子线程去做一些事情,就是一个代理模式,主线程分代理权给子线程,子线 ...

  10. 洛谷 P1102 A-B数对

    P1102 A-B数对 题目描述 出题是一件痛苦的事情! 题目看多了也有审美疲劳,于是我舍弃了大家所熟悉的A+B Problem,改用A-B了哈哈! 好吧,题目是这样的:给出一串数以及一个数字C,要求 ...