Merge branch 'master' of git.linphone.org:linphone-android

This commit is contained in:
Sylvain Berfini 2011-12-28 13:23:43 +01:00
commit cdd1551daa
26 changed files with 325 additions and 51 deletions

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.linphone" package="org.linphone"
android:versionCode="1210" android:versionName="1.2.1" android:installLocation="auto"> android:versionCode="1220" android:versionName="1.2.2" android:installLocation="auto">
<uses-sdk android:minSdkVersion="3" /> <uses-sdk android:minSdkVersion="3" />
@ -16,19 +16,6 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity>
<activity android:name="org.linphone.LinphoneActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar"
android:launchMode="singleTask"
> <!-- android:alwaysRetainTaskState="true" clearTaskOnLaunch="false"-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.CALL" /> <action android:name="android.intent.action.CALL" />
@ -44,6 +31,20 @@
<data android:scheme="sip" /><!-- maybe one day --> <data android:scheme="sip" /><!-- maybe one day -->
<data android:scheme="imto" /> <data android:scheme="imto" />
</intent-filter> </intent-filter>
</activity>
<activity android:name="org.linphone.LinphoneActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar"
android:launchMode="singleTask"
> <!-- android:alwaysRetainTaskState="true" clearTaskOnLaunch="false"-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity> </activity>
<activity android:name="org.linphone.IncomingCallActivity" <activity android:name="org.linphone.IncomingCallActivity"

1
README
View file

@ -19,6 +19,7 @@ BUILD_X264 0 (don't build x264) or 1 (build x264)
BUILD_AMR 0 (don't build amr codec), light (try to use amr codec from android), full (build your own amr codec) BUILD_AMR 0 (don't build amr codec), light (try to use amr codec from android), full (build your own amr codec)
BUILD_GPLV3_ZRTP 0 (don't support ZRTP), 1 (support ZRTP and make the whole program GPLv3) BUILD_GPLV3_ZRTP 0 (don't support ZRTP), 1 (support ZRTP and make the whole program GPLv3)
BUILD_SILK 0 (don't build silk plugin), 1 (build silk) [silk is Skype nonfree patented audio codec] BUILD_SILK 0 (don't build silk plugin), 1 (build silk) [silk is Skype nonfree patented audio codec]
BUILD_TUNNEL 0 (don't build tunnel), 1 (build tunnel) [requires a tunnel implementation in submodules/linphone/tunnel]
In order to use ZRTP you also need to define the media_encryption property to In order to use ZRTP you also need to define the media_encryption property to
"zrtp" in the sip section of linphonerc file. "zrtp" in the sip section of linphonerc file.

View file

@ -63,6 +63,10 @@ include $(linphone-root-dir)/submodules/linphone/mediastreamer2/build/android/An
include $(linphone-root-dir)/submodules/linphone/mediastreamer2/tests/Android.mk include $(linphone-root-dir)/submodules/linphone/mediastreamer2/tests/Android.mk
ifeq ($(BUILD_TUNNEL), 1)
include $(linphone-root-dir)/submodules/linphone/tunnel/Android.mk
endif
ifeq ($(BUILD_SILK), 1) ifeq ($(BUILD_SILK), 1)
$(info Build proprietary SILK plugin for mediastreamer2) $(info Build proprietary SILK plugin for mediastreamer2)
include $(linphone-root-dir)/submodules/mssilk/Android.mk include $(linphone-root-dir)/submodules/mssilk/Android.mk

View file

@ -2,10 +2,6 @@ APP_PROJECT_PATH := $(call my-dir)/../
APP_MODULES :=libspeex libgsm libortp libosip2 libeXosip2 libmediastreamer2 liblinphone APP_MODULES :=libspeex libgsm libortp libosip2 libeXosip2 libmediastreamer2 liblinphone
APP_STL := stlport_static APP_STL := stlport_static
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
APP_MODULES +=libmsilbc
endif
ifeq ($(LINPHONE_VIDEO),1) ifeq ($(LINPHONE_VIDEO),1)
APP_MODULES += libavutil libavcore libavcodec libswscale libvpx APP_MODULES += libavutil libavcore libavcodec libswscale libvpx
endif endif
@ -14,10 +10,6 @@ ifeq ($(BUILD_AMR),1)
APP_MODULES += libopencoreamr libmsamr APP_MODULES += libopencoreamr libmsamr
endif endif
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
APP_MODULES += liblincrypto liblinssl
endif
ifeq ($(BUILD_X264),1) ifeq ($(BUILD_X264),1)
APP_MODULES +=libx264 libmsx264 APP_MODULES +=libx264 libmsx264
endif endif
@ -30,7 +22,14 @@ ifeq ($(RING),yes)
APP_MODULES += libring APP_MODULES += libring
endif endif
ifeq ($(BUILD_TUNNEL), 1)
APP_MODULES += libtunnelclient
endif
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
APP_MODULES += liblincrypto liblinssl
APP_MODULES +=libmsilbc
ifeq ($(BUILD_GPLV3_ZRTP), 1) ifeq ($(BUILD_GPLV3_ZRTP), 1)
APP_MODULES += libzrtpcpp APP_MODULES += libzrtpcpp
endif endif
@ -38,12 +37,13 @@ endif
ifeq ($(BUILD_SRTP), 1) ifeq ($(BUILD_SRTP), 1)
APP_MODULES += libsrtp APP_MODULES += libsrtp
endif endif
endif endif #armeabi-v7a
linphone-root-dir:=$(APP_PROJECT_PATH) linphone-root-dir:=$(APP_PROJECT_PATH)
APP_BUILD_SCRIPT:=$(call my-dir)/Android.mk APP_BUILD_SCRIPT:=$(call my-dir)/Android.mk
APP_PLATFORM := android-8 APP_PLATFORM := android-8
#APP_ABI := armeabi-v7a #APP_ABI := armeabi
APP_ABI := armeabi-v7a armeabi APP_ABI := armeabi-v7a armeabi
APP_CFLAGS:=-DDISABLE_NEON APP_CFLAGS:=-DDISABLE_NEON

Binary file not shown.

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 905 B

View file

@ -23,6 +23,7 @@
android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_width="wrap_content" android:layout_height="fill_parent"
android:layout_centerVertical="true"> android:layout_centerVertical="true">
<TextView android:id="@+id/status_label" style="@style/callee_status" /> <TextView android:id="@+id/status_label" style="@style/callee_status" />
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/QoS" android:src="@drawable/stat_sys_signal_0" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" />
<ImageView android:id="@+id/callee_status_paused" style="@style/callee_status" android:src="@drawable/conf_status_paused" android:visibility="gone"/> <ImageView android:id="@+id/callee_status_paused" style="@style/callee_status" android:src="@drawable/conf_status_paused" android:visibility="gone"/>
<ImageView android:id="@+id/callee_status_secured" style="@style/callee_status" android:src="@drawable/conf_secured" android:visibility="gone"/> <ImageView android:id="@+id/callee_status_secured" style="@style/callee_status" android:src="@drawable/conf_secured" android:visibility="gone"/>
<ImageView android:id="@+id/callee_status_maybe_secured" style="@style/callee_status" android:src="@drawable/conf_maybe_secured" android:visibility="gone"/> <ImageView android:id="@+id/callee_status_maybe_secured" style="@style/callee_status" android:src="@drawable/conf_maybe_secured" android:visibility="gone"/>

View file

@ -26,8 +26,13 @@
ui:unchecked="@drawable/incall_micro" ui:unchecked="@drawable/incall_micro"
ui:bgdrawables="true" /> ui:bgdrawables="true" />
<ImageView android:src="@android:color/darker_gray" style="@style/incall_control" /> <ImageButton
<org.linphone.ui.ToggleImageButton android:id="@+id/toggleSpeaker" android:id="@+id/incallHang"
style="@style/incall_control"
android:background="@drawable/clavier_bg"
android:src="@drawable/stopcall_red" />
<org.linphone.ui.ToggleImageButton android:id="@+id/toggleSpeaker"
style="@style/incall_control" style="@style/incall_control"
ui:checked="@drawable/incall_speaker_inverse" ui:checked="@drawable/incall_speaker_inverse"
ui:unchecked="@drawable/incall_speaker" ui:unchecked="@drawable/incall_speaker"

View file

@ -8,5 +8,8 @@
<string name="notification_registered">Registered to %s </string> <string name="notification_registered">Registered to %s </string>
<string name="notification_register_failure">Fails to register to %s</string> <string name="notification_register_failure">Fails to register to %s</string>
<string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string>
<string name="tunnel_host"></string>
<string name="default_tunnel_mode_entry_value">@string/tunnel_mode_entry_value_disabled</string>
</resources> </resources>

View file

@ -1,5 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Do not translate any of the strings below -->
<string name="pref_tunnel_key">pref_tunnel_key</string>
<string name="pref_tunnel_mode_key">pref_tunnel_mode_key</string>
<string name="tunnel_mode_entry_value_disabled">disabled</string>
<string name="tunnel_mode_entry_value_3G_only">3G_only</string>
<string name="tunnel_mode_entry_value_always">always</string>
<string-array name="tunnel_mode_entry_values">
<item>@string/tunnel_mode_entry_value_disabled</item>
<item >@string/tunnel_mode_entry_value_3G_only</item>
<item>@string/tunnel_mode_entry_value_always</item>
<item>@string/tunnel_mode_entry_value_auto</item>
</string-array>
<string name="pref_tunnel_host_key">pref_tunnel_host_key</string>
<string name="pref_tunnel_port_key">pref_tunnel_port_key</string>
<string name="tunnel_mode_entry_value_auto">auto</string>
<string name="pref_audio_use_specific_mode_key">pref_audio_use_specific_mode_key</string> <string name="pref_audio_use_specific_mode_key">pref_audio_use_specific_mode_key</string>
<string name="pref_audio_hacks_use_galaxys_hack_key">pref_audio_hacks_use_galaxys_hack_key</string> <string name="pref_audio_hacks_use_galaxys_hack_key">pref_audio_hacks_use_galaxys_hack_key</string>

View file

@ -1,6 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="pref_tunnel">Tunnel</string>
<string name="pref_tunnel_host">Hostname</string>
<string name="pref_tunnel_port">Port</string>
<string name="pref_tunnel_mode">Mode</string>
<!-- do not change order without changing corresponding entry_values in non_localizable_strings.xml -->
<string-array name="tunnel_mode_entries">
<item>disabled</item>
<item>3G only</item>
<item>always</item>
<item>auto</item>
</string-array>
<string name="incall_notif_active">Audio call ongoing</string> <string name="incall_notif_active">Audio call ongoing</string>
<string name="incall_notif_paused">Paused call ongoing</string> <string name="incall_notif_paused">Paused call ongoing</string>
<string name="incall_notif_video">Video capturing call ongoing</string> <string name="incall_notif_video">Video capturing call ongoing</string>

View file

@ -21,6 +21,19 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:key="@string/pref_tunnel_key" android:title="@string/pref_tunnel">
<EditTextPreference android:title="@string/pref_tunnel_host"
android:key="@string/pref_tunnel_host_key"/>
<EditTextPreference android:title="@string/pref_tunnel_port"
android:key="@string/pref_tunnel_port_key" android:defaultValue="443"/>
<ListPreference android:title="@string/pref_tunnel_mode"
android:entries="@array/tunnel_mode_entries"
android:entryValues="@array/tunnel_mode_entry_values"
android:defaultValue="@string/default_tunnel_mode_entry_value"
android:key="@string/pref_tunnel_mode_key" />
</PreferenceCategory>

View file

@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
package org.linphone; package org.linphone;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -27,9 +28,9 @@ import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener;
import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener; import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener;
import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall; import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCore;
import org.linphone.core.Log; import org.linphone.core.Log;
import org.linphone.core.LinphoneCall.State;
import android.app.ListActivity; import android.app.ListActivity;
import android.net.Uri; import android.net.Uri;
@ -64,6 +65,8 @@ public abstract class AbstractCalleesActivity extends ListActivity implements Li
private Set<Chronometer> mChronometers = new HashSet<Chronometer>(); private Set<Chronometer> mChronometers = new HashSet<Chronometer>();
private Handler callqualityHandler;
private List<View> viewsToUpdateCallQuality;
@Override @Override
/** /**
* Called by the child classes AFTER their own onCreate. * Called by the child classes AFTER their own onCreate.
@ -210,6 +213,34 @@ public abstract class AbstractCalleesActivity extends ListActivity implements Li
timer.setBase(SystemClock.elapsedRealtime() - 1000 * callDuration); timer.setBase(SystemClock.elapsedRealtime() - 1000 * callDuration);
timer.start(); timer.start();
} }
protected final void initCallQualityListener() {
callqualityHandler = new Handler();
viewsToUpdateCallQuality = new ArrayList<View>();
callqualityHandler.postDelayed(new Runnable() {
public void run() {
if (viewsToUpdateCallQuality == null) {
return;
}
for (View v : viewsToUpdateCallQuality) {
LinphoneCall call = (LinphoneCall) v.getTag();
float newQuality = call.getCurrentQuality();
updateQualityOfSignalIcon(v, newQuality);
}
callqualityHandler.postDelayed(this, 1000);
}
},1000);
}
protected final void registerCallQualityListener(final View v, final LinphoneCall call) {
if (viewsToUpdateCallQuality == null && callqualityHandler == null) {
initCallQualityListener();
}
v.setTag(call);
viewsToUpdateCallQuality.add(v);
}
} }
@Override @Override
@ -248,4 +279,29 @@ public abstract class AbstractCalleesActivity extends ListActivity implements Li
} }
}); });
} }
void updateQualityOfSignalIcon(View v, float quality)
{
ImageView qos = (ImageView) v.findViewById(R.id.QoS);
if (quality >= 4) // Good Quality
{
qos.setImageDrawable(getResources().getDrawable(R.drawable.stat_sys_signal_4));
}
else if (quality >= 3) // Average quality
{
qos.setImageDrawable(getResources().getDrawable(R.drawable.stat_sys_signal_3));
}
else if (quality >= 2) // Low quality
{
qos.setImageDrawable(getResources().getDrawable(R.drawable.stat_sys_signal_2));
}
else if (quality >= 1) // Very low quality
{
qos.setImageDrawable(getResources().getDrawable(R.drawable.stat_sys_signal_1));
}
else // Worst quality
{
qos.setImageDrawable(getResources().getDrawable(R.drawable.stat_sys_signal_0));
}
}
} }

View file

@ -51,6 +51,13 @@ public class ConferenceDetailsActivity extends AbstractCalleesActivity {
return; return;
} }
setContentView(R.layout.conference_details_layout); setContentView(R.layout.conference_details_layout);
View v=findViewById(R.id.incallHang);
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
lc().terminateConference();
}
});
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@ -94,6 +101,8 @@ public class ConferenceDetailsActivity extends AbstractCalleesActivity {
setCalleePicture(pictureView, address); setCalleePicture(pictureView, address);
registerCallDurationTimer(v, call); registerCallDurationTimer(v, call);
registerCallQualityListener(v, call);
return v; return v;
} }

View file

@ -31,7 +31,6 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -51,15 +50,16 @@ import android.widget.Toast;
public class DialerActivity extends Activity implements LinphoneGuiListener { public class DialerActivity extends Activity implements LinphoneGuiListener {
private TextView mStatus; private TextView mStatus;
private Handler mHandler;
private AddressText mAddress; private AddressText mAddress;
private CallButton mCall; private CallButton mCall;
private static DialerActivity instance; private static DialerActivity instance;
private boolean mPreventDoubleCallOnRotation;
private static final String CURRENT_ADDRESS = "org.linphone.current-address"; private static final String CURRENT_ADDRESS = "org.linphone.current-address";
private static final String CURRENT_DISPLAYNAME = "org.linphone.current-displayname"; private static final String CURRENT_DISPLAYNAME = "org.linphone.current-displayname";
private static final String PREVENT_DOUBLE_CALL = "prevent_call_on_phone_rotation";
/** /**
* @return null if not ready yet * @return null if not ready yet
@ -71,8 +71,6 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.dialer); setContentView(R.layout.dialer);
mHandler = new Handler();
mAddress = (AddressText) findViewById(R.id.SipUri); mAddress = (AddressText) findViewById(R.id.SipUri);
((EraseButton) findViewById(R.id.Erase)).setAddressWidget(mAddress); ((EraseButton) findViewById(R.id.Erase)).setAddressWidget(mAddress);
@ -90,7 +88,13 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
// because it may call this.enterIncallMode // because it may call this.enterIncallMode
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
checkIfOutgoingCallIntentReceived(); mPreventDoubleCallOnRotation=savedInstanceState != null
&& savedInstanceState.getBoolean(PREVENT_DOUBLE_CALL, false);
if (mPreventDoubleCallOnRotation) {
Log.i("Prevent launching a new call on rotation");
} else {
checkIfOutgoingCallIntentReceived();
}
instance = this; instance = this;
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -129,6 +133,7 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
savedInstanceState.putCharSequence(CURRENT_ADDRESS, mAddress.getText()); savedInstanceState.putCharSequence(CURRENT_ADDRESS, mAddress.getText());
if (mAddress.getDisplayedName() != null) if (mAddress.getDisplayedName() != null)
savedInstanceState.putString(CURRENT_DISPLAYNAME,mAddress.getDisplayedName()); savedInstanceState.putString(CURRENT_DISPLAYNAME,mAddress.getDisplayedName());
savedInstanceState.putBoolean(PREVENT_DOUBLE_CALL, mPreventDoubleCallOnRotation);
} }
@Override @Override
@ -153,14 +158,23 @@ public class DialerActivity extends Activity implements LinphoneGuiListener {
public void newOutgoingCall(Intent intent) { public void newOutgoingCall(Intent intent) {
if (Intent.ACTION_CALL.equalsIgnoreCase(intent.getAction())) { String scheme = intent.getData().getScheme();
mAddress.setText(intent.getData().getSchemeSpecificPart()); if (scheme.startsWith("imto")) {
} else if (Intent.ACTION_SENDTO.equals(intent.getAction())) {
mAddress.setText("sip:" + intent.getData().getLastPathSegment()); mAddress.setText("sip:" + intent.getData().getLastPathSegment());
} else if (scheme.startsWith("call") || scheme.startsWith("sip")) {
mAddress.setText(intent.getData().getSchemeSpecificPart());
} else {
Log.e("Unknown scheme: ",scheme);
mAddress.setText(intent.getData().getSchemeSpecificPart());
} }
mAddress.clearDisplayedName(); mAddress.clearDisplayedName();
intent.setData(null); intent.setData(null);
// Setting data to null is no use when the activity is recreated
// as the intent is immutable.
// https://groups.google.com/forum/#!topic/android-developers/vrLdM5mKeoY
mPreventDoubleCallOnRotation=true;
setIntent(intent);
LinphoneManager.getInstance().newOutgoingCall(mAddress); LinphoneManager.getInstance().newOutgoingCall(mAddress);
} }

View file

@ -456,6 +456,7 @@ public class IncallActivity extends AbstractCalleesActivity implements
boolean statusPaused = state== State.Paused || state == State.PausedByRemote; boolean statusPaused = state== State.Paused || state == State.PausedByRemote;
setVisibility(v, R.id.callee_status_paused, statusPaused); setVisibility(v, R.id.callee_status_paused, statusPaused);
setVisibility(v, R.id.QoS, !statusPaused);
final OnLongClickListener showCallActionsLongListener = new OnLongClickListener() { final OnLongClickListener showCallActionsLongListener = new OnLongClickListener() {
public boolean onLongClick(View v) { public boolean onLongClick(View v) {
@ -538,6 +539,7 @@ public class IncallActivity extends AbstractCalleesActivity implements
} }
registerCallDurationTimer(v, call); registerCallDurationTimer(v, call);
registerCallQualityListener(v, call);
enableView(v, R.id.callee_status_details, showCallActionsSimpleListener, true); enableView(v, R.id.callee_status_details, showCallActionsSimpleListener, true);

View file

@ -87,9 +87,10 @@ public class LinphoneActivity extends TabActivity implements ContactPicked
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (!LinphoneManager.isInstanciated()) { if (!LinphoneManager.isInstanciated()) {
Log.e("No service running: avoid crash by finishing ", this.getClass().getName()); Log.e("No service running: avoid crash by starting the launcher", this.getClass().getName());
// super.onCreate called earlier // super.onCreate called earlier
finish(); finish();
startActivity(getIntent().setClass(this, LinphoneLauncherActivity.class));
return; return;
} }
instance = this; instance = this;

View file

@ -403,6 +403,47 @@ public final class LinphoneManager implements LinphoneCoreListener {
} }
} }
private boolean isTunnelNeeded(NetworkInfo info) {
if (info == null) {
Log.i("No connectivity: tunnel should be disabled");
return false;
}
String pref = getPrefString(R.string.pref_tunnel_mode_key, R.string.default_tunnel_mode_entry_value);
if (getString(R.string.tunnel_mode_entry_value_always).equals(pref)) {
return true;
}
if (info.getType() != ConnectivityManager.TYPE_WIFI
&& getString(R.string.tunnel_mode_entry_value_3G_only).equals(pref)) {
Log.i("need tunnel: 'no wifi' connection");
return true;
}
return false;
}
public void manageTunnelServer(NetworkInfo info) {
if (mLc == null) return;
if (!mLc.isTunnelAvailable()) return;
Log.i("Managing tunnel");
if (isTunnelNeeded(info)) {
Log.i("Tunnel need to be activated");
mLc.tunnelEnable(true);
} else {
Log.i("Tunnel should not be used");
String pref = getPrefString(R.string.pref_tunnel_mode_key, R.string.default_tunnel_mode_entry_value);
mLc.tunnelEnable(false);
if (getString(R.string.tunnel_mode_entry_value_auto).equals(pref)) {
mLc.tunnelAutoDetect();
}
}
}
private synchronized void startLibLinphone() { private synchronized void startLibLinphone() {
try { try {
copyAssetsFromPackage(); copyAssetsFromPackage();
@ -484,7 +525,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
void initMediaEncryption(){ void initMediaEncryption(){
String pref = getPrefString(R.string.pref_media_encryption_key, String pref = getPrefString(R.string.pref_media_encryption_key,
getString(R.string.pref_media_encryption_key_none)); R.string.pref_media_encryption_key_none);
MediaEncryption me=MediaEncryption.None; MediaEncryption me=MediaEncryption.None;
if (pref.equals(getString(R.string.pref_media_encryption_key_srtp))) if (pref.equals(getString(R.string.pref_media_encryption_key_srtp)))
me=MediaEncryption.SRTP; me=MediaEncryption.SRTP;
@ -494,11 +535,26 @@ public final class LinphoneManager implements LinphoneCoreListener {
mLc.setMediaEncryption(me); mLc.setMediaEncryption(me);
} }
private void initFromConfTunnel(){
if (!mLc.isTunnelAvailable()) return;
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
mLc.tunnelEnableLogs(getPrefBoolean(R.string.pref_debug_key, false));
mLc.tunnelCleanServers();
String host = getString(R.string.tunnel_host);
if (host == null || host.length() == 0)
host = mPref.getString(getString(R.string.pref_tunnel_host_key), "");
int port = Integer.parseInt(getPrefString(R.string.pref_tunnel_port_key, "443"));
mLc.tunnelAddServerAndMirror(host, port, 12345,500);
manageTunnelServer(info);
}
public void initFromConf() throws LinphoneConfigException { public void initFromConf() throws LinphoneConfigException {
//traces //traces
boolean lIsDebug = true;//mPref.getBoolean(getString(R.string.pref_debug_key), false); boolean lIsDebug = true;//mPref.getBoolean(getString(R.string.pref_debug_key), false);
LinphoneCoreFactory.instance().setDebugMode(lIsDebug); LinphoneCoreFactory.instance().setDebugMode(lIsDebug);
initFromConfTunnel();
if (initialTransports == null) if (initialTransports == null)
initialTransports = mLc.getSignalingTransportPorts(); initialTransports = mLc.getSignalingTransportPorts();
@ -713,9 +769,32 @@ public final class LinphoneManager implements LinphoneCoreListener {
private String getPrefString(int key, String value) { private String getPrefString(int key, String value) {
return mPref.getString(mR.getString(key), value); return mPref.getString(mR.getString(key), value);
} }
private String getPrefString(int key, int value) {
return mPref.getString(mR.getString(key), mR.getString(value));
}
/* Simple implementation as Android way seems very complicate:
For example: with wifi and mobile actives; when pulling mobile down:
I/Linphone( 8397): WIFI connected: setting network reachable
I/Linphone( 8397): new state [RegistrationProgress]
I/Linphone( 8397): mobile disconnected: setting network unreachable
I/Linphone( 8397): Managing tunnel
I/Linphone( 8397): WIFI connected: setting network reachable
*/
public void connectivityChanged(NetworkInfo eventInfo, ConnectivityManager cm) {
NetworkInfo activeInfo = cm.getActiveNetworkInfo();
if (eventInfo.getState() == NetworkInfo.State.DISCONNECTED) {
Log.i(eventInfo.getTypeName()," disconnected: setting network unreachable");
mLc.setNetworkReachable(false);
} else if (eventInfo.getState() == NetworkInfo.State.CONNECTED){
manageTunnelServer(activeInfo);
Log.i(eventInfo.getTypeName()," connected: setting network reachable");
mLc.setNetworkReachable(true);
}
}

View file

@ -52,6 +52,7 @@ import android.preference.CheckBoxPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener; import android.preference.Preference.OnPreferenceClickListener;
@ -144,6 +145,15 @@ public class LinphonePreferencesActivity extends PreferenceActivity implements E
if (Hacks.needSoftvolume()) checkAndDisableCheckbox(R.string.pref_audio_soft_volume_key); if (Hacks.needSoftvolume()) checkAndDisableCheckbox(R.string.pref_audio_soft_volume_key);
if (!LinphoneManager.getLc().isTunnelAvailable()){
hidePreferenceCategory(R.string.pref_tunnel_key);
}
}
private void hidePreferenceCategory(int key) {
PreferenceCategory p = (PreferenceCategory) findPreference(key);
p.removeAll();
p.setLayoutResource(R.layout.hidden);
} }
private void doOnFirstLaunch() { private void doOnFirstLaunch() {

View file

@ -414,7 +414,7 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered); sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
} }
if (state == RegistrationState.RegistrationFailed) { if (state == RegistrationState.RegistrationFailed || state == RegistrationState.RegistrationCleared) {
sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure); sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure);
} }

View file

@ -51,11 +51,15 @@ public class NetworkManager extends BroadcastReceiver {
if (lNoConnectivity | ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) { if (lNoConnectivity | ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) {
LinphoneManager.getLc().setNetworkReachable(false); LinphoneManager.getLc().setNetworkReachable(false);
} else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){ } else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){
LinphoneManager.getLc().setNetworkReachable(true); LinphoneManager.getLc().setNetworkReachable(true);
} else { } else {
// Other unhandled events // Other unhandled events
} }
NetworkInfo eventInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
LinphoneManager.getInstance().connectivityChanged(eventInfo, cm);
} }
} }

View file

@ -99,7 +99,9 @@ public class VideoCallActivity extends Activity implements LinphoneOnCallStateCh
} }
public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) { public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) {
// Remove references kept in jni code and restart camera
// LinphoneManager.getLc().setPreviewWindow(null);
// Commented to remove flicker.
} }
}); });
@ -272,7 +274,9 @@ public class VideoCallActivity extends Activity implements LinphoneOnCallStateCh
@Override @Override
protected void onDestroy() { protected void onDestroy() {
androidVideoWindowImpl.release(); if (androidVideoWindowImpl != null) { // Prevent linphone from crashing if correspondent hang up while you are rotating
androidVideoWindowImpl.release();
}
super.onDestroy(); super.onDestroy();
} }
@ -291,8 +295,6 @@ public class VideoCallActivity extends Activity implements LinphoneOnCallStateCh
LinphoneManager.getLc().setVideoWindow(null); LinphoneManager.getLc().setVideoWindow(null);
} }
LinphoneManager.getLc().setPreviewWindow(null);
if (mCallQualityUpdater!=null){ if (mCallQualityUpdater!=null){
refreshHandler.removeCallbacks(mCallQualityUpdater); refreshHandler.removeCallbacks(mCallQualityUpdater);
mCallQualityUpdater=null; mCallQualityUpdater=null;

View file

@ -49,6 +49,9 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
loadOptionalLibrary("srtp"); loadOptionalLibrary("srtp");
loadOptionalLibrary("zrtpcpp"); // GPLv3+ loadOptionalLibrary("zrtpcpp"); // GPLv3+
// Tunnel
loadOptionalLibrary("tunnelclient");
//Main library //Main library
System.loadLibrary("linphone"); System.loadLibrary("linphone");

View file

@ -617,8 +617,43 @@ class LinphoneCoreImpl implements LinphoneCore {
} }
private native void setPlayFile(long nativePtr, String path); private native void setPlayFile(long nativePtr, String path);
@Override @Override
public void setPlayFile(String path) { public void setPlayFile(String path) {
setPlayFile(nativePtr, path); setPlayFile(nativePtr, path);
} }
private native void tunnelAddServerAndMirror(long nativePtr, String host, int port, int mirror, int ms);
@Override
public void tunnelAddServerAndMirror(String host, int port, int mirror, int ms) {
tunnelAddServerAndMirror(nativePtr, host, port, mirror, ms);
}
private native void tunnelAutoDetect(long nativePtr);
@Override
public void tunnelAutoDetect() {
tunnelAutoDetect(nativePtr);
}
private native void tunnelCleanServers(long nativePtr);
@Override
public void tunnelCleanServers() {
tunnelCleanServers(nativePtr);
}
private native void tunnelEnable(long nativePtr, boolean enable);
@Override
public void tunnelEnable(boolean enable) {
tunnelEnable(nativePtr, enable);
}
private native void tunnelEnableLogs(long nativePtr, boolean enable);
@Override
public void tunnelEnableLogs(boolean enable) {
tunnelEnableLogs(nativePtr, enable);
}
@Override
public native boolean isTunnelAvailable();
} }

View file

@ -56,7 +56,9 @@ LOCAL_CFLAGS += \
-UHAVE_CONFIG_H \ -UHAVE_CONFIG_H \
-include $(LOCAL_PATH)/../build/exosip/libeXosip2_AndroidConfig.h \ -include $(LOCAL_PATH)/../build/exosip/libeXosip2_AndroidConfig.h \
-DOSIP_MT \ -DOSIP_MT \
-DENABLE_TRACE -DENABLE_TRACE \
-include $(LOCAL_PATH)/include/eXosip2/eXosip_transport_hook.h
LOCAL_C_INCLUDES += \ LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \ $(LOCAL_PATH)/include \

@ -1 +1 @@
Subproject commit 4eabd05b149d18629098f3254f15c8d14ff6664c Subproject commit c3da0303519ad3120355cb85baee9cf6d0e4d1c2

@ -1 +1 @@
Subproject commit ad8a8bbbb3fe7189111c38eefe1320ae21a64f02 Subproject commit 5bf95231b51641ce095af49a864cf00fa6837750