首先在此引用一下百度百科里关于蓝牙的定义:

蓝牙技术是一种无线数据和语音通信开放的全球规范,它是基于低成本的近距离无线连接,为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。
《来自百度百科》

使用android原生开放的api来开发蓝牙应用,简单的可以总结为以下三步:

  • 打开蓝牙开关,让设备处于扫描模式,扫描附近可用的其它蓝牙设备。
  • 与找到的某一蓝牙建立连接关系。
  • 通过socket套接字与流操作交换数据,或者使用设备已支持的蓝牙协议来获取数据。

以上三个步骤就是常见的android蓝牙开发过程,在android车载方向开发中,车机一般作为蓝牙连接中的从端设备,手机作为对应的主端设备,两者之间按照一致对应的蓝牙协议来交互,以下是android车载方向常见的蓝牙协议:

  • Hfp (Hands-Free profile):免提通话协议,常用于和手机之间的蓝牙通话,通过该协议可以控制主机拨打电话
  • A2dp (Advanced Audio Distribution Profile):高质量音频传输协议,用于蓝牙音乐,基于该协议可以获取主机传输过来的音频流数据
  • Avrcp (Audio/Video Remote Control Profile):音频/视频远程控制协议,基于该协议可以让从端控制主端的媒体上下曲,播放暂停等功能
  • MAP (Message Access Profile):信息访问协议,基于该协议可以获取主机上的信息,电子邮件,类似读取手机短信
  • Pbap (Phone Book Access Profile):电话本访问协议,基于该协议可以获取主机上的通讯录跟通话记录

从端开发过程

在日常开发过程中,车机端一般作为从端来开发蓝牙应用,而手机端则作为蓝牙主端,android原生已经封装支持了常见的主从协议功能交互接口以便开发者调用。以下以Pbap协议为例,介绍车机端蓝牙应用的常用类以及使用过程,其它协议过程类似:

  1. 定义蓝牙功能权限

开发设计蓝牙相关功能的,需要在AndroidManifest.xml清单文件中定义好权限:

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

如果应用不是系统级应用,还需要在代码中配置某些权限的动态申请,比如:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_CODE){if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "权限开启成功", Toast.LENGTH_LONG).show();} else {Toast.makeText(this, "权限开启失败", Toast.LENGTH_LONG).show();}}
}
  1. 扫描附近蓝牙设备

在定义好相关的蓝牙开发权限后,接下从使用BluetoothAdapter 类进行蓝牙交互开始,BluetoothAdapter 类是任何跟蓝牙相关交互都会先涉及到的操作类,用来打开/关闭设备蓝牙开关;扫描附近蓝牙设备,获取已经配对过的设备列表。

要先连接到其它蓝牙设备,首先需要打开当前设备的蓝牙开关:

//获取蓝牙适配器
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//打开蓝牙
bluetoothAdapter.enable();

在扫描其他设备前,需要先注册一个监听蓝牙开关状态BluetoothAdapter.ACTION_STATE_CHANGED 的广播,确保当前蓝牙状态处于已开启状态再去调用startDiscovery(),扫描过程中,系统也会发出扫描开始BluetoothAdapter.ACTION_DISCOVERY_STARTED跟扫描结束BluetoothAdapter.ACTION_DISCOVERY_FINISHED两个广播。一旦扫描到附近的蓝牙设备,只需监听BluetoothAdapter.ACTION_FOUND广播并获取设备信息即可:

public void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case BluetoothAdapter.ACTION_STATE_CHANGED:int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);if(state = 1){//开启扫描bluetoothAdapter.startDiscovery();}break;...case BluetoothDevice.ACTION_FOUND://发现设备BluetoothDevice foundDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);break;}
}
  1. 连接已扫描到的设备

BluetoothDevice即蓝牙设备类,通过此类获取对应蓝牙设备的信息,例如名称/地址/连接状态。为了连接到蓝牙设备并进行相关操作,则需要通过特定的BluetoothProfile协议类来发起连接,例如:

  • 通过BluetoothA2dpSink协议代理类连接设备,获取主端设备的音频流
  • 通过BluetoothHeadsetClient协议代理类连接设备,控制主端设备拨打电话
  • 通过BluetoothAvrcpController协议代理类连接设备,控制主端音乐播放器上下曲
  • 通过BluetoothPbapClient协议代理类连接设备,获取主端上的通讯录/通话记录数据
  • 通过BluetoothMapClient协议代理类连接设备,控制主端发送信息,以及获取主端上的信息数据

获取上述几个代理类的方式都差不多,即通过BluetoothAdapter类的 getProfileProxy()方法:

public boolean getProfileProxy(Context context,
BluetoothProfile.ServiceListener listener,int profile);

第一个参数为当前上下文,第二个参数是协议的连接监听,第三个参数为需要连接的协议在BluetoothProfile 类当中的对应整型值,成功连接上的蓝牙协议代理类会通过第二个参数 BluetoothProfile.ServiceListeneronServiceConnected()方法回调,回调方法的第二个参数 bluetoothProfile 就是本次连接上的蓝牙协议。

BluetoothProfile.ServiceListener serviceListener = new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceConnected(int profile, BluetoothProfile bluetoothProfile) {switch (profile) {case BluetoothProfile.HEADSET_CLIENT://初始化代理类mHeadsetClient = (BluetoothHeadsetClient) bluetoothProfile;break;case BluetoothProfile.A2DP_SINK:mA2dpSink = (BluetoothA2dpSink) bluetoothProfile;break;case BluetoothProfile.PBAP_CLIENT:mPbapClient = (BluetoothPbapClient) break;}}
};//发起服务连接请求
bluetoothAdapter.getProfileProxy(context, serviceListener, BluetoothProfile.PBAP_CLIENT);
bluetoothAdapter.getProfileProxy(context, serviceListener, BluetoothProfile.A2DP_SINK);
bluetoothAdapter.getProfileProxy(context, serviceListener, BluetoothProfile.HEADSET_CLIENT);

如果要获取主机端的通讯录数据,就需要用到BluetoothPbapClient协议代理类,在初始化了BluetoothPbapClient之后,就可以向已扫描到的设备发起连接请求了,直接调用BluetoothPbapClientconnect(BluetoothDevice device)方法:

mPbapClient.connect(device);

接着为了关注对应设备的连接情况,需要监听相关的广播,每个协议都有对应的连接状态变化广播,像BluetoothPbapClient协议的设备连接状态变化广播action值为BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED,而BluetoothA2dpSink协议的action值是BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED,监听各自协议的设备连接状态变化广播,便可知道何时设备断开或连上哪些协议:

public void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED:{int prevState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);int nowstate = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);                    BluetoothDevice pbapDevice =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if(prevState != BluetoothProfile.STATE_CONNECTED && nowstate == BluetoothProfile.STATE_CONNECTED){//已连接                        }else if(prevState != BluetoothProfile.STATE_DISCONNECTED && nowstate == BluetoothProfile.STATE_DISCONNECTED) {//已断开                        }break;}case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED:{//同上break;}}
}

在连接上设备后,便可以调用协议代理类中的其它方法来与主端蓝牙设备交互,例如BluetoothHeadsetClientdial(BluetoothDevice device, String number)方法来拨打电话等。

以上就是本次博客的内容,感谢阅读!

android蓝牙开发基础知识讲解,常见bluetooth蓝牙开发步骤相关推荐

  1. java nio ppt_Java开发基础知识讲解.ppt

    Java开发基础;?目录第1章 Java体系结构;Java体系结构Java体系结;Java体系结构(续);?目录第1章 Java体系结构;大纲数据类型变量运算符字符串注;数据类型数据类型整型浮点型ch ...

  2. 蓝牙技术基础知识总结笔记1 - 蓝牙版本及 4.0 和 BLE 的关系等

    1.蓝牙技术的起源 蓝牙的创始人是瑞典爱立信公司. 爱立信早在 1994 年就已进行研发. 1997 年,爱立信与其他设备生产商联系,并激发了他们对该项技术的浓厚兴趣. 1998 年 2 月,5 个跨 ...

  3. 蓝牙模块基础知识介绍

    蓝牙模块基础知识介绍 随着近年来蓝牙技术的不断发展,在功耗不断降低的情形下,蓝牙的传输速率也不断地得到提高,使蓝牙的应用范围更加广泛.但若想设计一套完善的蓝牙系统,就必须充分掌握蓝牙的相关技术知识,如 ...

  4. iPad开发基础知识

    转载自:http://www.cocoachina.com/bbs/simple/?t82559.html iPad开发基础知识 iPad平板电脑程序开发基础规则 苹果在今天凌晨发布了10寸平板电脑: ...

  5. IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

    1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动端IM)的数据流交换方式都是Http短连接+TCP或UDP长连接来实现.Http短连接主要用于从服务器读取各种持久化信息 ...

  6. IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理

    1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以"人"为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是 ...

  7. AndroidStudio 开发基础知识【翻译完成】

    协议:CC BY-NC-SA 4.0 尔曹身与名俱灭,不废江河万古流.--杜甫<戏为六绝句·其二> 在线阅读 在线阅读(Gitee) ApacheCN 学习资源 目录 AndroidStu ...

  8. 新手上路:ADAMS 基础知识讲解(图文并茂)【转载仿真论坛】

    引用 Baker 的 新手上路:ADAMS 基础知识讲解(图文并茂)[转载仿真论坛] 经过不知道多少个日夜,终于出来一个雏形了,内容主要是版内的帖子总结,这个为1.0版本,由于时间的问题,内容还不全, ...

  9. iOS开发基础知识--碎片44

    iOS开发基础知识--碎片44  iOS开发基础知识--碎片44 1:App跳转至系统Settings 跳转在IOS8以上跟以下是有区别的,如果是IOS8以上可以如下设置: NSURL *url = ...

  10. IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

    1.引言 消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一. 消息从发送者到接收者的典型传递方式有两种: 1)一种我 ...

最新文章

  1. 对标SpaceX?B站也要发卫星了!
  2. UITableView优化
  3. 栈与队列基本操作及其应用
  4. Android UI开发第二篇——多级列表(ExpandableListView)
  5. 阮一峰react demo代码研究的学习笔记 - demo4 debug - create element and Render
  6. php 405跳转,php – 返回HTTP 405的CORS预检请求
  7. #define和const的区别
  8. C++经典面试题汇总
  9. 将视图转为image_JavaScript二进制数组(2)TypedArray视图
  10. thinkphp生成php文件,thinkphp使用buildHtml生成静态文件的方法
  11. Python教程(从不懂到入门)
  12. 质心公式_No.217 质心位置的求法(基础篇)
  13. android开机logo制作
  14. chrome transition闪烁BUG 阿星小栈
  15. ZBrush - 动物毛发制作及渲染
  16. python调用多级目录中的文件_python复制多层目录下的文件至其他盘符对应的目录中...
  17. ==||FM数日...进行中
  18. icq蓝牙_使用WhizBase发送ICQ消息
  19. ipfs 云服务器_安丘ipfs服务器,ipfs云算力组装
  20. 企业cio(首席信息官)的职责

热门文章

  1. toefl备考2.20
  2. MySQL综合应用二:事务机制二:四种隔离级别:【READ UNCOMMITTED】、【READ COMMITTED】、【REPEATABLE READ】、【SERIALIZABLE】;
  3. jenkins Included Regions 监控svn下指定某个目录改动,触发自动构建
  4. 学习blender(B站)
  5. postgresql和Oracle中几种循环结构示例
  6. 用Python做图书管理系统
  7. 控制反转--依赖注入
  8. 数学之路不顺?别放弃,数据分析和人工智能的大门还为你敞开
  9. NC:上百个菌根真菌基因组
  10. PMP 验收和核实区别(Validation Versus Verification)