美文网首页智能家居Android项目经验分享Android技术知识
Android蓝牙开发(一)---基础知识梳理

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

作者: 心若冰清_ | 来源:发表于2017-06-07 16:26 被阅读455次

    前言


    在众多的消费电子类产品中,蓝牙作为一种简易的通讯方式,因此功耗小、体积小、成本低等优势,被广泛的应用于耳机、音箱、汽车及医疗器械等领域。作为一种即时技术,不需要特定的器械安装,固定的设施,而且得益于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值定义了点对点的音频传输。


    二、蓝牙开发规划


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

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

    相关文章

      网友评论

        本文标题:Android蓝牙开发(一)---基础知识梳理

        本文链接:https://www.haomeiwen.com/subject/wsqifxtx.html