1.前言
应学校课程要求学习传统蓝牙和手机app之间通信,实现的最终结果为:传统蓝牙模块通过串口实现和手机app之间的消息互发
2.开发环境
华为p20(android 8.1) AndroidStudio 3.2
经过测试发现有的手机搜索蓝牙设备需要开启location权限,在华为上我的手机没有开启也可以进行搜索,另外还需要动态的允许权限
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED||ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.ACCESS_COARSE_LOCATION)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION},1);
}
3.搜索设备
在搜索设备之前首先先判断自己的手机是否是支持蓝牙的,其次有没有打开蓝牙,最后再搜索设备
BluetoothAdapter 蓝牙适配器 代表移动设备的本地的蓝牙适配器
BluetoothDevice 代表远程的一个蓝牙设备
BluetoothSocket 代表蓝牙的一个socket接口,是一个连接点,用于连接设备通过inputstream和outputsream通信
adapter=BluetoothAdapter.getDefaultAdapter();//获取本地蓝牙设备
if(adapter!=null){
if(!adapter.isEnabled()){ //判断是否开启了蓝牙,如何未开启执行开启操作
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
}
}else{
//不支持蓝牙
}
因为搜索蓝牙是通过广播的形式,手机向周围设备发送广播,app中编写广播过滤器,接着对接收到的广播(返回为BluetoothDevice)进行进行处理,如加入到ListView中用于显示所有搜到的设备
IntentFilter intentFilter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
final BroadcastReceiver broadcastReceiver=new BluetoothReceiver();
registerReceiver(broadcastReceiver,intentFilter);//注册过滤器
public class BluetoothReceiver extends 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);
if (device != null) {
//此处可以执行加入List中操作
}
}
}
}
当前面的操作都设置好了,之后就可以开始搜索设备啦,记得刚才获取到的本地adapter吗,只要用他就可以了,调用后,就会在广播接收器里面收到device了
adapter.startDiscovery();
当你点击不需要搜索之后记得关闭搜索哦
adapter.cancelDiscovery()
4.配对设备
当获取到很多设备之后你可能显示在ListView中了,当你点击其中一个之后,接着编写配对的代码,想要配对她,那必须获取到他的BluetoothDevice对把,如何你List存的是BluetoothDevice,那就可以直接进行连接,如何存的是Mac地址,那就再用过Mac地址获取到BluetoothDevice,总之你得获取到她的BluetoothDevice
//通过mac地址获取Device
//device=adapter.getRemoteDevice(address);
Method method=BluetoothDevice.class.getMethod("createBond");
method.invoke(device);
5.连接设备
配对成功后通过指定串口通信的UUID和设备进行socket连接
private static final UUID My_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothSocket socket=device.createRfcommSocketToServiceRecord(My_UUID);
socket.connect();
6.接收数据
连接成功后即可通过socket对象获取inputstream和outputstream,接收数据可以通过inputstream对象读取蓝牙从串口发送过来的信息,接收数据需要开启一个线程不断的监听数据的获取
class ReceiveThread extends Thread{
String buffer="";
@Override
public void run() {
while(socket!=null ){
//定义一个存储空间buff
byte[] buff=new byte[2048];
try {
inputStream = socket.getInputStream();
inputStream.read(buff); //读取数据存储在buff数组中
processBuffer(buff,2048);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void processBuffer(byte[] buff,int size){
int length=0;
for(int i=0;i<size;i++){
if(buff[i]>'\0'){
length++;
}
else{
break;
}
}
byte[] newbuff=new byte[length]; //newbuff字节数组,用于存放真正接收到的数据
for(int j=0;j<length;j++){
newbuff[j]=buff[j];
}
//此处可对newbuff数据进行操作,如显示在界面上
}
}
7.发送数据
发送数据这里是写了一个异步的类,主要就是一句话,先通过socket获取到outputstream,然后再往里面写入数据就行了,必须是byte类型的
class SendInfoTask extends AsyncTask<String,String,String> {
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
@Override
protected String doInBackground(String... arg0) {
if (arg0[0].length() > 0)//不是空白串
{
byte[] msgBuffer = arg0[0].getBytes();
try {
// 将msgBuffer中的数据写到outStream对象中
outputStream.write(msgBuffer);
} catch (IOException e) {
}
}
}
}