Android蓝牙通信

这里跟大家分享一下 最近蓝牙中遇见的一些问题 以及蓝牙工作顺序 文章中有写的不好的欢迎大神吐槽 需要源码可以私 我么一起学习

 

蓝牙共分为扫描,配对,连接,通信 当然在扫描之前要做一些操作 判断是否支持蓝牙 以及蓝牙是否已开启 如果没有开启的话可以通过蓝牙适配器去打开

 

  • 1.创建蓝牙适配器

BluetoothAdapter mBluetoothAdapter =BluetoothAdapter.getDefaultAdapter();

蓝牙适配器是蓝牙的核心 Android中所有的蓝牙操作都在此适配器中 我们可以通过他去进行通信

 

  • 2.执行扫描前的预备工作

通过判断 mBluetoothAdapter是否为空可以得到本机是否支持蓝牙

mBluetoothAdapter.isEnabled(); 蓝牙是否打开

  • 3.当把所有的准备工作做完之后可以开始扫描(根据不同的需求计划)

扫描一般是通过广播去进行接收扫描到的结果的,可以如下设置

ScanBlueReceiver scanBlueReceiver = new ScanBlueReceiver(new ScanBlueCallBack());

IntentFilter filter1 = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

IntentFilter filter2 = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

IntentFilter filter3 = new IntentFilter(BluetoothDevice.ACTION_FOUND);

registerReceiver(scanBlueReceiver, filter1);

registerReceiver(scanBlueReceiver, filter2);

registerReceiver(scanBlueReceiver, filter3);

这样我们通过就广播监听了扫描结果 只需要在我们需求的点击事件或者合适的地方开启蓝牙扫描即可(扫描是异步操作 时间会长一些12s左右)

mBluetoothAdapter.startDiscovery();

 

4.扫描结束后下一步应该就要进行配对了 要注意的是配对的时候需要连接上蓝牙(之前有个问题卡了很久 每次都可以配对上 但是连不上)通过广播回调的BluetoothDevice也并没有发现连接与未连接之前有什么方法 广播的华主要监听一下(回调里面的方法pin是配对 如果没有我下面说出的问题可以不用管)

 

//创建广播 注册 配对请求和一个状态发生改变的广播

//配对接收

PinBlueReceiver pinBlueReceiver = new PinBlueReceiver(new PinBlueCallBack() {

@Override

public void onBondRequest() {

Log.d(TAG,"onBondRequest...");

}

@Override

public void onBondFail(BluetoothDevice device) {

pin(cnt ); }

@Override

public void onBonding(BluetoothDevice device) {}

@Override

public void onBondSuccess(BluetoothDevice device) {}

});

IntentFilter filter4 = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);

IntentFilter filter5 = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

registerReceiver(pinBlueReceiver, filter4);

registerReceiver(pinBlueReceiver, filter5);

 

//创建好广播 然后通过反射去配对

if (device.getBondState() == BluetoothDevice.BOND_NONE) {

try {

Method createBondMethod = device.getClass().getMethod("createBond");

Boolean returnValue = (Boolean) createBondMethod.invoke(device);

returnValue.booleanValue();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

Log.e(TAG, "attemp to bond fail!"); }

}

 

//到这里基本上就配对好了 但是到这里我在调试的时候会经常性的只配对不连接,这个问题卡了好久 通过返回的BluetoothDevice也没有找到什么方法 后来还是通过广播监听蓝牙的连接 断开连接 和发生变化(所以加上一个广播 直接onresume调用就行)

IntentFilter stateChangeFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);

IntentFilter connectedFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);

IntentFilter disConnectedFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);

registerReceiver(stateChangeReceiver, stateChangeFilter);

registerReceiver(stateChangeReceiver, connectedFilter);

registerReceiver(stateChangeReceiver, disConnectedFilter);

 

我们可以在这个广播中进行做出相应的处理

//连接状态广播接受者

private BroadcastReceiver stateChangeReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (BluetoothDevice.ACTION_ACL_CONNECTED == action) {

Log.d(TAG,action+"...ACTION_ACL_CONNECTED");

//已连接

}

if (BluetoothDevice.ACTION_ACL_DISCONNECTED == action) {

Log.d(TAG,action+"...ACTION_ACL_DISCONNECTED");

//断开

unpairDevice(cnt);//取消配对

}

if (BluetoothAdapter.ACTION_STATE_CHANGED == action) {

Log.d(TAG,action+"...ACTION_STATE_CHANGED");

//发生变化

unpairDevice(cnt); //取消配对

}

}

};

 

在这里把这个取消配对的给贴上 主要说一下什么时候取消配对。 蓝牙在连接的时候会经常性的支配对不连接 不管连接没连上没有什么状态改变

如果你在配对时加了配对上上就取消配对逻辑的话 第二次配对可能就配对不上 调试的时候也麻烦

首先说这个配对的广播他基本都是会走成功方法的(有无连接都是)如果是无连接情况就需要取消配对然后重新配对 在连接状态广播中也要去进行合适的取消配对和配对 总之没连上就取消让它不停的去连接只能连接上为止

//取消配对

private void unpairDevice(BluetoothDevice device) {

try {

Method m = device.getClass().getMethod("removeBond", (Class[]) null);

m.setAccessible(true);

m.invoke(device, (Object[]) null);

pin(cnt);

} catch (Exception e) {

Log.e("ble",e.toString());

}

}

 

  • 5.配对完之后应该是连接(spp) 这里就是打开spp的操作 这一步有很多报(java.io.IOException: read failed, socket might closed or timeout, read ret: -1) 可以换个uuid试试(00001101-0000-1000-8000-00805F9B34FB)

 

//连接之前把扫描关闭

if (mBluetoothAdapter.isDiscovering()) {

mBluetoothAdapter.cancelDiscovery();

}

连接需要通过一个BluetoothDevice对象 然后创建socket。socket去绑定上uuid然后和服务器进行连接

new Thread(new Runnable() {

@Override

public void run() {

try{

Log.d(TAG,"开始连接socket,uuid:" + ClassicsBluetooth.UUID);

socket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(ClassicsBluetooth.UUID));

if (socket != null && !socket.isConnected()){

socket.connect();

Log.d("芜湖芜湖",socket.isConnected()+"...连接");

}

}catch (IOException e){

Log.e(TAG,"socket连接失败");

try {

socket.close();

} catch (IOException e1) {

e1.printStackTrace();

Log.e(TAG,"socket关闭失败");

}

}

}

}).start();

到这里应该就打开spp了 我们就可以开始愉快的通信了

 

  • ***6最后一步 通过接口回调 拿到已连接的socket 然后和蓝牙友好的发送指令  这里和socket的操作是基本一样的了

 

这里可以接收我们每次发送完指令返回的信息

//读取返回数据

public void readData(){

if (socket!=null){

new Thread(new Runnable() {

@Override

public void run() {

int length = 0;

String str;

byte[] buf = new byte[1024];

try {

BufferedInputStream in = new BufferedInputStream(socket.getInputStream());

while ((length = in.read(buf)) != -1) {

str = new String(buf, 0, length);

Message message = new Message();

message.obj=str;

message.what=1;

handler.sendMessage(message);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}).start();

}

}

//返回信息 给到handler去展示

private Handler handler =new Handler(){

@Override

public void handleMessage(@NonNull Message msg) {

super.handleMessage(msg);

if (msg.what==1){

String str= (String) msg.obj;

 

Log.d(TAG,str+"。。。。。handler");

Toast.makeText(MainActivity.this, "..."+str, Toast.LENGTH_SHORT).show();

}

}

};

以上就是接收信息的代码 下面我把发送数据的代码贴上来

通过socket获取输出流发送 发送完调用读取方法拿回调信息

if (socket!=null){

new Thread(new Runnable() {

@Override

public void run() {

try {

OutputStream outputStream = socket.getOutputStream();

outputStream.write("MICOPEN".getBytes());

outputStream.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

}).start();

readData(); //开启

}else {

Toast.makeText(MainActivity.this, "你还没有连接socket", Toast.LENGTH_SHORT).show();

}

 

你可能感兴趣的:(Android蓝牙通信)