[Android] Android 操作 Bluetooth(一)——蓝牙2.3等

[TOC]

0x00 蓝牙(Bluetooth)

这个小硬件已经是 android 机器的标配了,由于平时不怎么用,因此到现在都没有去研究过。现在有一个简单的小需求:通过蓝牙连接一个串口设备读取其上面的数据,遂写此文。

最终效果:从已配对的设备列表中选择我们的串口蓝牙设备(从),连接,然后读取数据。

0x01 简单使用

蓝牙设备的详细使用,可以参考Android关于蓝牙的官方文档。如果你和我一样,之前没有研究过蓝牙,估计看到最后也会有一堆问题存在:什么主设备、从设备、UUID是干嘛的,如何免密要配对等等。不着急,我们慢慢来。

上面已经说到,我们的设备已经提前配对完成(怎么配对:网络设置中中找到蓝牙,然后搜索,找到你的设备,然后配对。这个时候可能会提示输入密码,默认密码比如0000,1234等)。我们只需要连接即可。下面简述操作步骤:

  1. 添加蓝牙权限

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    
  2. 判断是否支持蓝牙

    private void initBluetooth() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (null == mBluetoothAdapter) {
            tvContent.setText("BluetoothAdapter is null");
            return;
        }
        if (!mBluetoothAdapter.isEnabled()) {
            tvContent.setText("BluetoothAdapter is disable, please open it");
    
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_ENABLE_BT);
        }
    
        tvContent.setText("Bluetooth init success");
    }
    

    首先是判断是否有蓝牙适配器,如果没有,BluetoothAdapter.getDefaultAdapter() 返回 null。然后判断蓝牙设备是否启用 mBluetoothAdapter.isEnabled() ,如果未启用,则发送一个 Intent 来让用户启用蓝牙,这个 Intent 是系统的,我们在 onActivityResult 中处理用户操作结果,如果用户顺利开启蓝牙,则会返回 RESULT_OK

  3. 获取设备列表

    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
    if (null != pairedDevices && pairedDevices.size() > 0) {
      for (BluetoothDevice device : pairedDevices) {
          ......
          String msg = String.format("%s %s\n", device.getName(), device.getAddress());
          ......
      }
    }
    

    这个时候我们可以拿到 BluetoothDevice ,这个对象中保存了已配对蓝牙设备的信息,比如名称,MAC地址,状态,UUID等信息,我们需要保存下来,在接下来的连接时候会使用。

  4. 连接设备

    有了 BluetoothDevice 信息,我们就可以连接这个已经配对的蓝牙设备了。

    public static final UUID DEFAULT_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
    
    try {
       if(null == mSocket){
           mSocket = mDevice.createRfcommSocketToServiceRecord(DEFAULT_UUID);
       }
       mSocket.connect(); // 阻塞的
    
       mIn = mSocket.getInputStream();
    } catch (IOException e) {
       e.printStackTrace();
       return false;
    }
    

    连接成功后,我们会得到一个 BluetoothSocket 对象,然后调用其阻塞的 connect() 方法,等待两台设备连接成功(所以这个时候必须在另外一个线程中进行)。当两台设备连接成功之后会继续向下执行。

  5. 读取数据

    连接成功之后,我们可以通过 mSocket.getInputStream() 获得一个输入流,结下来的操作就是流的操作了,这个和普通 socket 中输入输出流的操作一样了。

    try {
       mBytes = mIn.read(readBuffer);
       System.arraycopy(readBuffer, 0, tempBuffer, mCount, mBytes);
       mCount += mBytes;
       if (mCount >= SIZE) {
           parseData(tempBuffer);
           mCount = 0;
       }
    } catch (IOException e) {
       e.printStackTrace();
    }
    

0x02 总结

Android蓝牙(主从)的操作:

  • 检查是否支持,是否启用(包括是否可见等)
  • 扫描设备
  • 配对
  • 连接
  • 数据交换
  • 等等

这里只讲了检查部分操作,涉及的扫描与配对可能是更复杂一些的,在接下来讲述。

最后,项目代码可参考这里github/ttdevs/air

0x03 简单分享一个java线程的封装:

/**
 * Created by ttdevs
 * 2017-01-22 (android)
 * https://github.com/ttdevs
 */
public abstract class BaseWorkerThread extends Thread {

    private boolean isRunning = true;

    @Override
    public void run() {
        super.run();
        isRunning = workerBefore();

        while (isRunning) {
            workerCycle();
        }

        workerAfter();
    }

    /**
     * 提前执行 true: 继续 false: 结束
     *
     * @return
     */
    public boolean workerBefore() {
        return true;
    }

    /**
     * 工作方法,被循环调用
     *
     * @return true: 继续 false: 结束
     */
    public abstract void workerCycle();


    /**
     * 结束执行
     */
    public void workerAfter() {

    }

    /**
     * 开始线程
     */
    public void startThread() {
        isRunning = true;
        try {
            start();
        } catch (Exception e) {
            e.printStackTrace();
            isRunning = false;
        }
    }

    /**
     * 结束线程
     */
    public void stopThread() {
        isRunning = false;
    }
}

参考

https://developer.android.google.cn/guide/topics/connectivity/bluetooth.html

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

推荐阅读更多精彩内容