使用 BluetoothAdapter
,您可以透過裝置探索或查詢已配對裝置清單,尋找遠端藍牙裝置。
請先確認您已取得適當的藍牙權限,並設定應用程式的藍牙功能,再嘗試尋找藍牙裝置。
裝置探索是一種掃描程序,可搜尋附近支援藍牙的裝置,並要求取得每部裝置的相關資訊。這項程序有時也稱為探索、查詢或掃描。鄰近的藍牙裝置只有在目前可供偵測時,才會回應探索要求。如果裝置可供偵測,則會分享部分資訊 (例如裝置名稱、類別和專屬 MAC 位址),藉此回應偵測要求。執行探索程序的裝置可利用這項資訊,選擇是否要與所探索的裝置建立連線。
由於可偵測的裝置可能會揭露使用者位置資訊,因此裝置探索程序需要位置資訊存取權。如果應用程式是在搭載 Android 8.0 (API 級別 26) 以上版本的裝置上使用,建議改用Companion Device Manager API。這個 API 會代表您的應用程式執行裝置探索作業,因此應用程式不需要要求位置存取權。
首次與遠端裝置建立連線後,系統會自動向使用者顯示配對要求。裝置配對後,系統會儲存該裝置的基本資訊 (例如裝置名稱、類別和 MAC 位址),並可透過藍牙 API 讀取。只要使用遠端裝置的已知 MAC 位址,即可隨時與該裝置建立連線,且無須執行探索作業 (假設裝置仍在範圍內)。
請注意,配對和連線有所不同:
- 配對的意思是兩部裝置都知道彼此的存在,並且有可用於驗證的共用連結鍵,且能彼此建立加密連線。
- 「已連線」是指裝置目前共用 RFCOMM 管道,且可相互傳輸資料。目前的藍牙 API 要求裝置必須先配對,才能建立 RFCOMM 連線。您只要透過藍牙 API 啟動加密連線,系統就會自動進行配對。
以下各節將說明如何尋找已配對的裝置,以及如何使用裝置探索功能來探索新裝置。
查詢配對的裝置
在執行裝置探索作業之前,建議您查詢已配對的裝置組合,看看是否已知曉所需的裝置。如要這麼做,請呼叫 getBondedDevices()
。這個方法會傳回一組代表已配對裝置的 BluetoothDevice
物件。舉例來說,您可以查詢所有已配對的裝置,並取得每部裝置的名稱和 MAC 位址,如以下程式碼片段所示:
Kotlin
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
Java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
如要啟動與藍牙裝置的連線,您只需要從相關聯的 BluetoothDevice
物件擷取 MAC 位址,方法是呼叫 getAddress()
。如要進一步瞭解如何建立連線,請參閱「連線藍牙裝置」一文。
探索裝置
如要開始探索裝置,請呼叫 startDiscovery()
。這個程序是非同步的,並會傳回布林值,指出是否已成功啟動探索。探索程序通常會進行約 12 秒的查詢掃描,接著掃描每個找到的裝置,以擷取其藍牙名稱。
如要接收每個偵測到的裝置相關資訊,應用程式必須為 ACTION_FOUND
意圖註冊 BroadcastReceiver
。系統會向每部裝置廣播這個意圖。意圖包含額外欄位 EXTRA_DEVICE
和 EXTRA_CLASS
,而這兩個欄位分別包含 BluetoothDevice
和 BluetoothClass
。下列程式碼片段說明如何註冊,以便在偵測到裝置時處理廣播訊息:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) } // Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when(action) { BluetoothDevice.ACTION_FOUND -> { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address } } } } override fun onDestroy() { super.onDestroy() ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
如要啟動與藍牙裝置的連線,請在 BluetoothDevice
上呼叫 getAddress()
,擷取相關聯的 MAC 位址。
啟用可探索性
如要讓本機裝置可供其他裝置探索,請使用 ACTION_REQUEST_DISCOVERABLE
意圖呼叫 startActivityForResult(Intent, int)
。這會發出要求,讓您啟用系統的可偵測模式,而無須前往「設定」應用程式,這會停止您自己的應用程式。根據預設,裝置會在兩分鐘內變成可偵測狀態。您可以新增 EXTRA_DISCOVERABLE_DURATION
額外項目,定義不同的時間長度 (最多五分鐘)。
以下程式碼片段會將裝置設為可在五分鐘內偵測:
Kotlin
val requestCode = 1; val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply { putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivityForResult(discoverableIntent, requestCode)
Java
int requestCode = 1; Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(discoverableIntent, requestCode);
圖 2:啟用可偵測性對話方塊。
系統會顯示對話方塊,要求使用者授予權限,讓裝置可供他人偵測,如圖 2 所示。如果使用者回覆「允許」,裝置就會在指定時間內變得可供搜尋。接著,您的活動會收到對 onActivityResult()
回呼的呼叫,結果代碼等於裝置可供偵測的時間長度。如果使用者回應「拒絕」,或發生錯誤,結果代碼會是 RESULT_CANCELED
。
裝置會在預定的時間內保持在可偵測模式。如要接收可發現模式變更的通知,請為 ACTION_SCAN_MODE_CHANGED
意圖註冊 BroadcastReceiver
。這個意圖包含額外的欄位 EXTRA_SCAN_MODE
和 EXTRA_PREVIOUS_SCAN_MODE
,分別提供新掃描模式和舊掃描模式。每個額外項目的可能值如下:
SCAN_MODE_CONNECTABLE_DISCOVERABLE
- 裝置處於可偵測模式。
SCAN_MODE_CONNECTABLE
- 裝置未處於可偵測模式,但仍可接收連線。
SCAN_MODE_NONE
- 裝置未處於可偵測模式,因此無法接收連線。
如果您要啟動與遠端裝置的連線,則不需要啟用裝置可偵測性。只有在您希望應用程式主機代管可接受傳入連線的伺服器通訊端時,才需要啟用可探索性,因為遠端裝置必須先探索其他裝置,才能與這些裝置建立連線。