Android蓝牙开发(一)---基础知识梳理

前言


在众多的消费电子类产品中,蓝牙作为一种简易的通讯方式,因此功耗小、体积小、成本低等优势,被广泛的应用于耳机、音箱、汽车及医疗器械等领域。作为一种即时技术,不需要特定的器械安装,固定的设施,而且得益于linux和Android的开源特性,被很多厂家所青睐。

此次分享摘自于项目中的蓝牙部分,主要用于实现蓝牙耳机的功能,包括电话、音乐、EQ、配对等操作。将分篇章对于android蓝牙的开发作介绍说明,并辅以代码、注释、通信协议等篇章,力求囊括android简易的开发流程。


一、Android的蓝牙系统


1. Android的蓝牙功能

Android包含了对蓝牙的协议支持,提供了访问蓝牙功能的API,因此可以很容易的实现:

1) 扫描并连接其他蓝牙设备;

2)查询本地的蓝牙适配器;

3)数据通信;

4)管理蓝牙连接;

2. Android蓝牙相关的类及权限

1)Bluetooth权限

//android的蓝牙开发首先需要在AndroidManifest.xml中开通以下权限

<uses-permission android:name="android.permission.BLUETOOTH"/>

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

2)BluetoothAdapter;

蓝牙适配器,在蓝牙Bluetoothsocket连接前,都需要不断的操作,通过此类用户可以执行基本的蓝牙操作,如初始化设备的搜索,查询,初始化一个BluetoothDevice类,创建一个BluetoothServerSocket类以监听其他设备对本机的连接请求等。

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();//建立本地适配器

startDiscovery();//开始远程设备的搜寻,注册ACTION_DISCOVERY_STARTED和ACTION_DISCOVERY_FINISHED,确认搜寻结果,返回值为true or false

cancelDiscovery();//取消当前的设备搜索进程,成功返回 true or false

disable();//关闭本地蓝牙适配器,异步调用的方法,用户通过监听ACTION_STATE_CHANGED的值来获取随后的适配器的状态,成功返回 true or false

enable();//打开本地蓝牙适配器,

//为实现友好的提示用户打开蓝牙,建议使用如下方法

Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(intent, 0x01);//0x01代表result_code,可以自行设定

getAddress();//返回本地蓝牙适配器的硬件地址,string,例:00:22:44:AA:CC:DD

getName();//获取本地蓝牙适配器的蓝牙名称,即可以在别的蓝牙设备上搜索到的名字

setName();//设置蓝牙或者本地蓝牙适配器的名称

getBondedDevices();//返回已经匹配(绑定)到本地蓝牙适配器的BluetoothDevice类的对象集合;

getRemoteDevice(String address);//根据蓝牙地址获取一个BluetoothDevice对象

checkBluetoothAddress(String address);//验证蓝牙地址是否有效,字母必须全部为大写,成功返回 true or false

listenUsingRfcommWithServiceRecord(String name, UUID uuid);//根据name,uuid创建一个正在监听的安全的带有服务记录的RFCOMM蓝牙端口,并返回一个BluetoothServerSocket

3)BluetoothServerSocket

蓝牙设备之间的连接,也可以理解为服务器端与客户端的连接,其通信的过程可以理解为拥有相同的RFCOMM通道下分别拥有一个连接的BluetoothSocket,然后通过read、write字节流的方法进行通信。在服务器端,使用BluetoothServerSocket类来创建一个监听服务端口,当调用accept接受连接,会返回一个新的BluetoothSocket进行管理该连接。

accept();//阻塞直到一个连接建立,返回值:已连接的BluetoothSocket,需要在新建立的线程中执行,避免阻塞,使用try ...catch语法,异常将抛出IOException

accept(int timeout);//阻塞直到超时时间内的连接建立,返回值:已连接的BluetoothSocket,需要在新建立的线程中执行,避免阻塞,使用try ...catch语法,异常将抛出IOException

close();//关闭端口,释放资源

4)BluetoothSocket;

客户端,使用一个单独的BluetoothSocket去初始化一个外接连接和管理该连接。

connect();//连接远程蓝牙设备,由于会造成线程阻塞,因此需要新建一个线程中执行此操作,使用try...catch语法,异常将抛出IOException

getInputStream();//通过连接的端口获得输入的数据流

BluetoothSocket socket = socket.getInputStream();

getOutputStream();//通过连接的端口获得输出的数据流

BluetoothSocket socket = socket.getOutputStream();

getRemoteDevice();//获得该端口正在连接或是已经连接的远程设备

5)BluetoothDevice;

通过蓝牙搜索可以搜索到BluetoothDevice类的对象集合。

createRfcommSocketToServiceRecord(UUID uuid);//创建并返回一个BluetoothSocket

//首先通过搜索到的device建立一个客户端的socket,然后通过connect()方法尝试连接服务器端

BluetoothSocket clientSocket = device.createRfcommSocketToServiceRecord(uuid);

clientSocket.connect();

以上5个知识点是蓝牙开发中最常用的基础知识,此外还包括蓝牙搜索设备广播的建立。

//采用动态方法建立广播,根据需要可以在onCreate()或者在onResume()方法中注册广播

private BroadcastReceiver receiver;

@Override

public void onResume() {

super.onResume();

receiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context,Intent intent) {

String action = intent.getAction();

switch(action)

{

case BluetoothDevice.ACTION_FOUND:

device = intent.getParcelableExtra(BluetoothDevice.EXTRA_NAME);

mlist.add(device);

break;

case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:

case BluetoothAdapter.ACTION_DISCOVERY_STARTED:

break;

}

}

};

filter = newIntentFilter();

filter.addAction(BluetoothDevice.ACTION_FOUND);

filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

//注册蓝牙搜索结果的receiver

mActivity.registerReceiver(receiver,filter);//加上mActivity是因为项目中为fragment与Activity进行交互,如果单纯只是为了测试或者没有fragment,也可以不用加mActivity

}

需要注意的是在使用结束后,需要在onDestroy()中注销此receiver。

3. Android蓝牙中的一些常用知识及使用


3.1 RFCOMM

作为最常用的蓝牙端口,是一个面向连接,通过蓝牙模块进行的数据流传输方式,也可称为SPP(Serial Port Profile,串行端口规范)。作为蓝牙客户端与服务器端的socket通道,在设备连接后,仅仅是bondedDevice,还没有建立通信通道。因此需要在不同的设备的应用程序间建立一个可以通信的路径。

3.2 UUID

Universally Unique Identifier,通用识别码,其目的是让分布式系统中的所有元素,都能有唯一的识别资讯,从而不再需要透过中央控制端来辨别资讯的指定。因此,每个人都可以建立与其他人不冲突的UUID来进行沟通,数据的传输,也不需要在考虑数据库建立时的名字重复问题。理论上只要两台设备的UUID一致,即可建立socket。

String ble_uuid = “00000001-0000-1000-8000-00805F9B34AB”;

UUID uuid = UUID.fromString(ble_uuid);

System.out.println("UUID is " + uuid);

3.3 A2DP

之所以提到A2DP,是因为项目中主要是用来实现蓝牙耳机的功能(包括音频、免提电话、播放音乐、设定EQ等)。A2DPProfile定义了高质量音频数据传输的协议和过程,包括立体声和单声道数据的传输。这里的高质量音频指的是单声道(Mono)和立体声(Sterco)的音频,主要区别于蓝牙SCO链路上传输的普通语音。A2DP的典型应用是将音乐播放器的音频数据发送到耳机或音箱。而目前的A2DP值定义了点对点的音频传输。


二、蓝牙开发规划


此次蓝牙开发流程,包括对于基础知识的梳理,通信协议的介绍和撰写说明,蓝牙搜索界面,相关类的封装,通信过程的开发及代码讲解,会根据笔记的撰写进行不同程序的完善和改变。

以上知识梳理部分,如有错误还请各位大神指出,谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容