Started incall menu to choose audio route between receiver, speaker and bluetooth (if connected and available)

This commit is contained in:
Sylvain Berfini 2013-03-25 15:49:10 +01:00
parent afe863a235
commit a8f2b928c0
49 changed files with 448 additions and 93 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -3,9 +3,9 @@
<item android:state_pressed="true" <item android:state_pressed="true"
android:drawable="@drawable/options_over" /> android:drawable="@drawable/options_over" />
<item android:state_enabled="false" <item android:state_enabled="false"
android:drawable="@drawable/options_disabled" /> android:drawable="@drawable/options_disabled" />
<item android:state_selected="true" <item android:state_selected="true"
android:drawable="@drawable/options_selected" /> android:drawable="@drawable/options_selected" />
<item <item
android:drawable="@drawable/options_default" /> android:drawable="@drawable/options_default" />
</selector> </selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/route_bluetooth_off_over" />
<item android:state_enabled="false"
android:drawable="@drawable/route_bluetooth_off_disabled" />
<item
android:drawable="@drawable/route_bluetooth_off_default" />
</selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/route_bluetooth_off_over" />
<item android:state_enabled="false"
android:drawable="@drawable/route_bluetooth_off_disabled" />
<item
android:drawable="@drawable/route_bluetooth_on_default" />
</selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/route_phone_off_over" />
<item android:state_enabled="false"
android:drawable="@drawable/route_phone_off_disabled" />
<item
android:drawable="@drawable/route_phone_off_default" />
</selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/route_phone_off_over" />
<item android:state_enabled="false"
android:drawable="@drawable/route_phone_off_disabled" />
<item
android:drawable="@drawable/route_phone_on_default" />
</selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/route_speaker_off_over" />
<item android:state_enabled="false"
android:drawable="@drawable/route_speaker_off_disabled" />
<item
android:drawable="@drawable/route_speaker_off_default" />
</selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/route_speaker_off_over" />
<item android:state_enabled="false"
android:drawable="@drawable/route_speaker_off_disabled" />
<item
android:drawable="@drawable/route_speaker_on_default" />
</selector>

12
res/drawable/routes.xml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/routes_over" />
<item android:state_selected="true"
android:drawable="@drawable/routes_selected" />
<item android:state_enabled="false"
android:drawable="@drawable/routes_disabled" />
<item
android:drawable="@drawable/routes_default" />
</selector>

View file

@ -55,10 +55,10 @@
<LinearLayout <LinearLayout
android:id="@+id/menu" android:id="@+id/menu"
android:visibility="gone"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:visibility="gone"
android:gravity="bottom" android:gravity="bottom"
android:orientation="horizontal" > android:orientation="horizontal" >
@ -126,6 +126,59 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
<LinearLayout
android:id="@+id/routesLayout"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/routeBluetooth"
android:visibility="invisible"
android:background="@drawable/route_bluetooth_off"
android:text="@string/button_bluetooth"
android:gravity="center"
android:paddingTop="35dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/routeReceiver"
android:visibility="invisible"
android:background="@drawable/route_receiver_off"
android:text="@string/button_receiver"
android:gravity="center"
android:paddingTop="35dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/routeSpeaker"
android:visibility="invisible"
android:background="@drawable/route_speaker_off"
android:text="@string/button_speaker"
android:gravity="center"
android:paddingTop="35dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/audioRoute"
android:background="@drawable/routes"
android:text="@string/button_route"
android:gravity="center"
android:paddingTop="30dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -58,31 +58,87 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:visibility="gone"
android:gravity="right" android:gravity="right"
android:orientation="vertical" > android:orientation="vertical">
<TextView <LinearLayout
android:id="@+id/transfer" android:layout_width="wrap_content"
android:background="@drawable/options_transfer" android:layout_height="wrap_content"
android:text="@string/button_transfer" android:gravity="right|bottom"
android:gravity="center" android:orientation="horizontal">
android:paddingTop="40dp"
android:visibility="invisible"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView <LinearLayout
android:id="@+id/addCall" android:layout_width="wrap_content"
android:background="@drawable/options_add_call_alt" android:layout_height="wrap_content"
android:text="@string/button_add_call" android:gravity="right|bottom"
android:gravity="center" android:orientation="vertical">
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color" <TextView
android:layout_width="wrap_content" android:id="@+id/routeBluetooth"
android:layout_height="wrap_content" android:visibility="invisible"
android:visibility="invisible" /> android:background="@drawable/route_bluetooth_off"
android:text="@string/button_bluetooth"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/routeReceiver"
android:visibility="invisible"
android:background="@drawable/route_receiver_off"
android:text="@string/button_receiver"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/routeSpeaker"
android:visibility="invisible"
android:background="@drawable/route_speaker_off"
android:text="@string/button_speaker"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right|bottom"
android:orientation="vertical">
<TextView
android:id="@+id/transfer"
android:background="@drawable/options_transfer"
android:text="@string/button_transfer"
android:gravity="center"
android:paddingTop="40dp"
android:visibility="invisible"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/addCall"
android:background="@drawable/options_add_call_alt"
android:text="@string/button_add_call"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -122,6 +178,18 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
<TextView
android:id="@+id/audioRoute"
android:visibility="gone"
android:background="@drawable/routes"
android:text="@string/button_route"
android:gravity="center"
android:paddingTop="45dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView <TextView
android:id="@+id/options" android:id="@+id/options"
android:background="@drawable/options" android:background="@drawable/options"

View file

@ -55,11 +55,11 @@
<LinearLayout <LinearLayout
android:id="@+id/menu" android:id="@+id/menu"
android:visibility="invisible"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:gravity="right" android:gravity="right"
android:visibility="gone"
android:orientation="vertical" > android:orientation="vertical" >
<LinearLayout <LinearLayout
@ -71,19 +71,31 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="invisible" android:visibility="invisible"
android:layout_weight="0.25"/> android:layout_weight="0.5"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_weight="0.5"/>
<TextView <TextView
android:id="@+id/transfer" android:id="@+id/routeBluetooth"
android:background="@drawable/options_transfer" android:visibility="invisible"
android:text="@string/button_transfer" android:background="@drawable/route_bluetooth_off"
android:text="@string/button_bluetooth"
android:gravity="center" android:gravity="center"
android:paddingTop="40dp" android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color" android:textColor="@drawable/text_incall_button_color"
android:visibility="invisible"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0.75" /> android:layout_weight="0.5" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_weight="0.5"/>
</LinearLayout> </LinearLayout>
@ -96,19 +108,80 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="invisible" android:visibility="invisible"
android:layout_weight="0.25"/> android:layout_weight="0.5"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_weight="0.5"/>
<TextView <TextView
android:id="@+id/routeReceiver"
android:visibility="invisible"
android:background="@drawable/route_receiver_off"
android:text="@string/button_receiver"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
<TextView
android:id="@+id/transfer"
android:visibility="invisible"
android:background="@drawable/options_transfer"
android:text="@string/button_transfer"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_weight="0.5"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_weight="0.5"/>
<TextView
android:id="@+id/routeSpeaker"
android:visibility="invisible"
android:background="@drawable/route_speaker_off"
android:text="@string/button_speaker"
android:gravity="center"
android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
<TextView
android:id="@+id/addCall" android:id="@+id/addCall"
android:visibility="invisible"
android:background="@drawable/options_add_call_alt" android:background="@drawable/options_add_call_alt"
android:text="@string/button_add_call" android:text="@string/button_add_call"
android:gravity="center" android:gravity="center"
android:paddingTop="40dp" android:paddingTop="40dp"
android:textColor="@drawable/text_incall_button_color" android:textColor="@drawable/text_incall_button_color"
android:visibility="invisible"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0.75" /> android:layout_weight="0.5" />
</LinearLayout> </LinearLayout>
@ -150,6 +223,18 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
<TextView
android:id="@+id/audioRoute"
android:background="@drawable/routes"
android:text="@string/button_route"
android:gravity="center"
android:paddingTop="45dp"
android:textColor="@drawable/text_incall_button_color"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView <TextView
android:id="@+id/options" android:id="@+id/options"
android:background="@drawable/options" android:background="@drawable/options"

View file

@ -315,6 +315,9 @@
<string name="button_video">Vidéo</string> <string name="button_video">Vidéo</string>
<string name="button_micro">Micro</string> <string name="button_micro">Micro</string>
<string name="button_speaker">HP</string> <string name="button_speaker">HP</string>
<string name="button_route">Route</string>
<string name="button_receiver">Ecouteur</string>
<string name="button_bluetooth">Bluetooth</string>
<string name="button_options">Options</string> <string name="button_options">Options</string>
<string name="button_send_message">Envoyer</string> <string name="button_send_message">Envoyer</string>

View file

@ -55,8 +55,6 @@
<bool name="hash_images_as_name_before_upload">true</bool> <bool name="hash_images_as_name_before_upload">true</bool>
<bool name="route_audio_to_bluetooth_if_available">true</bool>
<bool name="disable_every_log">false</bool> <bool name="disable_every_log">false</bool>
<bool name="disable_all_security_features_for_markets">false</bool> <!-- Disable TLS/SRTP/ZRTP --> <bool name="disable_all_security_features_for_markets">false</bool> <!-- Disable TLS/SRTP/ZRTP -->
<bool name="disable_all_patented_codecs_for_markets">false</bool> <!-- Disable MPEG4/H264 --> <bool name="disable_all_patented_codecs_for_markets">false</bool> <!-- Disable MPEG4/H264 -->

View file

@ -363,6 +363,9 @@
<string name="button_video">Video</string> <string name="button_video">Video</string>
<string name="button_micro">Micro</string> <string name="button_micro">Micro</string>
<string name="button_speaker">Speaker</string> <string name="button_speaker">Speaker</string>
<string name="button_route">Route</string>
<string name="button_receiver">Receiver</string>
<string name="button_bluetooth">Bluetooth</string>
<string name="button_options">Options</string> <string name="button_options">Options</string>
<string name="button_send_message">Send</string> <string name="button_send_message">Send</string>

View file

@ -14,10 +14,6 @@ import android.os.Build;
public class BluetoothManager extends BroadcastReceiver { public class BluetoothManager extends BroadcastReceiver {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public void onReceive(Context context, Intent intent) { 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(); String action = intent.getAction();
LinphoneManager lm = LinphoneManager.getInstance(); LinphoneManager lm = LinphoneManager.getInstance();
@ -26,7 +22,6 @@ public class BluetoothManager extends BroadcastReceiver {
Log.e("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED" ); Log.e("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED" );
if (lm != null) { if (lm != null) {
lm.isBluetoothScoConnected = false;
lm.scoDisconnected(); lm.scoDisconnected();
lm.routeAudioToReceiver(); lm.routeAudioToReceiver();
} }
@ -35,7 +30,6 @@ public class BluetoothManager extends BroadcastReceiver {
Log.e("Bluetooth Received Event" + " ACTION_ACL_CONNECTED" ); Log.e("Bluetooth Received Event" + " ACTION_ACL_CONNECTED" );
if (lm != null) { if (lm != null) {
lm.isBluetoothScoConnected = true;
lm.scoConnected(); lm.scoConnected();
} }
} }
@ -44,12 +38,10 @@ public class BluetoothManager extends BroadcastReceiver {
Log.e("Bluetooth sco state changed : " + state); Log.e("Bluetooth sco state changed : " + state);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
if (lm != null) { if (lm != null) {
lm.isBluetoothScoConnected = true;
lm.scoConnected(); lm.scoConnected();
} }
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
if (lm != null) { if (lm != null) {
lm.isBluetoothScoConnected = false;
lm.scoDisconnected(); lm.scoDisconnected();
lm.routeAudioToReceiver(); lm.routeAudioToReceiver();
} }
@ -61,7 +53,6 @@ public class BluetoothManager extends BroadcastReceiver {
0); //BluetoothAdapter.STATE_DISCONNECTED 0); //BluetoothAdapter.STATE_DISCONNECTED
Log.e("Bluetooth state changed: " + currentConnState); Log.e("Bluetooth state changed: " + currentConnState);
if (lm != null && currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED if (lm != null && currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED
lm.isBluetoothScoConnected = true;
lm.startBluetooth(); lm.startBluetooth();
} }
} }

View file

@ -87,6 +87,8 @@ public class InCallActivity extends FragmentActivity implements
private Runnable mControls; private Runnable mControls;
private ImageView pause, hangUp, dialer, switchCamera, conference; private ImageView pause, hangUp, dialer, switchCamera, conference;
private TextView video, micro, speaker, options, addCall, transfer; private TextView video, micro, speaker, options, addCall, transfer;
private TextView audioRoute, routeSpeaker, routeReceiver, routeBluetooth;
private LinearLayout routeLayout;
private StatusFragment status; private StatusFragment status;
private AudioCallFragment audioCallFragment; private AudioCallFragment audioCallFragment;
private VideoCallFragment videoCallFragment; private VideoCallFragment videoCallFragment;
@ -166,10 +168,6 @@ public class InCallActivity extends FragmentActivity implements
callFragment.setArguments(getIntent().getExtras()); callFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, callFragment).commitAllowingStateLoss(); getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, callFragment).commitAllowingStateLoss();
} }
boolean routeToBT = getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available);
if (routeToBT && LinphoneManager.isInstanciated() && !isSpeakerEnabled)
LinphoneManager.getInstance().routeToBluetoothIfAvailable();
} }
@Override @Override
@ -219,6 +217,20 @@ public class InCallActivity extends FragmentActivity implements
dialer.setEnabled(false); dialer.setEnabled(false);
numpad = (Numpad) findViewById(R.id.numpad); numpad = (Numpad) findViewById(R.id.numpad);
try {
routeLayout = (LinearLayout) findViewById(R.id.routesLayout);
audioRoute = (TextView) findViewById(R.id.audioRoute);
audioRoute.setOnClickListener(this);
routeSpeaker = (TextView) findViewById(R.id.routeSpeaker);
routeSpeaker.setOnClickListener(this);
routeReceiver = (TextView) findViewById(R.id.routeReceiver);
routeReceiver.setOnClickListener(this);
routeBluetooth = (TextView) findViewById(R.id.routeBluetooth);
routeBluetooth.setOnClickListener(this);
} catch (NullPointerException npe) {
Log.e("Audio routes menu disabled on tablets for now");
}
switchCamera = (ImageView) findViewById(R.id.switchCamera); switchCamera = (ImageView) findViewById(R.id.switchCamera);
switchCamera.setOnClickListener(this); switchCamera.setOnClickListener(this);
@ -255,10 +267,39 @@ public class InCallActivity extends FragmentActivity implements
} }
} }
if (isSpeakerEnabled) { if (LinphoneManager.getInstance().isBluetoothScoConnected) {
speaker.setBackgroundResource(R.drawable.speaker_on); try {
routeLayout.setVisibility(View.VISIBLE);
} catch (NullPointerException npe) {}
audioRoute.setVisibility(View.VISIBLE);
speaker.setVisibility(View.GONE);
} else { } else {
speaker.setBackgroundResource(R.drawable.speaker_off); try {
routeLayout.setVisibility(View.GONE);
} catch (NullPointerException npe) {}
audioRoute.setVisibility(View.GONE);
speaker.setVisibility(View.VISIBLE);
}
try {
if (isSpeakerEnabled) {
speaker.setBackgroundResource(R.drawable.speaker_on);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
} else {
speaker.setBackgroundResource(R.drawable.speaker_off);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
if (LinphoneManager.getInstance().isUsingBluetoothAudioRoute) {
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
} else {
routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
}
}
} catch (NullPointerException npe) {
Log.e("Audio routes menu disabled on tablets for now");
} }
if (isMicMuted) { if (isMicMuted) {
@ -361,6 +402,30 @@ public class InCallActivity extends FragmentActivity implements
else if (id == R.id.options) { else if (id == R.id.options) {
hideOrDisplayCallOptions(); hideOrDisplayCallOptions();
} }
else if (id == R.id.audioRoute) {
hideOrDisplayAudioRoutes();
}
else if (id == R.id.routeBluetooth) {
LinphoneManager.getInstance().routeAudioToBluetooth();
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
hideOrDisplayAudioRoutes();
}
else if (id == R.id.routeReceiver) {
LinphoneManager.getInstance().routeAudioToReceiver();
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
hideOrDisplayAudioRoutes();
}
else if (id == R.id.routeSpeaker) {
LinphoneManager.getInstance().routeAudioToSpeaker();
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
hideOrDisplayAudioRoutes();
}
else if (id == R.id.callStatus) { else if (id == R.id.callStatus) {
LinphoneCall call = (LinphoneCall) v.getTag(); LinphoneCall call = (LinphoneCall) v.getTag();
@ -483,10 +548,6 @@ public class InCallActivity extends FragmentActivity implements
} else { } else {
LinphoneManager.getInstance().routeAudioToReceiver(); LinphoneManager.getInstance().routeAudioToReceiver();
speaker.setBackgroundResource(R.drawable.speaker_off); speaker.setBackgroundResource(R.drawable.speaker_off);
boolean routeToBT = getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available);
if (!routeToBT)
LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled);
} }
} }
@ -878,6 +939,38 @@ public class InCallActivity extends FragmentActivity implements
addCall.startAnimation(animation); addCall.startAnimation(animation);
} }
private void hideOrDisplayAudioRoutes()
{
if (isSpeakerEnabled) {
speaker.setBackgroundResource(R.drawable.speaker_on);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
} else {
speaker.setBackgroundResource(R.drawable.speaker_off);
routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
if (LinphoneManager.getInstance().isUsingBluetoothAudioRoute) {
routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
} else {
routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
}
}
if (routeSpeaker.getVisibility() == View.VISIBLE) {
routeSpeaker.setVisibility(View.INVISIBLE);
routeBluetooth.setVisibility(View.INVISIBLE);
routeReceiver.setVisibility(View.INVISIBLE);
audioRoute.setSelected(false);
} else {
routeSpeaker.setVisibility(View.VISIBLE);
routeBluetooth.setVisibility(View.VISIBLE);
routeReceiver.setVisibility(View.VISIBLE);
audioRoute.setSelected(true);
}
}
private void hideOrDisplayCallOptions() { private void hideOrDisplayCallOptions() {
boolean isOrientationLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; boolean isOrientationLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
@ -895,6 +988,7 @@ public class InCallActivity extends FragmentActivity implements
hideAnimatedPortraitCallOptions(); hideAnimatedPortraitCallOptions();
} }
} }
options.setSelected(false);
} else { } else {
if (isAnimationDisabled) { if (isAnimationDisabled) {
if (isTransferAllowed) { if (isTransferAllowed) {
@ -909,6 +1003,7 @@ public class InCallActivity extends FragmentActivity implements
showAnimatedPortraitCallOptions(); showAnimatedPortraitCallOptions();
} }
} }
options.setSelected(true);
transfer.setEnabled(LinphoneManager.getLc().getCurrentCall() != null); transfer.setEnabled(LinphoneManager.getLc().getCurrentCall() != null);
} }
} }
@ -977,13 +1072,7 @@ public class InCallActivity extends FragmentActivity implements
switchVideo(isVideoEnabled, false); switchVideo(isVideoEnabled, false);
} }
boolean routeToBT = getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available); LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled);
if (routeToBT && LinphoneManager.isInstanciated() && !isSpeakerEnabled) {
LinphoneManager.getInstance().routeToBluetoothIfAvailable();
} else {
// The following should not be needed except some devices need it (e.g. Galaxy S).
LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled);
}
isMicMuted = LinphoneManager.getLc().isMicMuted(); isMicMuted = LinphoneManager.getLc().isMicMuted();
enableAndRefreshInCallActions(); enableAndRefreshInCallActions();

View file

@ -155,6 +155,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
private BluetoothProfile.ServiceListener mProfileListener; private BluetoothProfile.ServiceListener mProfileListener;
private BroadcastReceiver bluetoothReiceiver = new BluetoothManager(); private BroadcastReceiver bluetoothReiceiver = new BluetoothManager();
public boolean isBluetoothScoConnected; public boolean isBluetoothScoConnected;
public boolean isUsingBluetoothAudioRoute;
private static List<LinphoneSimpleListener> simpleListeners = new ArrayList<LinphoneSimpleListener>(); private static List<LinphoneSimpleListener> simpleListeners = new ArrayList<LinphoneSimpleListener>();
public static void addListener(LinphoneSimpleListener listener) { public static void addListener(LinphoneSimpleListener listener) {
@ -204,30 +205,27 @@ public final class LinphoneManager implements LinphoneCoreListener {
private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver(); private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver();
private void routeAudioToSpeakerHelper(boolean speakerOn) { private void routeAudioToSpeakerHelper(boolean speakerOn) {
boolean routeToBluetoothEnabled = false; isUsingBluetoothAudioRoute = false;
if (mAudioManager != null) {
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
}
if (!speakerOn) { if (!speakerOn) {
boolean routeToBT = mServiceContext.getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available); mLc.enableSpeaker(false);
if (!routeToBT || (routeToBT && !routeToBluetoothIfAvailable())) {
mLc.enableSpeaker(false);
scoDisconnected();
} else {
Log.d("Routing audio to bluetooth headset");
routeToBluetoothEnabled = true;
}
} else { } else {
mLc.enableSpeaker(true); mLc.enableSpeaker(true);
scoDisconnected();
} }
for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) { for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) {
listener.onAudioStateChanged(speakerOn ? AudioState.SPEAKER : (routeToBluetoothEnabled ? AudioState.BLUETOOTH : AudioState.EARPIECE)); listener.onAudioStateChanged(speakerOn ? AudioState.SPEAKER : AudioState.EARPIECE);
} }
} }
public void routeAudioToSpeaker() { public void routeAudioToSpeaker() {
routeAudioToSpeakerHelper(true); routeAudioToSpeakerHelper(true);
} }
public String getUserAgent() throws NameNotFoundException { public String getUserAgent() throws NameNotFoundException {
StringBuilder userAgent = new StringBuilder(); StringBuilder userAgent = new StringBuilder();
userAgent.append("LinphoneAndroid/" + mServiceContext.getPackageManager().getPackageInfo(mServiceContext.getPackageName(),0).versionCode); userAgent.append("LinphoneAndroid/" + mServiceContext.getPackageManager().getPackageInfo(mServiceContext.getPackageName(),0).versionCode);
@ -256,7 +254,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
if (profile == BluetoothProfile.HEADSET) { if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy; mBluetoothHeadset = (BluetoothHeadset) proxy;
Log.d("Bluetooth headset connected"); Log.d("Bluetooth headset connected");
routeToBluetoothIfAvailable(); isBluetoothScoConnected = true;
} }
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@ -264,6 +262,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
if (profile == BluetoothProfile.HEADSET) { if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null; mBluetoothHeadset = null;
Log.d("Bluetooth headset disconnected"); Log.d("Bluetooth headset disconnected");
isBluetoothScoConnected = false;
routeAudioToReceiver(); routeAudioToReceiver();
} }
} }
@ -276,40 +275,42 @@ public final class LinphoneManager implements LinphoneCoreListener {
int state = currentValue == null ? 0 : currentValue.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0); int state = currentValue == null ? 0 : currentValue.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
isBluetoothScoConnected = true; isBluetoothScoConnected = true;
scoConnected();
} }
} }
} } else {
else { isBluetoothScoConnected = false;
scoDisconnected(); scoDisconnected();
routeAudioToReceiver(); routeAudioToReceiver();
} }
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean routeToBluetoothIfAvailable() { public boolean routeAudioToBluetooth() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) { if (mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) {
mAudioManager.setBluetoothScoOn(true); mAudioManager.setBluetoothScoOn(true);
mAudioManager.startBluetoothSco(); mAudioManager.startBluetoothSco();
if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
boolean connected = false; isUsingBluetoothAudioRoute = false;
if (mBluetoothHeadset != null) { if (mBluetoothHeadset != null) {
List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices(); List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
for (final BluetoothDevice dev : devices) { for (final BluetoothDevice dev : devices) {
connected |= mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED; isUsingBluetoothAudioRoute |= mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED;
} }
} }
if (!connected) { if (!isUsingBluetoothAudioRoute) {
Log.d("No bluetooth device available"); Log.d("No bluetooth device available");
scoDisconnected(); scoDisconnected();
} else {
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) {
listener.onAudioStateChanged(AudioState.SPEAKER);
}
} }
return connected;
} else {
return isBluetoothScoConnected;
} }
return isUsingBluetoothAudioRoute;
} }
return false; return false;
@ -317,12 +318,13 @@ public final class LinphoneManager implements LinphoneCoreListener {
public void scoConnected() { public void scoConnected() {
Log.e("Bluetooth sco connected!"); Log.e("Bluetooth sco connected!");
mAudioManager.setMode(AudioManager.MODE_IN_CALL); isBluetoothScoConnected = true;
routeToBluetoothIfAvailable();
} }
public void scoDisconnected() { public void scoDisconnected() {
Log.e("Bluetooth sco disconnected!"); Log.e("Bluetooth sco disconnected!");
isUsingBluetoothAudioRoute = false;
isBluetoothScoConnected = false;
if (mAudioManager != null) { if (mAudioManager != null) {
mAudioManager.setMode(AudioManager.MODE_NORMAL); mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.stopBluetoothSco(); mAudioManager.stopBluetoothSco();
@ -578,10 +580,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
lFilter.addAction(Intent.ACTION_SCREEN_OFF); lFilter.addAction(Intent.ACTION_SCREEN_OFF);
mServiceContext.registerReceiver(mKeepAliveReceiver, lFilter); mServiceContext.registerReceiver(mKeepAliveReceiver, lFilter);
boolean routeToBT = mServiceContext.getResources().getBoolean(R.bool.route_audio_to_bluetooth_if_available); startBluetooth();
if (routeToBT) {
startBluetooth();
}
resetCameraFromPreferences(); resetCameraFromPreferences();
} }
catch (Exception e) { catch (Exception e) {