From b5d1e0958039da485a0d23b4ac5899ffe6370e5e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 26 Feb 2013 16:37:03 +0100 Subject: [PATCH] Bluetooth support for android 2.2+ added --- src/org/linphone/BluetoothManager.java | 49 +++++++++--- src/org/linphone/LinphoneManager.java | 105 ++++++++++++++++--------- 2 files changed, 105 insertions(+), 49 deletions(-) diff --git a/src/org/linphone/BluetoothManager.java b/src/org/linphone/BluetoothManager.java index 5e6287442..0e0d8885c 100644 --- a/src/org/linphone/BluetoothManager.java +++ b/src/org/linphone/BluetoothManager.java @@ -2,39 +2,68 @@ package org.linphone; import org.linphone.mediastream.Log; -import android.bluetooth.BluetoothAdapter; +import android.annotation.TargetApi; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.media.AudioManager; +import android.os.Build; +@TargetApi(Build.VERSION_CODES.HONEYCOMB) public class BluetoothManager extends BroadcastReceiver { - public void onReceive(Context context, Intent intent) { + @SuppressWarnings("deprecation") + public void onReceive(Context context, Intent intent) { boolean routeToBT = context.getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available); if (!routeToBT) return; String action = intent.getAction(); LinphoneManager lm = LinphoneManager.getInstance(); - + + String actionScoConnected = AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED; if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { Log.e("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED" ); if (lm != null) { - lm.uninitBluetooth(); + lm.isBluetoothScoConnected = false; + lm.scoDisconnected(); lm.routeAudioToReceiver(); } - } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { + } + else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { Log.e("Bluetooth Received Event" + " ACTION_ACL_CONNECTED" ); if (lm != null) { - lm.routeToBluetoothIfAvailable(); + lm.isBluetoothScoConnected = true; + lm.scoConnected(); } - } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { - Log.e("Bluetooth state changed!"); - if (lm != null) { + } + else if (actionScoConnected.equals(action)) { + int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0); + Log.e("Bluetooth sco state changed : " + state); + if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { + if (lm != null) { + lm.isBluetoothScoConnected = true; + lm.scoConnected(); + } + } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { + if (lm != null) { + lm.isBluetoothScoConnected = false; + lm.scoDisconnected(); + lm.routeAudioToReceiver(); + } + } + } + //Using real value instead of constant because not available before sdk 11 + else if ("android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED".equals(action)) { //BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED + int currentConnState = intent.getIntExtra("android.bluetooth.adapter.extra.CONNECTION_STATE", //BluetoothAdapter.EXTRA_CONNECTION_STATE + 0); //BluetoothAdapter.STATE_DISCONNECTED + Log.e("Bluetooth state changed: " + currentConnState); + if (lm != null && currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED + lm.isBluetoothScoConnected = true; lm.startBluetooth(); } - } + } } } diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 16a26d6d7..65148120f 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -150,6 +150,8 @@ public final class LinphoneManager implements LinphoneCoreListener { private BluetoothAdapter mBluetoothAdapter; private BluetoothHeadset mBluetoothHeadset; private BluetoothProfile.ServiceListener mProfileListener; + private BroadcastReceiver bluetoothReiceiver = new BluetoothManager(); + public boolean isBluetoothScoConnected; private static List simpleListeners = new ArrayList(); public static void addListener(LinphoneSimpleListener listener) { @@ -204,14 +206,14 @@ public final class LinphoneManager implements LinphoneCoreListener { boolean routeToBT = mServiceContext.getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available); if (!routeToBT || (routeToBT && !routeToBluetoothIfAvailable())) { mLc.enableSpeaker(false); - uninitBluetooth(); + scoDisconnected(); } else { Log.d("Routing audio to bluetooth headset"); routeToBluetoothEnabled = true; } } else { mLc.enableSpeaker(true); - uninitBluetooth(); + scoDisconnected(); } for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) { @@ -243,27 +245,40 @@ public final class LinphoneManager implements LinphoneCoreListener { @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void startBluetooth() { mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30) && mBluetoothAdapter.isEnabled()) { - mProfileListener = new BluetoothProfile.ServiceListener() { - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HEADSET) { - mBluetoothHeadset = (BluetoothHeadset) proxy; - Log.d("Bluetooth headset connected"); - routeToBluetoothIfAvailable(); - } - } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HEADSET) { - mBluetoothHeadset = null; - Log.d("Bluetooth headset disconnected"); - routeAudioToReceiver(); - } - } - }; - mBluetoothAdapter.getProfileProxy(mServiceContext, mProfileListener, BluetoothProfile.HEADSET); - } else { + if (mBluetoothAdapter.isEnabled()) { + if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { + mProfileListener = new BluetoothProfile.ServiceListener() { + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (profile == BluetoothProfile.HEADSET) { + mBluetoothHeadset = (BluetoothHeadset) proxy; + Log.d("Bluetooth headset connected"); + routeToBluetoothIfAvailable(); + } + } + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void onServiceDisconnected(int profile) { + if (profile == BluetoothProfile.HEADSET) { + mBluetoothHeadset = null; + Log.d("Bluetooth headset disconnected"); + routeAudioToReceiver(); + } + } + }; + mBluetoothAdapter.getProfileProxy(mServiceContext, mProfileListener, BluetoothProfile.HEADSET); + } else { + @SuppressWarnings("deprecation") + String actionScoConnected = AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED; + Intent currentValue = mServiceContext.registerReceiver(bluetoothReiceiver, new IntentFilter(actionScoConnected)); + int state = currentValue == null ? 0 : currentValue.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0); + if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { + isBluetoothScoConnected = true; + scoConnected(); + } + } + } + else { + scoDisconnected(); routeAudioToReceiver(); } } @@ -271,30 +286,42 @@ public final class LinphoneManager implements LinphoneCoreListener { @TargetApi(Build.VERSION_CODES.HONEYCOMB) public boolean routeToBluetoothIfAvailable() { BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30) && mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) { + if (mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) { mAudioManager.setBluetoothScoOn(true); mAudioManager.startBluetoothSco(); - - boolean connected = false; - if (mBluetoothHeadset != null) { - List devices = mBluetoothHeadset.getConnectedDevices(); - for (final BluetoothDevice dev : devices) { - connected |= mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED; - } - } - if (!connected) { - Log.d("No bluetooth device available"); - uninitBluetooth(); + if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { + boolean connected = false; + if (mBluetoothHeadset != null) { + List devices = mBluetoothHeadset.getConnectedDevices(); + for (final BluetoothDevice dev : devices) { + connected |= mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED; + } + } + + if (!connected) { + Log.d("No bluetooth device available"); + scoDisconnected(); + } + return connected; + } else { + return isBluetoothScoConnected; } - return connected; } + return false; } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void uninitBluetooth() { - if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30) && mAudioManager != null) { + public void scoConnected() { + Log.e("Bluetooth sco connected!"); + mAudioManager.setMode(AudioManager.MODE_IN_CALL); + routeToBluetoothIfAvailable(); + } + + public void scoDisconnected() { + Log.e("Bluetooth sco disconnected!"); + if (mAudioManager != null) { + mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.stopBluetoothSco(); mAudioManager.setBluetoothScoOn(false); }