天天看點

android 實作藍牙自動配對連接配接,Android實踐 -- Android藍牙設定連接配接

藍牙開發相關

使用Android Bluetooth APIs将裝置通過藍牙連接配接并通信,設定藍牙,查找藍牙裝置,配對藍牙裝置

連接配接并傳輸資料,以下是Android系統提供的藍牙相關的類和接口

BluetoothAdapter

BluetoothDevice

BluetoothSocket

BluetoothServerSocket

BluetoothClass

BluetoothProfile

BluetoothHeadset

BluetoothA2dp

BluetoothHealth

BluetoothHealthCallback

BluetoothHealthAppConfiguration

BluetoothProfile.ServiceListener

藍牙權限

使用藍牙功能,需要在AndroidManifest.xml中聲明藍牙相關的權限

建立藍牙

初始化連接配接

在通過藍牙通信之前,需要先确定裝置是否支援藍牙功能,先初始化一個BluetoothAdapter的執行個體,

BluetoothAdapter提供了一個靜态方法getDefaultAdapter()來獲得BluetoothAdapter的執行個體

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

if (mBluetoothAdapter == null) {

// 裝置不支援藍牙功能

}

打開藍牙

下一步就是打開藍牙,調用isEnabled()方法檢查藍牙功能是否已經打開,傳回true說明藍牙已開啟,

傳回false說明藍牙功能未開啟,開啟藍牙可以通過發送廣播ACTION_REQUEST_ENABLE,也可以通過方法

enable()直接打開,這兩種方法都會有藍牙權限的提示,選擇允許,否則無法打開藍牙

if (!mBluetoothAdapter.isEnabled()) {

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

}

mBluetoothAdapter.enable();

在應用中可以設定藍牙的狀态的監聽ACTION_STATE_CHANGED廣播,當藍牙的狀态的變化時,就會觸發這個

廣播,接收到這個廣播之後,在intent中可以獲得目前藍牙的狀态和前一次的藍牙的狀态

int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);

藍牙的狀态值有:

int STATE_OFF = 10;//藍牙關閉狀态

int STATE_TURNING_ON = 11;//藍牙正在打開

int STATE_ON = 12;//藍牙打開狀态

int STATE_TURNING_OFF = 13;//藍牙正在關閉

查找藍牙裝置

打開藍牙之後,下一步就是查找可以使用的藍牙裝置,藍牙的api中也提供了相關的接口,由于藍牙的掃描

是一個耗電的操作,不用時計時取消掃描藍牙

mBluetoothAdapter.isDiscovering(); //監測藍牙是否正在掃描

mBluetoothAdapter.startDiscovery();//開始掃描

mBluetoothAdapter.cancelDiscovery();//取消掃描

為了發現可用的藍牙的裝置,必須在應用中注冊ACTION_FOUND的廣播,調用方法startDiscovery()如果查找到可用的

裝置會觸發這個廣播,這個廣播中帶有EXTRA_DEVICE的裝置資訊可以通過下面的方法獲得裝置的資訊

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (BluetoothDevice.ACTION_FOUND.equals(action)) {

BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

Log.e("tag","device name: "+device.getName()+" address: "+device.getAddress());

}

}

};

IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

registerReceiver(mReceiver, filter);

查詢已經配對的裝置清單

在進行查找之前,可以先獲得之前已經配對成功的藍牙裝置的清單,可以調用方法getBondedDevices()獲得

已經配對的藍牙裝置清單

Set pairedDevices = mBluetoothAdapter.getBondedDevices();

if (pairedDevices.size() > 0) {

for (BluetoothDevice device : pairedDevices) {

//可以獲得已經配對的藍牙的名稱和位址

Log.e("tag","device name: "+device.getName()+" address: "+device.getAddress());

}

}

是其他裝置可見

上面講的都是發現其他的藍牙裝置,也可以設定裝置本身是否對其他裝置可見,通過發送ACTION_REQUEST_DISCOVERABLE

的廣播,會調用系統的方法,還可以設定多長時間内是可見的,在intent中設定EXTRA_DISCOVERABLE_DURATION,最大值是

3600s,超過3600s會設定為120s,點選允許會回調onActivityResult()方法

//設定裝置在300s内是可見的

Intent discoverableIntent = new

Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);

startActivity(discoverableIntent);

如果沒有打開藍牙,執行上面的操作會自動打開藍牙

可以通過監聽ACTION_SCAN_MODE_CHANGED廣播,可以在intent中根據EXTRA_SCAN_MODE的參數獲得目前裝置的SCAN MODE

有一些幾種模式

int SCAN_MODE_NONE = 20;//這個模式不能被發現也不能連接配接

int SCAN_MODE_CONNECTABLE = 21;//這個模式不能被掃描到,但是可以連接配接

int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;//這個模式可以被發現,也能被連接配接

藍牙的連接配接

Server 端

通過BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法獲得BluetoothServerSocket對象

的執行個體,然後socket就會通過accept()監聽用戶端的連接配接的狀态

private class AcceptThread extends Thread {

private final BluetoothServerSocket mmServerSocket;

public AcceptThread() {

BluetoothServerSocket tmp = null;

try {

tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

} catch (IOException e) { }

mmServerSocket = tmp;

}

public void run() {

BluetoothSocket socket = null;

// 在背景一直監聽用戶端的請求

while (true) {

try {

socket = mmServerSocket.accept();

} catch (IOException e) {

break;

}

if (socket != null) {

mmServerSocket.close();

break;

}

}

}

public void cancel() {

try {

mmServerSocket.close();

} catch (IOException e) { }

}

}

Client 端

使用BluetoothDevice的createRfcommSocketToServiceRecord(UUID)方法獲得BluetoothSocket對象的執行個體

然後調用connect()方法,這時server端會監聽到這個請求,之後就建立連接配接,然後就可以進行通信了

private class ConnectThread extends Thread {

private final BluetoothSocket mmSocket;

private final BluetoothDevice mmDevice;

public ConnectThread(BluetoothDevice device) {

BluetoothSocket tmp = null;

mmDevice = device;

try {

tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

} catch (IOException e) { }

mmSocket = tmp;

}

public void run() {

mBluetoothAdapter.cancelDiscovery();

try {

mmSocket.connect();

} catch (IOException connectException) {

try {

mmSocket.close();

} catch (IOException closeException) { }

return;

}

}

public void cancel() {

try {

mmSocket.close();

} catch (IOException e) { }

}

}

連接配接的監聽

可以通過注冊廣播監聽藍牙裝置連接配接的狀态變化,廣播BluetoothDevice.ACTION_BOND_STATE_CHANGED,監聽到這個廣播之後,可以

在intent中獲得連接配接的狀态

int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);

裝置連接配接的狀态值

int BOND_NONE = 10;//沒有連接配接

int BOND_BONDING = 11;//正在連接配接

int BOND_BONDED = 12;//已經建立連接配接