全栈工程师开发手册 (作者:栾鹏)
安卓教程全解
安卓蓝牙开发全解。启动蓝牙、启动可发现机制、广播监听蓝牙状态、广播监听蓝牙可发现机制状态、发现远程蓝牙设备、蓝牙设备作为服务器端、蓝牙设备作为客户端、蓝牙设备发送接收数据。
获取蓝牙管理
在使用蓝牙前需要先获取系统蓝牙管理
BluetoothAdapter bluetooth;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1); //这里的UI文件任意
//访问默认的Bluetooth Adapter
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
this.bluetooth = bluetooth;
}
启动蓝牙、可发现机制
//启动蓝牙
private static final int ENABLE_BLUETOOTH = 1;
private void initBluetooth() {
//判断蓝牙是否打开
if (!bluetooth.isEnabled()) {
//蓝牙未启动,提示用户打开它
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, ENABLE_BLUETOOTH);
} else {
//蓝牙已启动,初始化其UI
initBluetoothUI();
}
}
//启用可发现机制
protected static final int DISCOVERY_REQUEST = 1;
private void makeDiscoverable() {
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE),DISCOVERY_REQUEST);
Log.v("蓝牙", "准备启动可发现机制");
}
//根据返回结果,确认蓝牙、可发现机制是否启动
protected void onActivityResult(int requestCode,int resultCode, Intent data) {
//请求值为是否打开蓝牙
if (requestCode == ENABLE_BLUETOOTH)
//返回值为蓝牙以打开
if (resultCode == RESULT_OK) {
//蓝牙已启动,初始化其UI
initBluetoothUI();
}
if (resultCode==RESULT_CANCELED) {
Log.v("蓝牙", "未能成功启动蓝牙");
}
//请求值为是否允许打开可发现机制
if (requestCode == DISCOVERY_REQUEST) {
//返回值为取消
if (resultCode == RESULT_CANCELED) {
Log.v("蓝牙", "未能成功启动可发现机制");
}
if(resultCode==RESULT_OK)
{
Log.v("蓝牙", "成功启动可发现机制");
}
}
}
//初始化蓝牙UI
private void initBluetoothUI() {
Log.v("蓝牙", "蓝牙已启动");
}
广播监听方式获取蓝牙和可发现机制的状态变化
除了根据请求蓝牙和可发现机制启动的返回结果获取蓝牙状态,实际中应用更多的是通过广播监听的方式获取蓝牙和可发现机制的状态变化。
当蓝牙启动或关闭,可发现机制启动或关闭,都会想系统发送广播信息,主要在app中监听这些广播就能获取蓝牙状态。
//广播监听的方式获知蓝牙状态变化
private void surebluetoothstate() {
registerReceiver(bluetoothState_receiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
//监听蓝牙是否打开的广播接收器
BroadcastReceiver bluetoothState_receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
// TODO 自动生成的方法存根
String prevStateExtra = BluetoothAdapter.EXTRA_PREVIOUS_STATE;
String stateExtra = BluetoothAdapter.EXTRA_STATE;
int state=intent.getIntExtra(stateExtra, -1);
int previousState = intent.getIntExtra(prevStateExtra, -1);
String tt="";
switch (state) {
case (BluetoothAdapter.STATE_TURNING_ON): tt="蓝牙正在打开"; break;
case (BluetoothAdapter.STATE_ON): tt="蓝牙已经打开"; break;
case (BluetoothAdapter.STATE_TURNING_OFF): tt="蓝牙正在关闭"; break;
case (BluetoothAdapter.STATE_OFF): tt="蓝牙已经关闭"; break;
default:break;
}
Log.v("蓝牙", "广播监听到"+tt);
}
};
//广播监听的方式获知蓝牙可发现机制状态变化
private void surebluetoothstate1() {
registerReceiver(new BroadcastReceiver(){ //匿名注册接收机
@Override
public void onReceive(Context context, Intent intent) {
// TODO 自动生成的方法存根
String prevScanMode= BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE;
String scanMode = BluetoothAdapter.EXTRA_SCAN_MODE;
int currentScanMode=intent.getIntExtra(scanMode, -1);
int prevMode = intent.getIntExtra(prevScanMode, -1);
//currentScanMode,23表示打开,21表示关闭,20表示蓝牙关闭(蓝牙关闭,可发现自动关闭)
String str="可发现机制开启";
switch (currentScanMode) {
case 23:str="蓝牙开启,可发现机制开启";break;
case 21:str="蓝牙开启,可发现机制关闭";break;
case 20:str="蓝牙关闭,可发现机制关闭";break;
default:break;
}
Log.d("蓝牙", str);
}
}, new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED));
}
发现远程蓝牙设备
由于发现远程蓝牙设备比较耗时,所以安卓也是通过异步广播的形式向系统广播发现的蓝牙设备信息。因此需要在自己的app中实现这个广播接收。
//启动发现远程蓝牙设备,使用广播监听获知远程设备的信息
private ArrayList<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
private void startDiscovery()
{
registerReceiver(discoveryResult,new IntentFilter(BluetoothDevice.ACTION_FOUND));
//isEnabled判断蓝牙是否打开,isDiscovering判断蓝牙是否正在扫描
if (bluetooth.isEnabled() && !bluetooth.isDiscovering())
deviceList.clear();
bluetooth.startDiscovery();
}
//发现远程设备的过程是异步的,安卓使用broadcast intent来依次通知发现过程的启动和结束以及在扫描过程中发现的远程设备
//注册一个接收器,接收这个广播事件
BroadcastReceiver discoveryResult = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String remoteDeviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//BluetoothDevice device = bluetooth.getRemoteDevice("01:23:77:35:2F:AA"); //也可以通过硬件地址获取设备,
deviceList.add(remoteDevice);
Log.d("蓝牙", "发现到远程设备" + remoteDeviceName);
}
};
蓝牙数据的传输
蓝牙包含一个BluetoothServerSocket连接信道(用于连接信令的传输),一个BluetoothSocket数据信道(用于服务器端和客户端数据的传输)。
两个蓝牙设备,一个作为服务器端,一个作为客户端。
服务器端代码
//作为服务器端,监听客户端蓝牙socket连接请求。
private BluetoothSocket transferSocket;
private UUID startServerSocket(BluetoothAdapter bluetooth) {
UUID uuid = UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666");
String name = "bluetoothserver";
try {
final BluetoothServerSocket btserver = bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);
Thread acceptThread = new Thread(new Runnable() {
public void run() {
try {
// 在客户端连接建立以前保持阻塞
BluetoothSocket Socket = btserver.accept();
//可以先发送消息
// 开始监听信息
StringBuilder incoming = new StringBuilder();
listenForMessages(Socket, incoming);
// 添加对用来到来消息的套接字的引用,以便本机进行发送数据
transferSocket = Socket;
} catch (IOException e) {
Log.e("蓝牙", "服务器 连接 IO 出错", e);
}
}
});
acceptThread.start();
} catch (IOException e) {
Log.e("蓝牙", "Socket 监听 IO 出错", e);
}
return uuid;
}
客户端代码
//创建一个蓝牙客户端套接字
private void connectToServerSocket(BluetoothDevice device, UUID uuid) {
try{
BluetoothSocket clientSocket = device.createRfcommSocketToServiceRecord(uuid);
// 阻塞直到服务器接受连接
clientSocket.connect();
//可以先发送消息
//开始监听消息
StringBuilder incoming = new StringBuilder();
listenForMessages(clientSocket, incoming);
// 添加对用于发送信息的套接字的引用
transferSocket = clientSocket;
} catch (IOException e) {
Log.e("蓝牙", "蓝牙客户端 I/O 出错", e);
}
}
服务器端或客户端的发送数据函数
//使用Bluetooth Sockets发送数据
private void sendMessage(BluetoothSocket socket, String message) {
OutputStream outStream;
try {
outStream = socket.getOutputStream();
//添加一个终止符
byte[] byteArray = (message + " ").getBytes();
byteArray[byteArray.length - 1] = 0;
outStream.write(byteArray);
} catch (IOException e) {
Log.e("蓝牙", "消息发送失败", e);
}
}
服务器端或客户端的接收数据函数
//使用Bluetooth Sockets接收数据
private boolean listening = false;
private void listenForMessages(BluetoothSocket socket, StringBuilder incoming)
{
listening = true;
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
try {
InputStream instream = socket.getInputStream();
int bytesRead = -1;
while (listening) {
bytesRead = instream.read(buffer);
if (bytesRead != -1) {
String result = "";
while ((bytesRead == bufferSize) &&(buffer[bufferSize-1] != 0))
{
result = result + new String(buffer, 0, bytesRead - 1);
bytesRead = instream.read(buffer);
}
result = result + new String(buffer, 0, bytesRead - 1);
incoming.append(result);
}
socket.close();
}
} catch (IOException e) {
Log.e("蓝牙", "消息接收失败", e);
}
finally {
}
}