android 传统蓝牙开发(三):蓝牙设备连接及通信

蓝牙设备连接及通信

1.设备连接,服务器端开启线程一直等待连接,客户端点击某个目标设备,关闭服务器线程监听,并开启线程,发出连接请求。 

注意:客户端连接前,一定cancelDiscovery()

 

// 蓝牙已开启

if (bluetoothAdapter.isEnabled()) {

showBondDevice();

// 默认开启服务线程监听

if (serverThread != null) {

serverThread.cancel();

}

Log.e("tag", "-------------- new server thread");

serverThread = new ServerThread(bluetoothAdapter, uiHandler);

new Thread(serverThread).start();

}

 

resultList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

// 关闭服务器监听

if (serverThread != null) {

serverThread.cancel();

serverThread = null;

Log.e("TAg", "---------------client item click , cancel server thread ," +

"server thread is null");

}

BluetoothDevice device = deviceList.get(position);

// 开启客户端线程,连接点击的远程设备

clientThread = new ClientThread(bluetoothAdapter, device,uiHandler);

new Thread(clientThread).start();

// 通知 ui 连接的服务器端设备

Message message = new Message();

message.what = Params.MSG_CONNECT_TO_SERVER;

message.obj = device;

uiHandler.sendMessage(message);

 

}

});

 

 

 

2.服务端

android 蓝牙之间可以通过SDP协议建立连接进行通信,通信方式类似于平常使用socket。

首先创建BluetoothServerSocket ,BluetoothAdapter中提供了两种创建BluetoothServerSocket 方式,如下图所示为创建安全的RFCOMM Bluetooth socket,该连接是安全的需要进行配对。而通过listenUsingInsecureRfcommWithServiceRecord创建的RFCOMM Bluetooth socket是不安全的,连接时不需要进行配对。

其中的uuid需要服务器端和客户端进行统一。

package com.example.zb.mybluetoothdemo;

 

import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;

import android.bluetooth.BluetoothServerSocket;

import android.bluetooth.BluetoothSocket;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.UUID;

 

/**

* Created by zb on 2019/5/6.

*/

 

public class ServerThread implements Runnable{

final String TAG = "ServerThread";

 

BluetoothAdapter bluetoothAdapter;

// 本地服务器套接字

BluetoothServerSocket serverSocket =null;

BluetoothSocket socket = null;

Handler uiHandler;

OutputStream out;

InputStream in;

boolean acceptFlag = true;

 

public ServerThread(BluetoothAdapter bluetoothAdapter, Handler handler) {

this.bluetoothAdapter = bluetoothAdapter;

this.uiHandler = handler;

BluetoothServerSocket tmp = null;

try {

// 创建一个新的监听服务器套接字

tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(Params.NAME, UUID.fromString(Params.UUID));

} catch (IOException e) {

e.printStackTrace();

}

serverSocket = tmp;

Log.e(TAG, "-------------- do new()");

}

 

@Override

public void run() {

Log.e(TAG, "-------------- do run()");

try {

while (acceptFlag) {

// 这是一个阻塞调用 返回成功的连接

// mServerSocket.close()在另一个线程中调用,可以中止该阻塞

socket = serverSocket.accept();

// 阻塞,直到有客户端连接

if (socket != null) {

Log.e(TAG, "-------------- socket not null, get a client");

out = socket.getOutputStream();

in = socket.getInputStream();

BluetoothDevice remoteDevice = socket.getRemoteDevice();

Message message = new Message();

message.what = Params.MSG_REV_A_CLIENT;

message.obj = remoteDevice;

uiHandler.sendMessage(message);

 

// 读取服务器 socket 数据

new Thread(new Runnable() {

@Override

public void run() {

Log.e(TAG, "-----------do server read run()");

 

byte[] buffer = new byte[1024];

int len;

String content;

try {

while ((len = in.read(buffer)) != -1) {

content = new String(buffer, 0, len);

Message message = new Message();

message.what = Params.MSG_CLIENT_REV_NEW;

message.obj = content;

uiHandler.sendMessage(message);

Log.e(TAG, "------------- server read data in while ,send msg ui" + content);

}

 

} catch (IOException e) {

e.printStackTrace();

}

}

}).start();

 

break;

}

}

} catch (IOException e) {

e.printStackTrace();

}

 

}

 

public void write(String data){

try {

out.write(data.getBytes("utf-8"));

Log.e(TAG, "---------- write data ok "+data);

} catch (IOException e) {

e.printStackTrace();

}

}

 

public void cancel() {

try {

acceptFlag = false;

serverSocket.close();

Log.e(TAG, "-------------- do cancel ,flag is "+acceptFlag);

 

} catch (IOException e) {

e.printStackTrace();

Log.e(TAG, "----------------- cancel " + TAG + " error");

}

}

}

 

 

3.客户端

客户端主要用来创建RFCOMM socket,并连接服务端。

先扫描周围的蓝牙设备,如果扫描到指定设备则进行连接。mBlthChatUtil.connect(scanDevice)连接到设备,

连接过程主要在ConnectThread线程中进行,先创建socket,方式有两种,

如下代码中是安全的(createRfcommSocketToServiceRecord)。另一种不安全连接对应的函数是createInsecureRfcommSocketToServiceRecord。

 

 

package com.example.zb.mybluetoothdemo;

 

import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;

import android.bluetooth.BluetoothSocket;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.UUID;

 

/**

* Created by zb on 2019/5/6.

*/

 

public class ClientThread implements Runnable{

final String TAG = "ClientThread";

BluetoothAdapter bluetoothAdapter;

BluetoothDevice device;

Handler uiHandler;

BluetoothSocket socket;

OutputStream out;

InputStream in;

public ClientThread(BluetoothAdapter bluetoothAdapter, BluetoothDevice device, Handler handler) {

this.bluetoothAdapter = bluetoothAdapter;

this.device = device;

this.uiHandler = handler;

BluetoothSocket tmp = null;

try {

//创建socket

tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(Params.UUID));

} catch (IOException e) {

e.printStackTrace();

}

socket = tmp;

}

 

@Override

public void run() {

 

Log.e(TAG, "----------------- do client thread run()");

if (bluetoothAdapter.isDiscovering()) {

bluetoothAdapter.cancelDiscovery();

}

 

try {

// socket 连接,该调用会阻塞,直到连接成功或失败

socket.connect();

out = socket.getOutputStream();

in = socket.getInputStream();

new Thread(new Runnable() {

@Override

public void run() {

Log.e(TAG, "-----------do client read run()");

byte[] buffer = new byte[1024];

int len;

String content;

try {

//读数据

while ((len=in.read(buffer)) != -1) {

content=new String(buffer, 0, len);

Message message = new Message();

message.what = Params.MSG_CLIENT_REV_NEW;

message.obj = content;

//更新 ui

uiHandler.sendMessage(message);

Log.e(TAG, "------------- client read data in while ,send msg ui" + content);

}

 

} catch (IOException e) {

e.printStackTrace();

}

}

}).start();

 

} catch (IOException e) {

e.printStackTrace();

Log.e(TAG, "-------------- exception");

}

}

//写数据

public void write(String data){

try {

out.write(data.getBytes("utf-8"));

Log.e(TAG, "---------- write data ok "+data);

} catch (IOException e) {

e.printStackTrace();

}

}

}

 

 

4.通信

/**

* 向 socket 写入发送的数据

*

* @param dataSend

*/

public void writeData(String dataSend) {

if (serverThread != null) {

serverThread.write(dataSend);

} else if (clientThread != null) {

clientThread.write(dataSend);

}

}

 

(一)打开/关闭蓝牙设备:https://blog.csdn.net/lumingzhang/article/details/89922173

(二)搜索蓝牙设备并展示:https://blog.csdn.net/lumingzhang/article/details/89922235

本人github地址:https://github.com/b888zhang/MyBluetoothDemo

 

本文在原文上修改,原文地址:https://blog.csdn.net/qiao_jim/article/details/73008695 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值