Android通過BluetoothAdapter來檢測藍牙狀態,打開或關閉藍牙,掃描藍牙並得到藍牙信息等功能。
在使用時,通過BluetoothAdapter.getDefaultAdapter()方法來獲取系統的BluetoothAdapter,如果系統支持藍牙則會返回實例,如果不支持,則返回空;寫個簡單的demo來看看吧:
先在MainActivity.class
中定義BluetoothAdapter、BluetoothDevice等變量
public class MainActivity extends Activity implements View.OnClickListener,TBluetoothListAdapter.OnBluetoothItemClickListener {
//adapter
private BluetoothAdapter bluetoothAdapter ;
//遠程的藍牙設備,可以創建到各個藍牙設備的連接,並獲取遠程藍牙設備的信息(如名字,地址,類名和匹配狀態)
private BluetoothDevice mDevice ;
//用列表顯示搜索得到的藍牙設備信息
private RecyclerView rvBluetooth ;
//自定義的數據展示adapter
private TBluetoothListAdapter adapter ;
//簡單的藍牙信息實體類,用於展示
private List<TBlueToothInfo> datas = new ArrayList<>() ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main) ;
initView();
initData();
}
}
然後在initView方法中初始化佈局等相關信息:
private void initView() {
//初始化佈局
rvBluetooth = (RecyclerView)findViewById(R.id.rv_bluetooth) ;
findViewById(R.id.tv_search_bluetooth).setOnClickListener(this) ;
//初始化TBluetoothListAdapter
adapter = new TBluetoothListAdapter(datas,this) ;
//設置數據列表的點擊事件
adapter.setOnBluetoothItemClickListener(this) ;
rvBluetooth.setAdapter(adapter) ;
rvBluetooth.setLayoutManager(new LinearLayoutManager(this)) ;
}
在initData方法中初始化bluetoothAdapter
private void initData() {
//初始化adapter和權限
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
通過點擊事件,開始判斷藍牙狀態,如果未打開則打開藍牙,如果可用,則開始掃描藍牙設備:
@Override
public void onClick(View v) {
if(bluetoothAdapter != null) {//代表系統有藍牙功能
if(!bluetoothAdapter.isEnabled()) { //如果藍牙不可用
//啓動藍牙
Intent bluetoothIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) ;
startActivity(bluetoothIntent);
//搜索藍牙
searchBluetooth();
} else { // 藍牙可用
//搜索藍牙
searchBluetooth();
}
}
}
搜索藍牙的方法如下,主要是通過發送系統廣播來監聽掃描得到的結果。BluetoothDevice有多個ACTION,這裏我們用到了2個
- ACTION_FOUND:掃描到任一遠程藍牙設備時,會發送;
- ACTION_DISCOVERY_FINISHED:掃描完成時會發送,一般掃描過程最長爲12秒
//搜索藍牙
private void searchBluetooth() {
hasRegist = true ;
IntentFilter filter = new IntentFilter() ;
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(receiver,filter);
if (bluetoothAdapter.isDiscovering()) {
//通過cancelDiscovery方法來取消掃描
bluetoothAdapter.cancelDiscovery();
}
datas.clear();
//通過調用BluetoothAdapter的startDiscovery方法來掃描,掃描的結果通過廣播來監聽
blutoothAdapter.startDiscovery() ;
}
在廣播的receiver裏,通過BluetoothDevice得到遠程的藍牙設備的信息:
private BroadcastReceiver receiver = new 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) ;
String itemName = device.getName() ;
String hasPaired = device.getBondState == BluetoothDevice.BOND_BONDED ?"(已配對)":"(未配對)" ;
String address = device.getAddress() ;
TBlueToothInfo info = new TBlueToothInfo() ;
info.setDeviceName(itemName + hasPaired) ;
info.setDeviceAddr(address) ;
if (!hasContainedDevice(info)) {
datas.add(info) ;
adapter.notifyDataSetChanged() ;
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
if (datas.size == 0 ) {
//沒有發現任何設備
}
}
}
}
//判斷掃描出的設備是不是已經存在於數據列表中了
private boolean hasContainedDevice(TBlueToothInfo info) {
for (TBlueToothInfo blueToothInfo : datas) {
if (info.getDeviceAddr.equals(blueToothInfo.getDeviceAddr())) {
return true ;
}
}
return false ;
}
註冊了receiver,也自然要註銷:
@Override
protected void onStop() {
super.onStop() ;
if (hasRegist) {
unregisterReceiver(receiver) ;
}
}
在receiver中,我們得到了掃描出的藍牙設備信息,並且展示到了列表中,現在,我們設置recyclerview的item點擊事件,點擊配對當前設備:
@Override
public void clickItem(int position) {
//取到當前點擊item的藍牙地址,通過adapter得到遠程設備
mDevice = bluetoothAdapter.getRemoteDevice(datas.get(position).getDeviceAddr()) ;
if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) { //如果未配對過
IntentFilter boundFilter = new IntentFilter() ;
boundFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED) ;
registerReceiver(boundReceiver,boundFilter);
//已經配對,則解除配對
pairOrConnect(true) ;
} else {
//未配對,則開始配對
pairOrConnect(false) ;
}
}
這裏我們獲取到遠程設備的配對狀態,如果是沒有配對過的設備,則開始配對:
private void pairOrConnect(boolean pair) {
boolean success ;// 配對 或 解除配對是否成功
if (pair) {//未配對過的設備,開始配對
try {
Method createBound = BluetoothDevice.class.getMethod("createBond");
success = (boolean) createBoundMethod.invoke(mDevice) ;
} catch(NoSuchMethonException e) {
e.printStackTrace();
} catch(InvocationTargetException e ) {
e.printStackTrace();
} catch(IllegalAccessException e) {
e.printStackTrace();
}
} else {//已經配對過的設備,則取消配對
try {
Method removeBound = BluetoothDevice.class.getMethod("removeBound");
success = (boolean) removeBound.invoke(mDevice) ;
} catch(NoSuchMethonException e) {
e.printStackTrace();
} catch(InvocationTargetException e ) {
e.printStackTrace();
} catch(IllegalAccessException e) {
e.printStackTrace();
}
}
}
這裏無論是配對還是移除配對(createBond/removeBond)都是通過反射來調用BluetoothDevice類裏的方法,具體有哪些方法可用可以加直接看BluetoothDevice.class的源碼。
藍牙配對狀態的改變,我們通過註冊boundReceiver來監聽:
private BroadcastReceiver boundReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context , Intent intent) {
String action = intent.getAction() ;
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (!mDevice.equals(device)) {//得到的設備不是剛剛點擊的設備
return ;
}
switch(device.getBondState()) {//得到設備的配對狀態
case BluetoothDevice.BOND_BONDING:
//配對中...
breake;
case BluetoothDevice.BOND_BONDED:
//配對成功
for (TBlueToothInfo info : datas ) {
if (info.getDeviceAddr().equals(device.getAddress())) {
String name = info.getDeviceName();
name = name.replace("未配對","已配對");
info.setDeviceName(name) ;
}
}
adapter.notifyDataSetChanged();
unregisterReceiver(boundReceiver) ;
break ;
case BluetoothDevice.BOND_NONE:
//配對成功
for (TBlueToothInfo info : datas ) {
if (info.getDeviceAddr().equals(device.getAddress())) {
String name = info.getDeviceName();
name = name.replace("未配對","已配對");
info.setDeviceName(name) ;
}
}
adapter.notifyDataSetChanged();
//註銷boundReceiver
unregisterReceiver(boundReceiver) ;
break ;
default:
break;
}
}
}
}
現在,藍牙的打開、搜索、配對和取消配對就已經全部實現了,也算是完成了藍牙最基本的功能。完成配對後就可以開始連接並傳輸數據了。