在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. jquery11源码 animate() : 运动的方法

    { var fxNow, timerId, rfxtypes = /^(?:toggle|show|hide)$/, rfxnum = new RegExp( "^(?:([+-])=|)( ...

  2. js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable

    js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable 一.总结 一句话总结:bootstrap能够做为最火的框架,绝对不仅仅只有我看到的位置,它应该还有很多位置可 ...

  3. 33.IDEA + maven]在IDEA中打开一个maven项目,resolve完依赖后,缺少部分jar包问题

    转自:https://www.cnblogs.com/zazalu/p/7649590.html [注意]作者只是对使用过程中遇到的问题提出了一个解决方案,但是本人在编写此解决方案文章的时候,对mav ...

  4. MATLAB 最优化计算 (二)

    matlab 程序设计 1, for start:increment:end  若默认步长为1,则为 for start:end ———— end while  condition ————  end ...

  5. OpenCV —— 摄像机模型与标定

    这种理论看的已经够多了,感觉应用价值不大(矫正畸变图像还凑合,用摄像机测距神马的...) 有始有终吧,简单把内容梳理一下 针孔  摄像机模型 —— 过于理想(不能为快速曝光收集足够的光线) 透镜可以聚 ...

  6. Block Manager

    在Spark中,将数据抽象为Block(不论是shuffle数据,还是节点本身存储的数据),而每个driver/executor中的block都是由`BlockManager`这个类来负责管理的.对于 ...

  7. 关于我遇到的“LNK 2019无法解析的外部符号”的链接错误

    昨天在调试程序的时候出现了"LNK 2019无法解析的外部符号"的问题(VS2008),依照网上说的方法都没有解决这个问题,最后在项目文件里发现有两个同名的可是不在同一个目录下的c ...

  8. Javascript 继承和克隆

    个人总结: call 继承的是父类私有 prototype 继承的父类公有 create 可以将公有或私有继承到子类上去(克隆) for in 克隆 不管公有还是私有的都克隆成私有的 1.原型继承:将 ...

  9. python学习 第六天课后总结:

    <br class="Apple-interchange-newline"><div></div>       python学习 第六天课后总结 ...

  10. Spider_req

    requests模块 安装(用管理员身份去打开Anaconda Prompt) conda install requests python -m pip install requests # 以管理员 ...