Android實現主動連線藍芽耳機
阿新 • • 發佈:2019-02-08
原網址:http://www.cnblogs.com/tt2015-sz/p/5616607.html
private static final String TAG = "BluetoothA2DPTest"; private BroadcastReceiver mBroadcastReceiver; private BluetoothA2dp mBluetoothA2dp; private BluetoothAdapter mBluetoothAdapter; private String DEVICE_NAME = "KUWO_K1"; private BluetoothDevice mBluetoothDevice;private MediaPlayer mMediaPlayer; private void initParameters(){ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if(mBluetoothAdapter == null){ Log.e(TAG,"have no bluetooth adapter."); return; } if(!mBluetoothAdapter.isEnabled()){ mBluetoothAdapter.enable(); }else{ //開始搜尋附近藍芽 startDiscovery(); //繫結BluetoothA2DP,獲得service getBluetoothA2DP(); } //監聽廣播 mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { BluetoothDevice device;switch (intent.getAction()) { case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: //<editor-fold> switch (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) { case BluetoothA2dp.STATE_CONNECTING: device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i(TAG, "device: " + device.getName() +" connecting"); break; case BluetoothA2dp.STATE_CONNECTED: device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i(TAG, "device: " + device.getName() +" connected"); //連線成功,開始播放 startPlay(); break; case BluetoothA2dp.STATE_DISCONNECTING: device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i(TAG, "device: " + device.getName() +" disconnecting"); break; case BluetoothA2dp.STATE_DISCONNECTED: device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i(TAG, "device: " + device.getName() +" disconnected"); // setResultPASS(); break; default: break; } //</editor-fold> break; case BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED: //<editor-fold> int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1); switch (state) { case BluetoothA2dp.STATE_PLAYING: Log.i(TAG, "state: playing."); break; case BluetoothA2dp.STATE_NOT_PLAYING: Log.i(TAG, "state: not playing"); break; default: Log.i(TAG, "state: unkown"); break; } //</editor-fold> break; case BluetoothDevice.ACTION_FOUND: //<editor-fold> device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int deviceClassType = device.getBluetoothClass().getDeviceClass(); //找到指定的藍芽裝置 if ((deviceClassType == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET || deviceClassType == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) && device.getName().equals(DEVICE_NAME)) { Log.i(TAG, "Found device:" + device.getName()); mBluetoothDevice = device; //start bond,開始配對 createBond(); } //</editor-fold> break; case BluetoothDevice.ACTION_BOND_STATE_CHANGED: //<editor-fold> int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,BluetoothDevice.BOND_NONE); device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (bondState){ case BluetoothDevice.BOND_BONDED: //配對成功 Log.i(TAG,"Device:"+device.getName()+" bonded."); mBluetoothAdapter.cancelDiscovery(); //取消搜尋 connect(); //連線藍芽裝置 break; case BluetoothDevice.BOND_BONDING: Log.i(TAG,"Device:"+device.getName()+" bonding."); break; case BluetoothDevice.BOND_NONE: Log.i(TAG,"Device:"+device.getName()+" not bonded."); //不知道是藍芽耳機的關係還是什麼原因,經常配對不成功 //配對不成功的話,重新嘗試配對 createBond(); break; default: break; } //</editor-fold> break; case BluetoothAdapter.ACTION_STATE_CHANGED: //<editor-fold> state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); switch (state) { case BluetoothAdapter.STATE_TURNING_ON: Log.i(TAG, "BluetoothAdapter is turning on."); break; case BluetoothAdapter.STATE_ON: Log.i(TAG, "BluetoothAdapter is on."); //藍芽已開啟,開始搜尋並連線service startDiscovery(); getBluetoothA2DP(); break; case BluetoothAdapter.STATE_TURNING_OFF: Log.i(TAG, "BluetoothAdapter is turning off."); break; case BluetoothAdapter.STATE_OFF: Log.i(TAG, "BluetoothAdapter is off."); break; } //</editor-fold> break; default: break; } } }; IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); registerReceiver(mBroadcastReceiver, filter); } private void startDiscovery(){ Log.i(TAG,"mBluetoothAdapter startDiscovery."); if(mBluetoothAdapter!=null && mBluetoothAdapter.isEnabled() && !mBluetoothAdapter.isDiscovering()){ mBluetoothAdapter.startDiscovery(); } } private void getBluetoothA2DP(){ Log.i(TAG,"getBluetoothA2DP"); if(mBluetoothAdapter == null){ return; } if(mBluetoothA2dp != null){ return; } mBluetoothAdapter.getProfileProxy(this, new BluetoothProfile.ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if(profile == BluetoothProfile.A2DP){ //Service連線成功,獲得BluetoothA2DP mBluetoothA2dp = (BluetoothA2dp)proxy; } } @Override public void onServiceDisconnected(int profile) { } },BluetoothProfile.A2DP); } private void createBond() { Log.i(TAG, "createBond"); mBluetoothDevice.createBond(); } //connect和disconnect都是hide方法,普通應用只能通過反射機制來呼叫該方法 private void connect(){ Log.i(TAG,"connect"); if(mBluetoothA2dp == null){ return; } if(mBluetoothDevice == null){ return; } try { Method connect = mBluetoothA2dp.getClass().getDeclaredMethod("connect", BluetoothDevice.class); connect.setAccessible(true); connect.invoke(mBluetoothA2dp,mBluetoothDevice); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { Log.e(TAG,"connect exception:"+e); e.printStackTrace(); } } private void startPlay(){ Log.i(TAG, "startPlay"); AudioManager mAudioManager= (AudioManager)getSystemService(AUDIO_SERVICE); if(mAudioManager!=null){ int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,maxVolume,0); } Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+ R.raw.speaker_test); mMediaPlayer = new MediaPlayer(); mMediaPlayer.reset(); try { mMediaPlayer.setDataSource(this,uri); mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { //播放完成,可以考慮斷開連線 disconnect(); } }); mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Log.e(TAG, "Playback error."); return false; } }); mMediaPlayer.prepare(); mMediaPlayer.start(); } catch(IllegalStateException|IOException e) { Log.e(TAG, "Exception: prepare or start mediaplayer"); setResultFAIL(); } } //程式退出前,要release播放器 private void stopPlay(){ Log.i(TAG,"stopPlay"); if(mMediaPlayer!=null){ mMediaPlayer.stop(); mMediaPlayer.release(); mMediaPlayer = null; } } private void disconnect(){ Log.i(TAG,"disconnect"); if(mBluetoothA2dp == null){ return; } if(mBluetoothDevice == null){ return; } try { Method disconnect = mBluetoothA2dp.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class); disconnect.setAccessible(true); disconnect.invoke(mBluetoothA2dp,mBluetoothDevice); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { Log.e(TAG,"connect exception:"+e); e.printStackTrace(); } } //取消配對 private void unPairAllDevices(){ Log.i(TAG,"unPairAllDevices"); for(BluetoothDevice device:mBluetoothAdapter.getBondedDevices()){ try { Method removeBond = device.getClass().getDeclaredMethod("removeBond"); removeBond.invoke(device); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } //注意,在程式退出之前(OnDestroy),需要斷開藍芽相關的Service //否則,程式會報異常:service leaks private void disableAdapter(){ Log.i(TAG,"disableAdapter"); if(mBluetoothAdapter == null){ return; } if(mBluetoothAdapter.isDiscovering()){ mBluetoothAdapter.cancelDiscovery(); } //關閉ProfileProxy,也就是斷開service連線 mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP,mBluetoothA2dp); if(mBluetoothAdapter.isEnabled()){ boolean ret = mBluetoothAdapter.disable(); Log.i(TAG,"disable adapter:"+ret); } }