Android实践 -- Android蓝牙设置连接

蓝牙开发相关

使用Android Bluetooth APIs将设备通过蓝牙连接并通信,设置蓝牙,查找蓝牙设备,配对蓝牙设备
连接并传输数据,以下是Android系统提供的蓝牙相关的类和接口

  • BluetoothAdapter
  • BluetoothDevice
  • BluetoothSocket
  • BluetoothServerSocket
  • BluetoothClass
  • BluetoothProfile
  • BluetoothHeadset
  • BluetoothA2dp
  • BluetoothHealth
  • BluetoothHealthCallback
  • BluetoothHealthAppConfiguration
  • BluetoothProfile.ServiceListener

蓝牙权限

使用蓝牙功能,需要在AndroidManifest.xml中声明蓝牙相关的权限

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

建立蓝牙

  • 初始化连接

在通过蓝牙通信之前,需要先确定设备是否支持蓝牙功能,先初始化一个BluetoothAdapter的实例,
BluetoothAdapter提供了一个静态方法getDefaultAdapter()来获得BluetoothAdapter的实例

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
    // 设备不支持蓝牙功能
}
  • 打开蓝牙
    下一步就是打开蓝牙,调用isEnabled()方法检查蓝牙功能是否已经打开,返回true说明蓝牙已开启,
    返回false说明蓝牙功能未开启,开启蓝牙可以通过发送广播ACTION_REQUEST_ENABLE,也可以通过方法
    enable()直接打开,这两种方法都会有蓝牙权限的提示,选择允许,否则无法打开蓝牙
if (!mBluetoothAdapter.isEnabled()) {
  Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
  startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
mBluetoothAdapter.enable();

在应用中可以设置蓝牙的状态的监听ACTION_STATE_CHANGED广播,当蓝牙的状态的变化时,就会触发这个
广播,接收到这个广播之后,在intent中可以获得当前蓝牙的状态和前一次的蓝牙的状态

int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);

蓝牙的状态值有:

int STATE_OFF = 10;//蓝牙关闭状态
int STATE_TURNING_ON = 11;//蓝牙正在打开
int STATE_ON = 12;//蓝牙打开状态
int STATE_TURNING_OFF = 13;//蓝牙正在关闭

查找蓝牙设备

打开蓝牙之后,下一步就是查找可以使用的蓝牙设备,蓝牙的api中也提供了相关的接口,由于蓝牙的扫描
是一个耗电的操作,不用时计时取消扫描蓝牙

mBluetoothAdapter.isDiscovering(); //监测蓝牙是否正在扫描
mBluetoothAdapter.startDiscovery();//开始扫描
mBluetoothAdapter.cancelDiscovery();//取消扫描

为了发现可用的蓝牙的设备,必须在应用中注册ACTION_FOUND的广播,调用方法startDiscovery()如果查找到可用的
设备会触发这个广播,这个广播中带有EXTRA_DEVICE的设备信息可以通过下面的方法获得设备的信息

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Log.e("tag","device name: "+device.getName()+" address: "+device.getAddress());
        }
    }
};
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
  • 查询已经配对的设备列表
    在进行查找之前,可以先获得之前已经配对成功的蓝牙设备的列表,可以调用方法getBondedDevices()获得
    已经配对的蓝牙设备列表
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
  for (BluetoothDevice device : pairedDevices) {
      //可以获得已经配对的蓝牙的名称和地址
      Log.e("tag","device name: "+device.getName()+" address: "+device.getAddress());
  }
}
  • 是其他设备可见
    上面讲的都是发现其他的蓝牙设备,也可以设置设备本身是否对其他设备可见,通过发送ACTION_REQUEST_DISCOVERABLE
    的广播,会调用系统的方法,还可以设置多长时间内是可见的,在intent中设置EXTRA_DISCOVERABLE_DURATION,最大值是
    3600s,超过3600s会设置为120s,点击允许会回调onActivityResult()方法
//设置设备在300s内是可见的
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

如果没有打开蓝牙,执行上面的操作会自动打开蓝牙

可以通过监听ACTION_SCAN_MODE_CHANGED广播,可以在intent中根据EXTRA_SCAN_MODE的参数获得当前设备的SCAN MODE
有一些几种模式

int SCAN_MODE_NONE = 20;//这个模式不能被发现也不能连接
int SCAN_MODE_CONNECTABLE = 21;//这个模式不能被扫描到,但是可以连接
int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;//这个模式可以被发现,也能被连接

蓝牙的连接

  • Server 端
    通过BluetoothAdapterlistenUsingRfcommWithServiceRecord(String, UUID)方法获得BluetoothServerSocket对象
    的实例,然后socket就会通过accept()监听客户端的连接的状态
private class AcceptThread extends Thread {
    private final BluetoothServerSocket mmServerSocket;
    public AcceptThread() {
        BluetoothServerSocket tmp = null;
        try {
            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
        } catch (IOException e) { }
        mmServerSocket = tmp;
    }

    public void run() {
        BluetoothSocket socket = null;
        // 在后台一直监听客户端的请求
        while (true) {
            try {
                socket = mmServerSocket.accept();
            } catch (IOException e) {
                break;
            }
            if (socket != null) {
                mmServerSocket.close();
                break;
            }
        }
    }
    public void cancel() {
        try {
            mmServerSocket.close();
        } catch (IOException e) { }
    }
}
  • Client 端
    使用BluetoothDevicecreateRfcommSocketToServiceRecord(UUID)方法获得BluetoothSocket对象的实例
    然后调用connect()方法,这时server端会监听到这个请求,之后就建立连接,然后就可以进行通信了
private class ConnectThread extends Thread {
  private final BluetoothSocket mmSocket;
  private final BluetoothDevice mmDevice;
  public ConnectThread(BluetoothDevice device) {
      BluetoothSocket tmp = null;
      mmDevice = device;
      try {
          tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
      } catch (IOException e) { }
      mmSocket = tmp;
  }

  public void run() {
      mBluetoothAdapter.cancelDiscovery();

      try {
          mmSocket.connect();
      } catch (IOException connectException) {
          try {
              mmSocket.close();
          } catch (IOException closeException) { }
          return;
      }
  }
  public void cancel() {
      try {
          mmSocket.close();
      } catch (IOException e) { }
  }
}

连接的监听

可以通过注册广播监听蓝牙设备连接的状态变化,广播BluetoothDevice.ACTION_BOND_STATE_CHANGED,监听到这个广播之后,可以
在intent中获得连接的状态

int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);

设备连接的状态值

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

推荐阅读更多精彩内容