Android 掃描附近的藍(lán)牙設(shè)備并連接藍(lán)牙音響的示例
寫了一個(gè)可以掃描附近藍(lán)牙設(shè)備的小Demo,可以查看藍(lán)牙設(shè)備的設(shè)備名和Mac地址
代碼量不多,很容易看懂
/** * 作者:葉應(yīng)是葉 * 時(shí)間:2017/9/8 20:13 * 描述: */ public class ScanDeviceActivity extends AppCompatActivity { private LoadingDialog loadingDialog; private DeviceAdapter deviceAdapter; private BluetoothAdapter bluetoothAdapter; private Handler handler = new Handler(); private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case BluetoothAdapter.ACTION_DISCOVERY_STARTED: showLoadingDialog("正在搜索附近的藍(lán)牙設(shè)備"); break; case BluetoothAdapter.ACTION_DISCOVERY_FINISHED: Toast.makeText(ScanDeviceActivity.this, "搜索結(jié)束", Toast.LENGTH_SHORT).show(); hideLoadingDialog(); break; case BluetoothDevice.ACTION_FOUND: BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); deviceAdapter.addDevice(bluetoothDevice); deviceAdapter.notifyDataSetChanged(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan_device); BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); if (bluetoothAdapter == null) { Toast.makeText(this, "當(dāng)前設(shè)備不支持藍(lán)牙", Toast.LENGTH_SHORT).show(); finish(); } initView(); registerDiscoveryReceiver(); startScan(); } @Override protected void onDestroy() { super.onDestroy(); handler.removeCallbacksAndMessages(null); unregisterReceiver(discoveryReceiver); if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } } private void initView() { ListView lv_deviceList = (ListView) findViewById(R.id.lv_deviceList); deviceAdapter = new DeviceAdapter(this); lv_deviceList.setAdapter(deviceAdapter); } private void registerDiscoveryReceiver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); registerReceiver(discoveryReceiver, intentFilter); } private void startScan() { if (!bluetoothAdapter.isEnabled()) { if (bluetoothAdapter.enable()) { handler.postDelayed(new Runnable() { @Override public void run() { scanDevice(); } }, 1500); } else { Toast.makeText(this, "請(qǐng)求藍(lán)牙權(quán)限被拒絕,請(qǐng)授權(quán)", Toast.LENGTH_SHORT).show(); } } else { scanDevice(); } } private void scanDevice() { if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } bluetoothAdapter.startDiscovery(); } private void showLoadingDialog(String message) { if (loadingDialog == null) { loadingDialog = new LoadingDialog(this); } loadingDialog.show(message, true, false); } private void hideLoadingDialog() { if (loadingDialog != null) { loadingDialog.dismiss(); } } }
此外,還可以通過(guò)利用反射來(lái)調(diào)用系統(tǒng)API,從而與支持藍(lán)牙A2DP協(xié)議的藍(lán)牙音響連接上,不過(guò)因?yàn)槲抑挥幸徊坎凰銍?yán)格意義上的藍(lán)牙音響來(lái)做測(cè)試,所以這個(gè)功能并不確定是否適用于大多數(shù)藍(lán)牙設(shè)備
/** * 作者:葉應(yīng)是葉 * 時(shí)間:2017/9/8 20:02 * 描述: */ public class ConnectA2dpActivity extends AppCompatActivity { private DeviceAdapter deviceAdapter; private BluetoothAdapter bluetoothAdapter; private Handler handler = new Handler(); private BluetoothA2dp bluetoothA2dp; private LoadingDialog loadingDialog; private final String TAG = "ConnectA2dpActivity"; private BroadcastReceiver a2dpReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: int connectState = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED); if (connectState == BluetoothA2dp.STATE_DISCONNECTED) { Toast.makeText(ConnectA2dpActivity.this, "已斷開(kāi)連接", Toast.LENGTH_SHORT).show(); } else if (connectState == BluetoothA2dp.STATE_CONNECTED) { Toast.makeText(ConnectA2dpActivity.this, "已連接", Toast.LENGTH_SHORT).show(); } break; case BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED: int playState = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_NOT_PLAYING); if (playState == BluetoothA2dp.STATE_PLAYING) { Toast.makeText(ConnectA2dpActivity.this, "處于播放狀態(tài)", Toast.LENGTH_SHORT).show(); } else if (playState == BluetoothA2dp.STATE_NOT_PLAYING) { Toast.makeText(ConnectA2dpActivity.this, "未在播放", Toast.LENGTH_SHORT).show(); } break; } } }; private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case BluetoothAdapter.ACTION_DISCOVERY_STARTED: showLoadingDialog("正在搜索藍(lán)牙設(shè)備,搜索時(shí)間大約一分鐘"); break; case BluetoothAdapter.ACTION_DISCOVERY_FINISHED: Toast.makeText(ConnectA2dpActivity.this, "搜索藍(lán)牙設(shè)備結(jié)束", Toast.LENGTH_SHORT).show(); hideLoadingDialog(); break; case BluetoothDevice.ACTION_FOUND: BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); deviceAdapter.addDevice(bluetoothDevice); deviceAdapter.notifyDataSetChanged(); break; case BluetoothDevice.ACTION_BOND_STATE_CHANGED: int status = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); if (status == BluetoothDevice.BOND_BONDED) { Toast.makeText(ConnectA2dpActivity.this, "已連接", Toast.LENGTH_SHORT).show(); } else if (status == BluetoothDevice.BOND_NONE) { Toast.makeText(ConnectA2dpActivity.this, "未連接", Toast.LENGTH_SHORT).show(); } hideLoadingDialog(); break; } } }; private BluetoothProfile.ServiceListener profileServiceListener = new BluetoothProfile.ServiceListener() { @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.A2DP) { Toast.makeText(ConnectA2dpActivity.this, "onServiceDisconnected", Toast.LENGTH_SHORT).show(); bluetoothA2dp = null; } } @Override public void onServiceConnected(int profile, final BluetoothProfile proxy) { if (profile == BluetoothProfile.A2DP) { Toast.makeText(ConnectA2dpActivity.this, "onServiceConnected", Toast.LENGTH_SHORT).show(); bluetoothA2dp = (BluetoothA2dp) proxy; } } }; private AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { BluetoothDevice device = deviceAdapter.getDevice(position); if (device.getBondState() == BluetoothDevice.BOND_BONDED) { Toast.makeText(ConnectA2dpActivity.this, "已連接該設(shè)備", Toast.LENGTH_SHORT).show(); return; } showLoadingDialog("正在連接"); connectA2dp(device); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_connect_a2dp); BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); if (bluetoothAdapter == null || !getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(ConnectA2dpActivity.this, "當(dāng)前設(shè)備不支持藍(lán)牙", Toast.LENGTH_SHORT).show(); finish(); } bluetoothAdapter.getProfileProxy(this, profileServiceListener, BluetoothProfile.A2DP); initView(); registerDiscoveryReceiver(); registerA2dpReceiver(); startScan(); } @Override protected void onDestroy() { super.onDestroy(); handler.removeCallbacksAndMessages(null); unregisterReceiver(a2dpReceiver); unregisterReceiver(discoveryReceiver); if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } } private void initView() { ListView lv_deviceList = (ListView) findViewById(R.id.lv_deviceList); deviceAdapter = new DeviceAdapter(this); lv_deviceList.setAdapter(deviceAdapter); lv_deviceList.setOnItemClickListener(itemClickListener); } private void registerDiscoveryReceiver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); registerReceiver(discoveryReceiver, intentFilter); } private void registerA2dpReceiver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED); registerReceiver(a2dpReceiver, intentFilter); } private void startScan() { if (!bluetoothAdapter.isEnabled()) { if (bluetoothAdapter.enable()) { handler.postDelayed(new Runnable() { @Override public void run() { scanDevice(); } }, 1500); } else { Toast.makeText(ConnectA2dpActivity.this, "請(qǐng)求藍(lán)牙權(quán)限被拒絕", Toast.LENGTH_SHORT).show(); } } else { scanDevice(); } } private void scanDevice() { if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } bluetoothAdapter.startDiscovery(); } public void setPriority(BluetoothDevice device, int priority) { try { Method connectMethod = BluetoothA2dp.class.getMethod("setPriority", BluetoothDevice.class, int.class); connectMethod.invoke(bluetoothA2dp, device, priority); } catch (Exception e) { e.printStackTrace(); } } private void connectA2dp(BluetoothDevice bluetoothDevice) { if (bluetoothA2dp == null || bluetoothDevice == null) { return; } setPriority(bluetoothDevice, 100); try { Method connectMethod = BluetoothA2dp.class.getMethod("connect", BluetoothDevice.class); connectMethod.invoke(bluetoothA2dp, bluetoothDevice); } catch (Exception e) { e.printStackTrace(); } } private void showLoadingDialog(String message) { if (loadingDialog == null) { loadingDialog = new LoadingDialog(this); } loadingDialog.show(message, true, false); } private void hideLoadingDialog() { if (loadingDialog != null) { loadingDialog.dismiss(); } } }
這里給出源代碼供大家參考:BluetoothDemo
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android遞歸壓縮上傳多張圖片到七牛的實(shí)例代碼
本篇文章主要介紹了android遞歸壓縮上傳多張圖片到七牛的實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Flutter Navigator路由傳參的實(shí)現(xiàn)
本文主要介紹了Flutter Navigator路由傳參的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04深入android Unable to resolve target ''android-XX''詳解
本篇文章是對(duì)android Unable to resolve target 'android-XX'錯(cuò)誤的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06詳解Android JetPack之LiveData的工作原理
這篇文章主要介紹了詳解Android JetPack之LiveData的工作原理,幫助大家更好的理解和學(xué)習(xí)使用Android開(kāi)發(fā),感興趣的朋友可以了解下2021-03-03一次OOM問(wèn)題排查過(guò)程實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了一次OOM問(wèn)題排查過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05Android應(yīng)用開(kāi)發(fā)工程目錄作用介紹
這篇文章主要介紹了Android應(yīng)用開(kāi)發(fā)工程目錄作用介紹,本文對(duì)Android項(xiàng)目中的每個(gè)目錄的作用作了總結(jié),需要的朋友可以參考下2014-10-10