Android 6.0后蓝牙的开发,搜索,配对,连接发送数据等(一)
2017-12-06 11:47
976 查看
最近在项目中需要使用蓝牙链接蓝牙打印机 , 所有对蓝牙的开发做了一下整理以供学习 .
**如果是小米手机请先手动在应用权限里打开定位权限, 下一篇博客告诉你原因和我踩过的坑**
首先在Android 6.0以后对手机权限做了修改 , 蓝牙的搜索需要需要在清单配置里面添加两个定位的权限:
蓝牙设备自己的权限
android里面蓝牙是通过BluetoothAdapter来进行操作的,首先我们需要获取到BluetoothAdapter的实例
在搜索之前,我们可以先获取与之前已经配对过的蓝牙设备
打开蓝牙的方式有三种:
关闭蓝牙
蓝牙的搜索
取消蓝牙搜索
我们要在代码里面注册这个广播接收器,在调用蓝牙的搜索方法,就能够进行蓝牙的搜索了
通过接收广播的形式来接收。所以我们应该自定义一个广播接收器,
这里需要注意的是,如果你的代码将运行在(Build.VERSION.SDK_INT >= 23)的设备上,那么务必加上以下权限,并在代码中动态的申请权限
蓝牙的配对,通过反射的形式来调用BluetoothDevice的createBondde()方法,我们要监听配对的过程,就可以在广播接收器再注册一个action。在上面的广播注册已给出代码
向已配对的设备发送数据
发送数据分为服务端和客户端,通过socket来进行消息的交互。
服务端:
客户端
可以看到无论是服务端还是客户端,都需要新起一个子线程来操作。那么服务端和客户端是怎么识别对方的呢,那么就需要用到UUID了,只有当服务端和客户端的UUID相同的时候才能够建立连接。
蓝牙开发demo下载 :demo下载
下一篇博客说说我在蓝牙发开时遇到的坑
**如果是小米手机请先手动在应用权限里打开定位权限, 下一篇博客告诉你原因和我踩过的坑**
首先在Android 6.0以后对手机权限做了修改 , 蓝牙的搜索需要需要在清单配置里面添加两个定位的权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
蓝牙设备自己的权限
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
android里面蓝牙是通过BluetoothAdapter来进行操作的,首先我们需要获取到BluetoothAdapter的实例
BluetoothAdapter blueToothAdapter = BluetoothAdapter.getDefaultAdapter();
在搜索之前,我们可以先获取与之前已经配对过的蓝牙设备
Set<BluetoothDevice> bondedDevices = blueToothAdapter.getBondedDevices();
打开蓝牙的方式有三种:
//第一种打开方式 blueToothAdapter.enable(); //第二种打开方式
//会以dialog的形式打开一个activity,并且如果我们通过startActivityForResult的形式的话 //还能查看蓝牙是否被打开,或者处理蓝牙被打开之后的操作 //如果是result_ok的话那么是打开,反之打开失败Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(intent, 1);//第三种打开方式
//第三种打开方式 设置本地设备可以被其它设备搜索,可被搜索的时间是有限的,最多为300s //效果和第二种类似Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(discoverableIntent);
关闭蓝牙
blueToothAdapter.disable();
蓝牙的搜索
blueToothAdapter.startDiscovery();
取消蓝牙搜索
blueToothAdapter.cancelDiscovery();
我们要在代码里面注册这个广播接收器,在调用蓝牙的搜索方法,就能够进行蓝牙的搜索了
//注册广播 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); //本地蓝牙适配器已经完成设备的搜寻过程。 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//动作状态发生了变化 intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); registerReceiver(bluetoothReceiver, intentFilter);
通过接收广播的形式来接收。所以我们应该自定义一个广播接收器,
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); showToast("找到新设备了"+device.getName()+"..."+device.getAddress()); boolean addFlag = true; for (BluetoothDevice bluetoothDevice : strArr) { if (device.getAddress().equals(bluetoothDevice.getAddress())) { addFlag = false; } } if (addFlag) { strArr.add(device); adapter.notifyDataSetChanged(); } } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (device.getBondState()) { case BluetoothDevice.BOND_NONE: Log.e(getPackageName(), "取消配对"); break; case BluetoothDevice.BOND_BONDING: Log.e(getPackageName(), "配对中"); break; case BluetoothDevice.BOND_BONDED: Log.e(getPackageName(), "配对成功"); break; } }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){ showToast("收搜结束"); }else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { showToast("收搜开始"); } } };
这里需要注意的是,如果你的代码将运行在(Build.VERSION.SDK_INT >= 23)的设备上,那么务必加上以下权限,并在代码中动态的申请权限
private void requestPermission() { if (Build.VERSION.SDK_INT >= 23) { //校验是否已具有模糊定位权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) //可读 != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) //可写 != PackageManager.PERMISSION_GRANTED ) { //申请ACCESS_FINE_LOCATION权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_PERMISSION_ACCESS_LOCATION); } else { //具有权限,开始收搜 search(); } } else { //系统不高于6.0直接执行 search(); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int b838 [] grantResults) { switch (requestCode) { case REQUEST_PERMISSION_ACCESS_LOCATION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { showToast("权限开启"); //开始收搜 search(); } else { showToast("没有定位权限,请先开启!"); } } } }
蓝牙的配对,通过反射的形式来调用BluetoothDevice的createBondde()方法,我们要监听配对的过程,就可以在广播接收器再注册一个action。在上面的广播注册已给出代码
try { Method method = BluetoothDevice.class.getMethod("createBond"); Log.e(getPackageName(), "开始配对"); method.invoke(strArr.get(i)); } catch (Exception e) { e.printStackTrace(); }
向已配对的设备发送数据
发送数据分为服务端和客户端,通过socket来进行消息的交互。
服务端:
new Thread(new Runnable() { @Override public void run() { InputStream is = null; try { BluetoothServerSocket serverSocket = blueToothAdapter.listenUsingRfcommWithServiceRecord("serverSocket", uuid); mHandler.sendEmptyMessage(startService); BluetoothSocket accept = serverSocket.accept(); is = accept.getInputStream(); byte[] bytes = new byte[1024]; int length = is.read(bytes); Message msg = new Message(); msg.what = getMessageOk; msg.obj = new String(bytes, 0, length); mHandler.sendMessage(msg); } catch (IOException e) { e.printStackTrace(); } } }).start();
客户端
new Thread(new Runnable() { @Override public void run() { OutputStream os = null; try { BluetoothSocket socket = strArr.get(i).createRfcommSocketToServiceRecord(uuid); socket.connect(); os = socket.getOutputStream(); os.write("testMessage".getBytes()); os.flush(); mHandler.sendEmptyMessage(sendOver); } catch (Exception e) { e.printStackTrace(); } } }).start();
可以看到无论是服务端还是客户端,都需要新起一个子线程来操作。那么服务端和客户端是怎么识别对方的呢,那么就需要用到UUID了,只有当服务端和客户端的UUID相同的时候才能够建立连接。
蓝牙开发demo下载 :demo下载
下一篇博客说说我在蓝牙发开时遇到的坑
相关文章推荐
- Android 6.0后蓝牙的开发,搜索,配对,连接发送数据等(二)
- Android 蓝牙开发之搜索、配对、连接、通信大全
- Android 蓝牙开发之搜索、配对、连接、通信大全
- Android 蓝牙开发之搜索、配对、连接、通信大全
- [置顶] Android 蓝牙开发之搜索、配对、连接、通信大全
- Android开发蓝牙篇之蓝牙配对、连接与接收数据
- Android 蓝牙设备通讯的开发(配对/连接/传输数据)
- 如何实现android蓝牙开发 自动配对连接,并不弹出提示框
- 如何实现android蓝牙开发 自动配对连接,并不弹出提示框
- android开发之蓝牙初步 扫描已配对蓝牙、更改蓝牙可见性、搜索外部蓝牙设备
- android开发之蓝牙主动配对连接手机
- android开发之蓝牙主动配对连接手机
- android 蓝牙搜索、配对连接通信总结
- 求教Android蓝牙串口开发OutputStream发送数据失败的问题。
- Android蓝牙搜索设备,向其发送数据并接收
- Android开发之蓝牙连接与配对设备
- android开发之蓝牙配对连接的方法
- android bluetooth——蓝牙的开启、搜索、配对与连接
- Android蓝牙设备的配对,连接,搜索
- android开发之蓝牙主动配对连接手机