diff --git a/.gitignore b/.gitignore
index 1b94dd9f7..f1ed51c97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,7 +47,6 @@ tests/tests.output
WORK
.d
google-services.json
-gradle.properties
.*clang*
linphone.iml
src/linphone-wrapper
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8f1b57fa0..d0c2f87b2 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -7,7 +7,7 @@
+ android:targetSdkVersion="28"/>
diff --git a/AndroidManifestSdk.xml b/AndroidManifestSdk.xml
new file mode 100755
index 000000000..17de7b7ee
--- /dev/null
+++ b/AndroidManifestSdk.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/README.md b/README.md
index 36c677fde..df4f16c35 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,16 @@
+[](https://gitlab.linphone.org/BC/public/linphone-android/commits/master)
+
Linphone is a free VoIP and video softphone based on the SIP protocol.
# COMPILATION INSTRUCTIONS
## To build liblinphone for Android, you must:
-1. Download the Android sdk (API 26.0.1 at max) with platform-tools and tools updated to latest revision, then add both 'tools' and 'platform-tools' folders in your path and the android-sdk folder to ANDROID_HOME environment variable.
+1. Download the Android sdk (API 28.0.0 at max) with platform-tools and tools updated to latest revision, then add both 'tools' and 'platform-tools' folders in your path and the android-sdk folder to ANDROID_HOME environment variable.
-2. Download the Android ndk (version r11c or 15) from google and add it to your path (no symlink !!!) and ANDROID_NDK environment variable.
+2. Download the Android ndk (version 16) from google and add it to your path (no symlink !!!) and ANDROID_NDK environment variable.
-3. Install _yasm_, _nasm_ (For OpenH224 support only), _python_, _pkg_config_ and _cmake(>=3.7)_.
+3. Install _yasm_, _nasm_ (For OpenH224 support only), _python_, _pkg_config_ and _cmake(>=3.10)_.
* On 64 bits linux systems you'll need the _ia32-libs_ package.
* With the latest Debian (multiarch), you need this:
* `dpkg --add-architecture i386`
@@ -65,11 +67,6 @@ You can speed up the compilation by using ccache (compiler cache, see [ccache.sa
To enable firebase in Linphone, just add your 'google-service.json' in project root, add your key at 'push_sender_id' and add 'firebase' at 'push_type' in 'res/values/non_localizable_custom.xml'
Be sure to have all services for Firebase in your 'AndroidManifest.xml'
-## Google
-
-To enable google push in Linphone, remove 'google-service.json' file if it exist, add your key at 'push_sender_id' and add 'google' at 'push_type' in 'res/values/non_localizable_custom.xml'
-Be sure to have every permissions and services for GCM in your 'AndroidManifest.xml'
-
# TROUBLESHOOTING
If you encounter the following issue:
diff --git a/build.gradle b/build.gradle
index 94840e15c..9628f764d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -47,7 +47,7 @@ dependencies {
if (firebaseEnable()) {
implementation 'com.google.firebase:firebase-messaging:15.0.2'
}
- implementation 'com.android.support:support-v4:26.0.1'
+ implementation 'com.android.support:support-v4:27.0.1'
implementation project(':liblinphone-sdk')
}
@@ -78,7 +78,8 @@ excludePackage.add('**/LICENSE.txt')
android {
defaultConfig {
- compileSdkVersion 26
+ compileSdkVersion 28
+ buildToolsVersion "28.0.0"
applicationId getPackageName()
multiDexEnabled true
@@ -155,7 +156,7 @@ android {
packagingOptions {
pickFirst 'META-INF/NOTICE'
pickFirst 'META-INF/LICENSE'
- pickFirst 'META-INF/MANIFEST.MF'
+ exclude 'META-INF/MANIFEST.MF'
}
}
diff --git a/liblinphone-sdk/AndroidManifestLibrary.xml b/liblinphone-sdk/AndroidManifestLibrary.xml
index 1d333c9de..650cbb6e1 100755
--- a/liblinphone-sdk/AndroidManifestLibrary.xml
+++ b/liblinphone-sdk/AndroidManifestLibrary.xml
@@ -2,10 +2,10 @@
+ android:versionCode="4001"
+ android:versionName="4.0.0">
+ android:targetSdkVersion="28"/>
diff --git a/liblinphone-sdk/build.gradle b/liblinphone-sdk/build.gradle
index c8011b585..78c6d83fe 100644
--- a/liblinphone-sdk/build.gradle
+++ b/liblinphone-sdk/build.gradle
@@ -68,13 +68,34 @@ android {
buildTypes {
release {}
- debug{}
+ debug {}
}
defaultConfig {
- compileSdkVersion 26
- buildToolsVersion "26.0.0"
+ compileSdkVersion 28
+ buildToolsVersion "28.0.0"
multiDexEnabled true
+ setProperty("archivesBaseName", "liblinphone-sdk")
+ }
+
+ // Signing
+ signingConfigs {
+ release {
+ storeFile file(RELEASE_STORE_FILE)
+ storePassword RELEASE_STORE_PASSWORD
+ keyAlias RELEASE_KEY_ALIAS
+ keyPassword RELEASE_KEY_PASSWORD
+ }
+ }
+ buildTypes {
+ release {
+ signingConfig signingConfigs.release
+ }
+ packaged {
+ initWith release
+ signingConfig null
+ matchingFallbacks = ['debug', 'release']
+ }
}
lintOptions {
diff --git a/liblinphone_tester/Makefile b/liblinphone_tester/Makefile
index 90d0fb69f..e78471ae5 100644
--- a/liblinphone_tester/Makefile
+++ b/liblinphone_tester/Makefile
@@ -57,6 +57,7 @@ copy-files: ../submodules/linphone/tester/tester_hosts
cp -rf ../submodules/linphone/tester/rcfiles assets/config_files
cp -rf ../submodules/linphone/tester/sounds assets/config_files
cp -rf ../submodules/linphone/tester/vcards assets/config_files
+ cp -rf ../submodules/linphone/tester/db assets/config_files
mkdir -p res/raw
if test -d "../liblinphone-sdk/android-arm/share/belr/grammars"; then \
cp ../liblinphone-sdk/android-arm/share/belr/grammars/*_grammar res/raw/; \
diff --git a/liblinphone_tester/gradle.properties b/liblinphone_tester/gradle.properties
new file mode 100644
index 000000000..a4996c82d
--- /dev/null
+++ b/liblinphone_tester/gradle.properties
@@ -0,0 +1,7 @@
+// Signing APK Release
+RELEASE_STORE_FILE=""
+RELEASE_STORE_PASSWORD=
+RELEASE_KEY_ALIAS=
+RELEASE_KEY_PASSWORD=
+#source:https://docs.gradle.org/current/userguide/build_environment.html#sec:configuring_jvm_memory
+org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
diff --git a/liblinphone_tester/src/org/linphone/tester/LogsActivity.java b/liblinphone_tester/src/org/linphone/tester/LogsActivity.java
index 40c7062cf..b4021760b 100644
--- a/liblinphone_tester/src/org/linphone/tester/LogsActivity.java
+++ b/liblinphone_tester/src/org/linphone/tester/LogsActivity.java
@@ -23,7 +23,7 @@ public class LogsActivity extends Activity {
@Override
public void run() {
- String res_path = mLogsActivity.getFilesDir().getAbsolutePath()+"/config_files";
+ String res_path = mLogsActivity.getFilesDir().getAbsolutePath();
String write_path = mLogsActivity.getCacheDir().getPath();
tester = new TesterLogger(mLogsActivity);
List list = new LinkedList(Arrays.asList(new String[]{"tester", "--verbose", "--resource-dir", res_path, "--writable-dir", write_path}));
diff --git a/liblinphone_tester/src/org/linphone/tester/TestUnit.java b/liblinphone_tester/src/org/linphone/tester/TestUnit.java
index 980c093dc..eefe4f675 100644
--- a/liblinphone_tester/src/org/linphone/tester/TestUnit.java
+++ b/liblinphone_tester/src/org/linphone/tester/TestUnit.java
@@ -26,42 +26,19 @@ public class TestUnit extends AndroidTestCase {
public TestUnit(String name) {
String[] tab = name.split("/");
mSuite = tab[0];
- mTest = tab[1];
+ if (tab.length == 2)
+ mTest = tab[1];
setName(name);
}
static public void copyAssetsFromPackage(Context ctx) throws IOException {
- copyAssetsFromPackage(ctx,"config_files");
+ //copy sdk assets
+ org.linphone.core.tools.AndroidPlatformHelper.copyAssetsFromPackage(ctx,"org.linphone.core",".");
+ //copy tester assets
+ org.linphone.core.tools.AndroidPlatformHelper.copyAssetsFromPackage(ctx,"config_files",".");
}
- public static void copyAssetsFromPackage(Context ctx,String fromPath) throws IOException {
- new File(ctx.getFilesDir().getPath()+"/"+fromPath).mkdir();
-
- for (String f :ctx.getAssets().list(fromPath)) {
- String current_name=fromPath+"/"+f;
- InputStream lInputStream;
- try {
- lInputStream = ctx.getAssets().open(current_name);
- } catch (IOException e) {
- //probably a dir
- new File(ctx.getFilesDir().getPath()+"/"+current_name).mkdir();
- copyAssetsFromPackage(ctx,current_name);
- continue;
- }
- FileOutputStream lOutputStream = new FileOutputStream(new File(ctx.getFilesDir().getPath()+"/"+current_name));//ctx.openFileOutput (fromPath+"/"+f, 0);
-
-
- int readByte;
- byte[] buff = new byte[8048];
- while (( readByte = lInputStream.read(buff)) != -1) {
- lOutputStream.write(buff,0, readByte);
- }
- lOutputStream.flush();
- lOutputStream.close();
- lInputStream.close();
- }
- }
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -79,7 +56,7 @@ public class TestUnit extends AndroidTestCase {
@Override
protected void runTest() {
- String res_path = getContext().getFilesDir().getPath()+"/config_files";
+ String res_path = getContext().getFilesDir().getPath();
String write_path = getContext().getCacheDir().getPath();
Tester tester = new Tester();
diff --git a/linphoneAndroidSdk.gradle b/linphoneAndroidSdk.gradle
index 4e811dab4..34b5c80b0 100644
--- a/linphoneAndroidSdk.gradle
+++ b/linphoneAndroidSdk.gradle
@@ -1,12 +1,8 @@
// Project information
buildDir = 'bin'
-def firebaseEnable() {
- File googleFile = new File('google-services.json')
- return googleFile.exists()
-}
+
buildscript {
- File googleFile = new File('google-services.json')
repositories {
jcenter()
mavenCentral()
@@ -15,9 +11,6 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0'
- if (googleFile.exists()) {
- classpath 'com.google.gms:google-services:3.1.0'
- }
}
}
@@ -33,28 +26,17 @@ allprojects {
apply plugin: 'com.android.library'
dependencies {
- implementation group: 'org.apache.commons', name: 'commons-compress', version: '1.16.1'
- if (firebaseEnable()) {
- implementation 'com.google.firebase:firebase-messaging:15.0.2'
- } else {
- implementation 'com.android.support:support-v4:26.0.1'
- }
-}
-
-if (firebaseEnable()) {
- apply plugin: 'com.google.gms.google-services'
+ compile group: 'org.apache.commons', name: 'commons-compress', version: '1.16.1'
+ compile 'com.android.support:support-v4:26.0.2'
}
def srcDirs = ['submodules/mediastreamer2/java/src', 'src/linphone-wrapper', 'src/android']
def excludeFiles = []
-// Exclude firebase file if not enable
-if (!firebaseEnable()) {
- excludeFiles.add('**/Firebase*')
-} else {
- excludeFiles.add('**/gcm*')
-}
+
+excludeFiles.add('**/Firebase*')
+excludeFiles.add('**/gcm*')
excludeFiles.add('**/mediastream/MediastreamerActivity.java')
def excludePackage = []
@@ -67,6 +49,7 @@ excludePackage.add('**/LICENSE.txt')
android {
defaultConfig {
compileSdkVersion 26
+ buildToolsVersion "27.0.3"
multiDexEnabled true
}
@@ -79,7 +62,7 @@ android {
sourceSets {
main {
- manifest.srcFile 'AndroidManifestLibrary.xml'
+ manifest.srcFile 'AndroidManifestSdk.xml'
java.srcDirs = srcDirs
resources.srcDirs = srcDirs
aidl.srcDirs = srcDirs
diff --git a/prepare.py b/prepare.py
index 1e8134542..4ad88b5e0 100755
--- a/prepare.py
+++ b/prepare.py
@@ -144,7 +144,7 @@ class AndroidPreparator(prepare.Preparator):
retval = True
ndk_build = find_executable('ndk-build')
ndk_path = os.path.dirname(ndk_build)
- # NDK prior to r11 had a RELEASE.TXT file holding the version number
+ # NDK prior to r11 had a RELEASE.TXT file holding the version number
release_file = os.path.join(ndk_path, 'RELEASE.TXT')
if os.path.isfile(release_file):
version = open(release_file).read().strip()
@@ -368,11 +368,10 @@ generate-javadoc:
\t./gradlew -q androidJavadocsJar
\t./gradlew -q sourcesJar
-liblinphone-android-sdk: java-clean build copy-libs
-\t./gradlew -q androidJavadocsJar
-\t./gradlew -q sourcesJar
-\t./gradlew -q assembleRelease
-\t@mv $(TOPDIR)/bin/outputs/aar/*.aar $(TOPDIR)/bin/outputs/aar/liblinphone-sdk.aar
+debug-sdk: java-clean build copy-libs generate-javadoc generate-apk
+\t./gradlew -q sdkZip
+
+release-sdk: java-clean build copy-libs generate-javadoc release
\t./gradlew -q sdkZip
linphone-android-sdk: java-clean build copy-libs
diff --git a/src/android/org/linphone/LinphoneManager.java b/src/android/org/linphone/LinphoneManager.java
index dfed7d63e..e9638139f 100644
--- a/src/android/org/linphone/LinphoneManager.java
+++ b/src/android/org/linphone/LinphoneManager.java
@@ -584,7 +584,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
BluetoothManagerDestroy();
try {
mTimer.cancel();
- mLc = null;
+ destroyLinphoneCore();
}
catch (RuntimeException e) {
Log.e(e);
@@ -623,6 +623,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
}
}
+
public void restartCore() {
destroyCore();
startLibLinphone(mServiceContext);
@@ -906,50 +907,15 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
}
}
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- private void doDestroy() {
- ContactsManagerDestroy();
- BluetoothManagerDestroy();
- try {
- mTimer.cancel();
- mLc = null;
- }
- catch (RuntimeException e) {
- Log.e(e);
- }
- finally {
- try {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
- mServiceContext.unregisterReceiver(mNetworkReceiver);
- }
- } catch (Exception e) {
- Log.e(e);
- }
- try {
- mServiceContext.unregisterReceiver(mHookReceiver);
- } catch (Exception e) {
- Log.e(e);
- }
- try {
- mServiceContext.unregisterReceiver(mKeepAliveReceiver);
- } catch (Exception e) {
- Log.e(e);
- }
- try {
- mServiceContext.unregisterReceiver(mCallReceiver);
- } catch (Exception e) {
- Log.e(e);
- }
- try {
- dozeManager(false);
- } catch (IllegalArgumentException iae) {
- Log.e(iae);
- } catch (Exception e) {
- Log.e(e);
- }
- mLc = null;
- instance = null;
+ private void destroyLinphoneCore() {
+ if (LinphonePreferences.instance() != null) {
+ // We set network reachable at false before destroy LC to not send register with expires at 0
+ if (LinphonePreferences.instance().isPushNotificationEnabled()
+ || LinphonePreferences.instance().isBackgroundModeEnabled()) {
+ mLc.setNetworkReachable(false);
+ }
}
+ mLc = null;
}
public void dozeManager(boolean enable) {
@@ -1035,7 +1001,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
if (instance == null) return;
getInstance().changeStatusToOffline();
sExited = true;
- instance.doDestroy();
+ instance.destroyCore();
}
private String getString(int key) {
diff --git a/src/android/org/linphone/LinphonePreferences.java b/src/android/org/linphone/LinphonePreferences.java
index d36a974e7..dc3d573f4 100644
--- a/src/android/org/linphone/LinphonePreferences.java
+++ b/src/android/org/linphone/LinphonePreferences.java
@@ -370,6 +370,13 @@ public class LinphonePreferences {
prxCfg.setQualityReportingCollector(tempQualityReportingCollector);
prxCfg.setQualityReportingInterval(tempQualityReportingInterval);
+ String regId = LinphonePreferences.instance().getPushNotificationRegistrationID();
+ String appId = LinphonePreferences.instance().getString(R.string.push_sender_id);
+ if (regId != null && LinphonePreferences.instance().isPushNotificationEnabled()) {
+ String contactInfos = "app-id=" + appId + ";pn-type=" + LinphonePreferences.instance().getString(R.string.push_type) + ";pn-tok=" + regId + ";pn-silent=1";
+ prxCfg.setContactUriParameters(contactInfos);
+ }
+
if(tempPrefix != null){
prxCfg.setDialPrefix(tempPrefix);
}
diff --git a/src/android/org/linphone/LinphoneUtils.java b/src/android/org/linphone/LinphoneUtils.java
index aeed8ea39..49860166d 100644
--- a/src/android/org/linphone/LinphoneUtils.java
+++ b/src/android/org/linphone/LinphoneUtils.java
@@ -628,11 +628,7 @@ public final class LinphoneUtils {
if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
- final String type = split[0];
-
- if ("primary".equalsIgnoreCase(type)) {
- return Environment.getExternalStorageDirectory() + "/" + split[1];
- }
+ if (split.length >= 1) return Environment.getExternalStorageDirectory() + "/" + split[1];
// TODO handle non-primary volumes
}// Docs storage
diff --git a/src/android/org/linphone/activities/LinphoneActivity.java b/src/android/org/linphone/activities/LinphoneActivity.java
index 4ced21cb8..8d27f70df 100644
--- a/src/android/org/linphone/activities/LinphoneActivity.java
+++ b/src/android/org/linphone/activities/LinphoneActivity.java
@@ -373,7 +373,8 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
}
private void changeCurrentFragment(FragmentsAvailable newFragmentType, Bundle extras, boolean withoutAnimation) {
- if (newFragmentType == currentFragment && newFragmentType != FragmentsAvailable.CHAT) {
+ if (newFragmentType == currentFragment && newFragmentType != FragmentsAvailable.CHAT
+ && newFragmentType != FragmentsAvailable.GROUP_CHAT) {
return;
}
diff --git a/src/android/org/linphone/assistant/AssistantActivity.java b/src/android/org/linphone/assistant/AssistantActivity.java
index 409c7f3d6..3ed24da84 100644
--- a/src/android/org/linphone/assistant/AssistantActivity.java
+++ b/src/android/org/linphone/assistant/AssistantActivity.java
@@ -677,7 +677,7 @@ private static AssistantActivity instance;
private void goToLinphoneActivity() {
mPrefs.firstLaunchSuccessful();
- setResult(Activity.RESULT_OK, new Intent().putExtra("isNewProxyConfig", true));
+ startActivity(new Intent().setClass(this, LinphoneActivity.class).putExtra("isNewProxyConfig", true));
finish();
}
diff --git a/src/android/org/linphone/call/CallActivity.java b/src/android/org/linphone/call/CallActivity.java
index fba1bb537..2fe3a2db2 100644
--- a/src/android/org/linphone/call/CallActivity.java
+++ b/src/android/org/linphone/call/CallActivity.java
@@ -71,6 +71,7 @@ import org.linphone.activities.LinphoneActivity;
import org.linphone.activities.LinphoneGenericActivity;
import org.linphone.core.Address;
import org.linphone.core.Call;
+import org.linphone.core.CallListenerStub;
import org.linphone.core.Call.State;
import org.linphone.core.CallParams;
import org.linphone.core.CallStats;
@@ -138,6 +139,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
private TimerTask mTask;
private HashMap mEncoderTexts;
private HashMap mDecoderTexts;
+ private CallListenerStub mCallListener;
private boolean oldIsSpeakerEnabled = false;
@@ -229,7 +231,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
boolean remoteVideo = call.getRemoteParams().videoEnabled();
boolean localVideo = call.getCurrentParams().videoEnabled();
boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests();
- if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !(LinphoneManager.getLc().getConference() != null)) {
+ if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
showAcceptCallUpdateDialog();
createTimerForDialog(SECONDS_BEFORE_DENYING_CALL_UPDATE);
}
@@ -591,7 +593,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
private void enableAndRefreshInCallActions() {
int confsize = 0;
- if( LinphoneManager.getLc().getConference() != null) {
+ if(LinphoneManager.getLc().isInConference()) {
confsize = LinphoneManager.getLc().getConferenceSize() - (LinphoneManager.getLc().getConference() != null ? 1 : 0);
}
@@ -951,7 +953,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
if (currentCall != null) {
lc.terminateCall(currentCall);
- } else if (lc.getConference() != null) {
+ } else if (lc.isInConference()) {
lc.terminateConference();
} else {
lc.terminateAllCalls();
@@ -1412,7 +1414,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
}
public void refreshCallList(Resources resources) {
- isConferenceRunning = LinphoneManager.getLc().getConference() != null;
+ isConferenceRunning = LinphoneManager.getLc().isInConference();
List pausedCalls = LinphoneUtils.getCallsInState(LinphoneManager.getLc(), Arrays.asList(State.PausedByRemote));
//MultiCalls
@@ -1489,7 +1491,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
private void exitConference(final Call call){
Core lc = LinphoneManager.getLc();
- if (call.getConference() != null) {
+ if (lc.isInConference()) {
lc.removeFromConference(call);
if (lc.getConferenceSize() <= 1) {
lc.leaveConference();
@@ -1506,7 +1508,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
Core lc = LinphoneManager.getLc();
conferenceStatus = (ImageView) findViewById(R.id.conference_pause);
if(conferenceStatus != null) {
- if (lc.getConference() != null) {
+ if (lc.isInConference()) {
conferenceStatus.setImageResource(R.drawable.pause_big_over_selected);
lc.leaveConference();
} else {
@@ -1706,6 +1708,16 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
final View videoLayout = view.findViewById(R.id.callStatsVideo);
final View audioLayout = view.findViewById(R.id.callStatsAudio);
+ mCallListener = new CallListenerStub(){
+ public void onStateChanged(Call call, Call.State cstate, String message){
+ if (cstate == Call.State.End || cstate == Call.State.Error){
+ if (mTimer != null) {
+ Log.i("Call is terminated, stopping timer in charge of stats refreshing.");
+ mTimer.cancel();
+ }
+ }
+ }
+ };
mTimer = new Timer();
mTask = new TimerTask() {
@@ -1762,6 +1774,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
});
}
};
+ call.addListener(mCallListener);
mTimer.scheduleAtFixedRate(mTask, 0, 1000);
}
diff --git a/src/android/org/linphone/chat/GroupChatFragment.java b/src/android/org/linphone/chat/GroupChatFragment.java
index e40b66019..046d09e5d 100644
--- a/src/android/org/linphone/chat/GroupChatFragment.java
+++ b/src/android/org/linphone/chat/GroupChatFragment.java
@@ -491,7 +491,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
//TODO error
return;
}
- Address proxyConfigContact = core.getDefaultProxyConfig().getContact();
+ Address proxyConfigContact = (core.getDefaultProxyConfig() != null) ? core.getDefaultProxyConfig().getContact() : null;
if (proxyConfigContact != null) {
mChatRoom = core.findOneToOneChatRoom(proxyConfigContact, mRemoteSipAddress);
}
diff --git a/src/android/org/linphone/contacts/ContactsManager.java b/src/android/org/linphone/contacts/ContactsManager.java
index c48ec134a..7d7802e82 100644
--- a/src/android/org/linphone/contacts/ContactsManager.java
+++ b/src/android/org/linphone/contacts/ContactsManager.java
@@ -264,11 +264,20 @@ public class ContactsManager extends ContentObserver {
}
public synchronized void setContacts(List c) {
- contacts = c;
+ if (contacts.isEmpty() || contacts.size() > c.size()) {
+ contacts = c;
+ } else {
+ for (LinphoneContact contact : c) {
+ if (!contacts.contains(contact)) {
+ contacts.add(contact);
+ }
+ }
+ }
+ Collections.sort(contacts);
}
public synchronized void setSipContacts(List c) {
- if (sipContacts.isEmpty()) {
+ if (sipContacts.isEmpty() || sipContacts.size() > c.size()) {
sipContacts = c;
} else {
for (LinphoneContact contact : c) {
@@ -277,6 +286,7 @@ public class ContactsManager extends ContentObserver {
}
}
}
+ Collections.sort(sipContacts);
}
public synchronized void refreshSipContact(Friend lf) {
@@ -458,8 +468,6 @@ public class ContactsManager extends ContentObserver {
Log.w("[Permission] Read contacts permission wasn't granted, only fetch Friends");
}
- Collections.sort(contacts);
- Collections.sort(sipContacts);
setContacts(contacts);
setSipContacts(sipContacts);
diff --git a/src/android/org/linphone/contacts/LinphoneContact.java b/src/android/org/linphone/contacts/LinphoneContact.java
index 0b83dffa8..0c5f5399a 100644
--- a/src/android/org/linphone/contacts/LinphoneContact.java
+++ b/src/android/org/linphone/contacts/LinphoneContact.java
@@ -75,6 +75,13 @@ public class LinphoneContact implements Serializable, Comparable
-
-
--
-
--
-+ -->
-
-