Android实现主动连接蓝牙耳机
在Android程序中可以实现自动扫描蓝牙、配对蓝牙、建立数据通道。
蓝牙分不同类型,可以参考(http://gqdy365.iteye.com/admin/blogs/2229304)
可以入下面方法获取蓝牙设备支持的类型:
- BluetoothDevice device;
- Arrays.toString(device.getUuids());
我的蓝牙音箱支持的类型有:
- 0000111e-0000-1000-8000-00805f9b34fb:Handsfree
- 0000110b-0000-1000-8000-00805f9b34fb:AudioSink
- 0000110e-0000-1000-8000-00805f9b34fb:AVRemoteControl
- 00001203-0000-1000-8000-00805f9b34fb:GenericFileTransfer
这篇文字只讨论如何与蓝牙耳机(蓝牙音箱)连接。
蓝牙耳机一般都支持A2DP(蓝牙立体声,用于音乐播放)、HFP协议(通话),参考:http://gqdy365.iteye.com/admin/blogs/2231553
所以下面操作要同时操作A2DP和HFP,两个都连接成功,才算连接成功;
一、A2DP的操作可以分三步:
1、扫描蓝牙设备:
注册并监听广播:
- BluetoothAdapter.ACTION_DISCOVERY_STARTED
- BluetoothDevice.ACTION_FOUND
- BluetoothAdapter.ACTION_DISCOVERY_FINISHED
启动扫描:
- BluetoothAdapter.getDefaultAdapter().startDiscovery();
对扫描的结果按类型进行筛选,只保留我们需要的蓝牙耳机:
- if(device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET
- || device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE){
- //蓝牙耳机
- }
2、配对指定的蓝牙设备:
这个跟配对普通蓝牙一样,方法如下:
- public static boolean createBond(BluetoothDevice btDevice){
- boolean result = false;
- try{
- Method m = btDevice.getClass().getDeclaredMethod("createBond",new Class[]{});
- m.setAccessible(true);
- Boolean originalResult = (Boolean) m.invoke(btDevice);
- result = originalResult.booleanValue();
- }catch(Exception ex){
- }
- return result;
- }
等配对完成之后就是要建立数据连接;
3、建立数据连接:
if you SDK between 11 and 16.call a2dp.connectSink(btDevice) or a2dp.connect(btDevice)
- private static IBluetoothA2dp getIBluetoothA2dp() {
- IBluetoothA2dp ibta = null;
- try {
- final Class serviceManager = Class.forName("android.os.ServiceManager");
- final Method getService = serviceManager.getDeclaredMethod("getService", String.class);
- final IBinder iBinder = (IBinder) getService.invoke(null, "bluetooth_a2dp");
- final Class iBluetoothA2dp = Class.forName("android.bluetooth.IBluetoothA2dp");
- final Class[] declaredClasses = iBluetoothA2dp.getDeclaredClasses();
- final Class c = declaredClasses[0];
- final Method asInterface = c.getDeclaredMethod("asInterface", IBinder.class);
- asInterface.setAccessible(true);
- ibta = (IBluetoothA2dp) asInterface.invoke(null, iBinder);
- } catch (final Exception e) {
- Log.e("Error " + e.getMessage());
- }
- return ibta;
- }
参考:http://stackoverflow.com/questions/8467178/working-around-a2dp-and-hfp-limitations-of-android-pre-honeycomb
如果API大于16需要用如下的方法:
- private void initA2dpService(){
- // Intent i = getExplicitIntent(mContext,new Intent(IBluetoothA2dp.class.getName()));//5.0以上系统需要显示intent
- //详细参考http://blog.csdn.net/l2show/article/details/47421961
- Intent i = new Intent(IBluetoothA2dp.class.getName());
- boolean success = mContext.bindService(i, mConnection, Context.BIND_AUTO_CREATE);
- if (success) {
- } else {
- }
- }
- public ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- try {
- mA2dpService = IBluetoothA2dp.Stub.asInterface(service);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // TODO Auto-generated method stub
- }
- };
- public Intent getExplicitIntent(Context context, Intent implicitIntent) {
- // Retrieve all services that can match the given intent
- PackageManager pm = context.getPackageManager();
- List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
- // Make sure only one match was found
- if (resolveInfo == null || resolveInfo.size() != 1) {
- return null;
- }
- // Get component info and create ComponentName
- ResolveInfo serviceInfo = resolveInfo.get(0);
- String packageName = serviceInfo.serviceInfo.packageName;
- String className = serviceInfo.serviceInfo.name;
- ComponentName component = new ComponentName(packageName, className);
- // Create a new intent. Use the old one for extras and such reuse
- Intent explicitIntent = new Intent(implicitIntent);
- // Set the component to be explicit
- explicitIntent.setComponent(component);
- return explicitIntent;
- }
建立连接: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、初始化:
- private void initOrCloseBtCheck(boolean init){
- if(init){
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- mBluetoothAdapter.getProfileProxy(mContext, new ServiceListener() {
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (profile == BluetoothProfile.HEADSET) {
- mBluetoothHeadset = (BluetoothHeadset) proxy;
- }
- }
- public void onServiceDisconnected(int profile) {
- if (profile == BluetoothProfile.HEADSET) {
- mBluetoothHeadset = null;
- }
- }
- },BluetoothProfile.HEADSET);
- }else{
- mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET,mBluetoothHeadset);
- }
- }
建立连接:
- Method m = mBluetoothHeadset.getClass().getDeclaredMethod("connect",BluetoothDevice.class);
- m.setAccessible(true);
- //连接Headset
- boolean successHeadset = (Boolean)m.invoke(mBluetoothHeadset, device);
断开连接:
- Method m = mBluetoothHeadset.getClass().getDeclaredMethod("disconnect",BluetoothDevice.class);
- m.setAccessible(true);
- m.invoke(mBluetoothHeadset, device);
三、状态判断:
蓝牙耳机连接成功:
- mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_DISCONNECTED && mBluetoothHeadset.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED
断开成功:
- (mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED || mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_PLAYING)
- && mBluetoothHeadset.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
Android实现主动连接蓝牙耳机的更多相关文章
- Android 检测是否连接蓝牙耳机
前言 欢迎大家我分享和推荐好用的代码段~~ 声明 欢迎转载,但请保留文章原始出处: CSDN:http://www.csdn.net ...
- Android连接蓝牙耳机播放音乐
参考: Android实现主动连接蓝牙耳机 具体实现: private static final String TAG = "BluetoothA2DPTest"; private ...
- Android怎样监听蓝牙耳机的按键事件
Android怎样监听蓝牙耳机的按键事件 写在前面: 直接想要代码非常easy,你直接把滚动栏拉到最底端就能够看到.假设想要十分地了解为什么,那就依照我规划的一步一步来理解.下面測试环境以手头上有的「 ...
- 71.Android之长连接实现
转载:http://blog.csdn.net/qq_23547831/article/details/51690047 本文中我们将讲解一下App的长连接实现.一般而言长连接已经是App的标配了,推 ...
- Android自己主动化測试之Monkeyrunner用法及实例
眼下android SDK里自带的现成的測试工具有monkey 和 monkeyrunner两个.大家别看这俩兄弟名字相像,但事实上是完全然全不同的两个工具,应用在不同的測试领域.总的来说,monke ...
- Android如何监听蓝牙耳机的按键事件(转)
源: Android如何监听蓝牙耳机的按键事件 写在前面: 直接想要代码很简单,你直接把滚动条拉到最底端就可以看到.如果想要十分地了解为什么,那就按照我规划的一步一步来理解.以下测试环境以手头上有的「 ...
- Android蓝牙A2DP连接实现
代码地址如下:http://www.demodashi.com/demo/14624.html 开发环境: 开发工具:Androidstudio 适配机型:honor8(Android6.0), 坚果 ...
- [转]Android TCP长连接 心跳机制及实现
背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...
- Android自己主动化測试解决方式
如今,已经有大量的Android自己主动化測试架构或工具可供我们使用,当中包含:Activity Instrumentation, MonkeyRunner, Robotium, 以及Robolect ...
随机推荐
- [Android实例] 高速静默更新,低流量耗费,让APP活跃起来!
大家好.我是csdn的新人,给大家带来一个做了一个星期的SDK,能够实现将Android APP碎片化管理.自由更新,实时更新,低流量耗费的更新~~ Zag Whim Renewal A system ...
- mysql_jdbc
package com.lovo.day18_jdbc1; import java.sql.Connection; import java.sql.DriverManager; import java ...
- FFmpeg的HEVC解码器源码简单分析:解码器主干部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- InnoDB引擎索引大观
InnoDB是mysql处理OLTP(online transcation process)类型业务的存储引擎.为了加快数据查询速度.InnoDB引擎提供了丰富的索引实现. 1. 索引的分类 索引能够 ...
- 关于vuex的项目中数据流动方式
vue的核心是数据驱动,所有数据变更的时机很重要,也就是watch的内容,一般是数据逻辑的操作.在使用vuex的项目中,我们在vuex中只是发请求.拿数据,在视图中来进行逻辑的操作.数据的更新. 1. ...
- 「HAOI2016」字符合并
「HAOI2016」字符合并 题意: 有一个长度为\(n\)的\(01\)串,你可以每次将相邻的\(k\)个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这\(k\)个字符确定.你 ...
- Vue 国家省市三级联动
在网上查阅一下,基本上是省市区三级联动,国家省市的就只能自己动手了. 样式就根据自己的需要去调整了. JSON数组太长,就折叠放在了后面. 效果图: <!DOCTYPE html> < ...
- mv---移动文件或目录
mv命令用来对文件或目录重新命名,或者将文件从一个目录移到另一个目录中.source表示源文件或目录,target表示目标文件或目录.如果将一个文件移到一个已经存在的目标文件中,则目标文件的内容将被覆 ...
- CMDB学习之三数据采集
判断系统因为是公用的方法,所有要写基类方法使用,首先在插件中创建一个基类 将插件文件继承基类 思路是创建基类使用handler.cmd ,命令去获取系统信息,然后进行判断,然后去执行 磁盘 ,cpu, ...
- Spring3 整合MyBatis3 配置多数据源 动态选择SqlSessionFactory(转)
1. Spring整合MyBatis切换SqlSessionFactory有两种方法,第一. 继承SqlSessionDaoSupport,重写获取SqlSessionFactory的方法.第二.继承 ...