Merge branch 'master' of gitlab.linphone.org:BC/public/linphone-android into dev_qrcode

This commit is contained in:
Erwan Croze 2018-06-27 10:06:58 +02:00
commit 75a01ef68e
38 changed files with 211 additions and 192 deletions

View file

@ -2,12 +2,12 @@
<manifest package="org.linphone" <manifest package="org.linphone"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="3996" android:versionCode="4001"
android:versionName="3.99.5"> android:versionName="4.0.0">
<uses-sdk <uses-sdk
android:minSdkVersion="16" android:minSdkVersion="16"
android:targetSdkVersion="26"/> android:targetSdkVersion="28"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/>

11
AndroidManifestSdk.xml Executable file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.linphone"
xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
android:versionCode="4001"
android:versionName="4.0.0">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="28"/>
</manifest>

View file

@ -5,13 +5,34 @@ Group changes to describe their impact on the project, as follows:
Added for new features. Added for new features.
Changed for changes in existing functionality. Changed for changes in existing functionality.
Deprecated for once-stable features removed in upcoming releases.é Deprecated for once-stable features removed in upcoming releases.
Removed for deprecated features removed in this release. Removed for deprecated features removed in this release.
Fixed for any bug fixes. Fixed for any bug fixes.
Security to invite users to upgrade in case of vulnerabilities. Security to invite users to upgrade in case of vulnerabilities.
## [Incomming] ## [Incomming]
## [4.0.1] - 2018-06-26
### Fixed
- fix loading of plugins
- fix issue with video stream, not started when receiving an incoming call just after the app is launched
- fix issue with TURN
## [4.0.0] - 2018-06-15
### Added
- Group chat between linphone.org SIP accounts.
- new JAVA/JNI wrapper. This new wrapper is automatically generated from liblinphone C API. It breaks compatibility with previous, hand-made wrapper.
(more information about new wrapper [here.](https://wiki.linphone.org/xwiki/wiki/public/view/Lib/Linphone%20%28Android%29%20Java%20wrapper/) )
### Deprecated
- hand-made java API in submodules/linphone/java is deprecated. However it is still possible to use it by checking out the 3.4.x branch of linphone-android.
### Fixed
- issue with changing push notification token not passed to library, possibly resulting in a loss of incoming calls.
## [3.3.0] - 2017-10-18 ## [3.3.0] - 2017-10-18
### Added ### Added

View file

@ -1,14 +1,16 @@
[![pipeline status](https://gitlab.linphone.org/BC/public/linphone-android/badges/master/pipeline.svg)](https://gitlab.linphone.org/BC/public/linphone-android/commits/master)
Linphone is a free VoIP and video softphone based on the SIP protocol. Linphone is a free VoIP and video softphone based on the SIP protocol.
# COMPILATION INSTRUCTIONS # COMPILATION INSTRUCTIONS
## To build liblinphone for Android, you must: ## 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. * On 64 bits linux systems you'll need the _ia32-libs_ package.
* With the latest Debian (multiarch), you need this: * With the latest Debian (multiarch), you need this:
* `dpkg --add-architecture i386` * `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' 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' 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 # TROUBLESHOOTING
If you encounter the following issue: If you encounter the following issue:

View file

@ -47,7 +47,7 @@ dependencies {
if (firebaseEnable()) { if (firebaseEnable()) {
implementation 'com.google.firebase:firebase-messaging:15.0.2' 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') implementation project(':liblinphone-sdk')
} }
@ -78,7 +78,8 @@ excludePackage.add('**/LICENSE.txt')
android { android {
defaultConfig { defaultConfig {
compileSdkVersion 26 compileSdkVersion 28
buildToolsVersion "28.0.0"
applicationId getPackageName() applicationId getPackageName()
multiDexEnabled true multiDexEnabled true
@ -155,7 +156,7 @@ android {
packagingOptions { packagingOptions {
pickFirst 'META-INF/NOTICE' pickFirst 'META-INF/NOTICE'
pickFirst 'META-INF/LICENSE' pickFirst 'META-INF/LICENSE'
pickFirst 'META-INF/MANIFEST.MF' exclude 'META-INF/MANIFEST.MF'
} }
} }

View file

@ -2,10 +2,10 @@
<manifest package="org.linphone.core" <manifest package="org.linphone.core"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="3320" android:versionCode="4001"
android:versionName="3.3.2"> android:versionName="4.0.0">
<uses-sdk <uses-sdk
android:minSdkVersion="16" android:minSdkVersion="16"
android:targetSdkVersion="26"/> android:targetSdkVersion="28"/>
</manifest> </manifest>

View file

@ -54,7 +54,7 @@ else {
} }
srcDir += [rootSdk+'/share/linphonej/java/org/linphone/core/'] srcDir += [rootSdk+'/share/linphonej/java/org/linphone/core/']
srcDir += ['../submodules/linphone/wrappers/java/classes/']
def excludePackage = [] def excludePackage = []
@ -68,13 +68,34 @@ android {
buildTypes { buildTypes {
release {} release {}
debug{} debug {}
} }
defaultConfig { defaultConfig {
compileSdkVersion 26 compileSdkVersion 28
buildToolsVersion "26.0.0" buildToolsVersion "28.0.0"
multiDexEnabled true 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 { lintOptions {

View file

@ -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/rcfiles assets/config_files
cp -rf ../submodules/linphone/tester/sounds 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/vcards assets/config_files
cp -rf ../submodules/linphone/tester/db assets/config_files
mkdir -p res/raw mkdir -p res/raw
if test -d "../liblinphone-sdk/android-arm/share/belr/grammars"; then \ if test -d "../liblinphone-sdk/android-arm/share/belr/grammars"; then \
cp ../liblinphone-sdk/android-arm/share/belr/grammars/*_grammar res/raw/; \ cp ../liblinphone-sdk/android-arm/share/belr/grammars/*_grammar res/raw/; \

View file

@ -23,7 +23,7 @@ public class LogsActivity extends Activity {
@Override @Override
public void run() { public void run() {
String res_path = mLogsActivity.getFilesDir().getAbsolutePath()+"/config_files"; String res_path = mLogsActivity.getFilesDir().getAbsolutePath();
String write_path = mLogsActivity.getCacheDir().getPath(); String write_path = mLogsActivity.getCacheDir().getPath();
tester = new TesterLogger(mLogsActivity); tester = new TesterLogger(mLogsActivity);
List<String> list = new LinkedList<String>(Arrays.asList(new String[]{"tester", "--verbose", "--resource-dir", res_path, "--writable-dir", write_path})); List<String> list = new LinkedList<String>(Arrays.asList(new String[]{"tester", "--verbose", "--resource-dir", res_path, "--writable-dir", write_path}));

View file

@ -32,37 +32,13 @@ public class TestUnit extends AndroidTestCase {
} }
static public void copyAssetsFromPackage(Context ctx) throws IOException { 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 @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
@ -80,7 +56,7 @@ public class TestUnit extends AndroidTestCase {
@Override @Override
protected void runTest() { protected void runTest() {
String res_path = getContext().getFilesDir().getPath()+"/config_files"; String res_path = getContext().getFilesDir().getPath();
String write_path = getContext().getCacheDir().getPath(); String write_path = getContext().getCacheDir().getPath();
Tester tester = new Tester(); Tester tester = new Tester();

View file

@ -1,12 +1,8 @@
// Project information // Project information
buildDir = 'bin' buildDir = 'bin'
def firebaseEnable() {
File googleFile = new File('google-services.json')
return googleFile.exists()
}
buildscript { buildscript {
File googleFile = new File('google-services.json')
repositories { repositories {
jcenter() jcenter()
mavenCentral() mavenCentral()
@ -15,9 +11,6 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' 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' apply plugin: 'com.android.library'
dependencies { dependencies {
implementation group: 'org.apache.commons', name: 'commons-compress', version: '1.16.1' compile group: 'org.apache.commons', name: 'commons-compress', version: '1.16.1'
if (firebaseEnable()) { compile 'com.android.support:support-v4:26.0.2'
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'
} }
def srcDirs = ['submodules/mediastreamer2/java/src', 'src/linphone-wrapper', 'src/android'] def srcDirs = ['submodules/mediastreamer2/java/src', 'src/linphone-wrapper', 'src/android']
def excludeFiles = [] def excludeFiles = []
// Exclude firebase file if not enable
if (!firebaseEnable()) { excludeFiles.add('**/Firebase*')
excludeFiles.add('**/Firebase*') excludeFiles.add('**/gcm*')
} else {
excludeFiles.add('**/gcm*')
}
excludeFiles.add('**/mediastream/MediastreamerActivity.java') excludeFiles.add('**/mediastream/MediastreamerActivity.java')
def excludePackage = [] def excludePackage = []
@ -67,6 +49,7 @@ excludePackage.add('**/LICENSE.txt')
android { android {
defaultConfig { defaultConfig {
compileSdkVersion 26 compileSdkVersion 26
buildToolsVersion "27.0.3"
multiDexEnabled true multiDexEnabled true
} }
@ -79,7 +62,7 @@ android {
sourceSets { sourceSets {
main { main {
manifest.srcFile 'AndroidManifestLibrary.xml' manifest.srcFile 'AndroidManifestSdk.xml'
java.srcDirs = srcDirs java.srcDirs = srcDirs
resources.srcDirs = srcDirs resources.srcDirs = srcDirs
aidl.srcDirs = srcDirs aidl.srcDirs = srcDirs

View file

@ -144,7 +144,7 @@ class AndroidPreparator(prepare.Preparator):
retval = True retval = True
ndk_build = find_executable('ndk-build') ndk_build = find_executable('ndk-build')
ndk_path = os.path.dirname(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') release_file = os.path.join(ndk_path, 'RELEASE.TXT')
if os.path.isfile(release_file): if os.path.isfile(release_file):
version = open(release_file).read().strip() version = open(release_file).read().strip()
@ -368,11 +368,10 @@ generate-javadoc:
\t./gradlew -q androidJavadocsJar \t./gradlew -q androidJavadocsJar
\t./gradlew -q sourcesJar \t./gradlew -q sourcesJar
liblinphone-android-sdk: java-clean build copy-libs debug-sdk: java-clean build copy-libs generate-javadoc generate-apk
\t./gradlew -q androidJavadocsJar \t./gradlew -q sdkZip
\t./gradlew -q sourcesJar
\t./gradlew -q assembleRelease liblinphone-android-sdk: java-clean build copy-libs generate-javadoc release
\t@mv $(TOPDIR)/bin/outputs/aar/*.aar $(TOPDIR)/bin/outputs/aar/liblinphone-sdk.aar
\t./gradlew -q sdkZip \t./gradlew -q sdkZip
linphone-android-sdk: java-clean build copy-libs linphone-android-sdk: java-clean build copy-libs

View file

@ -12,7 +12,7 @@
<string name="tunnel_host"></string> <string name="tunnel_host"></string>
<string name="about_version">Linphone Android %s</string> <string name="about_version">Linphone Android %s</string>
<string name="about_liblinphone_version">Linphone Core %s</string> <string name="about_liblinphone_version">Linphone Core %s</string>
<string name="about_text">GNU General Public License V2\n © 2010-2017 Belledonne Communications</string> <string name="about_text">GNU General Public License V2\n © 2010-2018 Belledonne Communications</string>
<string name="about_link">www.linphone.org</string> <string name="about_link">www.linphone.org</string>
<string name="sync_account_name">linphone contacts</string> <string name="sync_account_name">linphone contacts</string>

View file

@ -584,7 +584,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
BluetoothManagerDestroy(); BluetoothManagerDestroy();
try { try {
mTimer.cancel(); mTimer.cancel();
mLc = null; destroyLinphoneCore();
} }
catch (RuntimeException e) { catch (RuntimeException e) {
Log.e(e); Log.e(e);
@ -623,6 +623,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
} }
} }
public void restartCore() { public void restartCore() {
destroyCore(); destroyCore();
startLibLinphone(mServiceContext); startLibLinphone(mServiceContext);
@ -906,50 +907,15 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
} }
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB) private void destroyLinphoneCore() {
private void doDestroy() { if (LinphonePreferences.instance() != null) {
ContactsManagerDestroy(); // We set network reachable at false before destroy LC to not send register with expires at 0
BluetoothManagerDestroy(); if (LinphonePreferences.instance().isPushNotificationEnabled()
try { || LinphonePreferences.instance().isBackgroundModeEnabled()) {
mTimer.cancel(); mLc.setNetworkReachable(false);
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;
} }
mLc = null;
} }
public void dozeManager(boolean enable) { public void dozeManager(boolean enable) {
@ -1035,7 +1001,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
if (instance == null) return; if (instance == null) return;
getInstance().changeStatusToOffline(); getInstance().changeStatusToOffline();
sExited = true; sExited = true;
instance.doDestroy(); instance.destroyCore();
} }
private String getString(int key) { private String getString(int key) {
@ -1809,4 +1775,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou
mUnreadChatsPerRoom.put(key, 1); mUnreadChatsPerRoom.put(key, 1);
} }
} }
public void onQrcodeFound(Core lc, String something){
}
} }

View file

@ -370,6 +370,13 @@ public class LinphonePreferences {
prxCfg.setQualityReportingCollector(tempQualityReportingCollector); prxCfg.setQualityReportingCollector(tempQualityReportingCollector);
prxCfg.setQualityReportingInterval(tempQualityReportingInterval); 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){ if(tempPrefix != null){
prxCfg.setDialPrefix(tempPrefix); prxCfg.setDialPrefix(tempPrefix);
} }

View file

@ -415,7 +415,7 @@ public final class LinphoneUtils {
String extension = LinphoneUtils.getExtensionFromFileName(path); String extension = LinphoneUtils.getExtensionFromFileName(path);
if(extension != null) if(extension != null)
extension = extension.toLowerCase(); extension = extension.toLowerCase();
return (extension != null && extension.matches(".*(png|jpg|jpeg|bmp|gif).*")); return (extension != null && extension.matches("(png|jpg|jpeg|bmp|gif)"));
} }
public static void recursiveFileRemoval(File root) { public static void recursiveFileRemoval(File root) {
@ -609,11 +609,7 @@ public final class LinphoneUtils {
if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
final String docId = DocumentsContract.getDocumentId(uri); final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":"); final String[] split = docId.split(":");
final String type = split[0]; if (split.length >= 1) return Environment.getExternalStorageDirectory() + "/" + split[1];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes // TODO handle non-primary volumes
}// Docs storage }// Docs storage

View file

@ -371,7 +371,8 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
} }
private void changeCurrentFragment(FragmentsAvailable newFragmentType, Bundle extras, boolean withoutAnimation) { 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; return;
} }

View file

@ -713,7 +713,7 @@ private static AssistantActivity instance;
private void goToLinphoneActivity() { private void goToLinphoneActivity() {
mPrefs.firstLaunchSuccessful(); mPrefs.firstLaunchSuccessful();
setResult(Activity.RESULT_OK, new Intent().putExtra("isNewProxyConfig", true)); startActivity(new Intent().setClass(this, LinphoneActivity.class).putExtra("isNewProxyConfig", true));
finish(); finish();
} }

View file

@ -71,6 +71,7 @@ import org.linphone.activities.LinphoneActivity;
import org.linphone.activities.LinphoneGenericActivity; import org.linphone.activities.LinphoneGenericActivity;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.core.CallListenerStub;
import org.linphone.core.Call.State; import org.linphone.core.Call.State;
import org.linphone.core.CallParams; import org.linphone.core.CallParams;
import org.linphone.core.CallStats; import org.linphone.core.CallStats;
@ -138,6 +139,8 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
private TimerTask mTask; private TimerTask mTask;
private HashMap<String, String> mEncoderTexts; private HashMap<String, String> mEncoderTexts;
private HashMap<String, String> mDecoderTexts; private HashMap<String, String> mDecoderTexts;
private CallListenerStub mCallListener;
private Call mCallDisplayedInStats;
private boolean oldIsSpeakerEnabled = false; private boolean oldIsSpeakerEnabled = false;
@ -229,7 +232,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
boolean remoteVideo = call.getRemoteParams().videoEnabled(); boolean remoteVideo = call.getRemoteParams().videoEnabled();
boolean localVideo = call.getCurrentParams().videoEnabled(); boolean localVideo = call.getCurrentParams().videoEnabled();
boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests(); boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests();
if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !(LinphoneManager.getLc().getConference() != null)) { if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
showAcceptCallUpdateDialog(); showAcceptCallUpdateDialog();
createTimerForDialog(SECONDS_BEFORE_DENYING_CALL_UPDATE); createTimerForDialog(SECONDS_BEFORE_DENYING_CALL_UPDATE);
} }
@ -591,7 +594,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
private void enableAndRefreshInCallActions() { private void enableAndRefreshInCallActions() {
int confsize = 0; int confsize = 0;
if( LinphoneManager.getLc().getConference() != null) { if(LinphoneManager.getLc().isInConference()) {
confsize = LinphoneManager.getLc().getConferenceSize() - (LinphoneManager.getLc().getConference() != null ? 1 : 0); confsize = LinphoneManager.getLc().getConferenceSize() - (LinphoneManager.getLc().getConference() != null ? 1 : 0);
} }
@ -951,7 +954,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
if (currentCall != null) { if (currentCall != null) {
lc.terminateCall(currentCall); lc.terminateCall(currentCall);
} else if (lc.getConference() != null) { } else if (lc.isInConference()) {
lc.terminateConference(); lc.terminateConference();
} else { } else {
lc.terminateAllCalls(); lc.terminateAllCalls();
@ -1412,7 +1415,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
} }
public void refreshCallList(Resources resources) { public void refreshCallList(Resources resources) {
isConferenceRunning = LinphoneManager.getLc().getConference() != null; isConferenceRunning = LinphoneManager.getLc().isInConference();
List<Call> pausedCalls = LinphoneUtils.getCallsInState(LinphoneManager.getLc(), Arrays.asList(State.PausedByRemote)); List<Call> pausedCalls = LinphoneUtils.getCallsInState(LinphoneManager.getLc(), Arrays.asList(State.PausedByRemote));
//MultiCalls //MultiCalls
@ -1489,7 +1492,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
private void exitConference(final Call call){ private void exitConference(final Call call){
Core lc = LinphoneManager.getLc(); Core lc = LinphoneManager.getLc();
if (call.getConference() != null) { if (lc.isInConference()) {
lc.removeFromConference(call); lc.removeFromConference(call);
if (lc.getConferenceSize() <= 1) { if (lc.getConferenceSize() <= 1) {
lc.leaveConference(); lc.leaveConference();
@ -1506,7 +1509,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
Core lc = LinphoneManager.getLc(); Core lc = LinphoneManager.getLc();
conferenceStatus = (ImageView) findViewById(R.id.conference_pause); conferenceStatus = (ImageView) findViewById(R.id.conference_pause);
if(conferenceStatus != null) { if(conferenceStatus != null) {
if (lc.getConference() != null) { if (lc.isInConference()) {
conferenceStatus.setImageResource(R.drawable.pause_big_over_selected); conferenceStatus.setImageResource(R.drawable.pause_big_over_selected);
lc.leaveConference(); lc.leaveConference();
} else { } else {
@ -1673,9 +1676,16 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
} }
public void initCallStatsRefresher(final Call call, final View view) { public void initCallStatsRefresher(final Call call, final View view) {
if (mCallDisplayedInStats == call) return;
if (mTimer != null && mTask != null) { if (mTimer != null && mTask != null) {
return; mTimer.cancel();
mTimer = null;
mTask = null;
} }
mCallDisplayedInStats = call;
if (call == null) return;
final TextView titleAudio = (TextView) view.findViewById(R.id.call_stats_audio); final TextView titleAudio = (TextView) view.findViewById(R.id.call_stats_audio);
final TextView titleVideo = (TextView) view.findViewById(R.id.call_stats_video); final TextView titleVideo = (TextView) view.findViewById(R.id.call_stats_video);
@ -1706,6 +1716,16 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
final View videoLayout = view.findViewById(R.id.callStatsVideo); final View videoLayout = view.findViewById(R.id.callStatsVideo);
final View audioLayout = view.findViewById(R.id.callStatsAudio); 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(); mTimer = new Timer();
mTask = new TimerTask() { mTask = new TimerTask() {
@ -1730,7 +1750,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
public void run() { public void run() {
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() == null) return; if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() == null) return;
synchronized(LinphoneManager.getLc()) { synchronized(LinphoneManager.getLc()) {
if (LinphoneActivity.isInstanciated()) { if (LinphoneActivity.isInstanciated() && call.getState() != Call.State.Released) {
CallParams params = call.getCurrentParams(); CallParams params = call.getCurrentParams();
if (params != null) { if (params != null) {
CallStats audioStats = call.getStats(StreamType.Audio); CallStats audioStats = call.getStats(StreamType.Audio);
@ -1762,6 +1782,7 @@ public class CallActivity extends LinphoneGenericActivity implements OnClickList
}); });
} }
}; };
call.addListener(mCallListener);
mTimer.scheduleAtFixedRate(mTask, 0, 1000); mTimer.scheduleAtFixedRate(mTask, 0, 1000);
} }

View file

@ -491,7 +491,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
//TODO error //TODO error
return; return;
} }
Address proxyConfigContact = core.getDefaultProxyConfig().getContact(); Address proxyConfigContact = (core.getDefaultProxyConfig() != null) ? core.getDefaultProxyConfig().getContact() : null;
if (proxyConfigContact != null) { if (proxyConfigContact != null) {
mChatRoom = core.findOneToOneChatRoom(proxyConfigContact, mRemoteSipAddress); mChatRoom = core.findOneToOneChatRoom(proxyConfigContact, mRemoteSipAddress);
} }

View file

@ -264,11 +264,20 @@ public class ContactsManager extends ContentObserver {
} }
public synchronized void setContacts(List<LinphoneContact> c) { public synchronized void setContacts(List<LinphoneContact> 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<LinphoneContact> c) { public synchronized void setSipContacts(List<LinphoneContact> c) {
if (sipContacts.isEmpty()) { if (sipContacts.isEmpty() || sipContacts.size() > c.size()) {
sipContacts = c; sipContacts = c;
} else { } else {
for (LinphoneContact contact : c) { for (LinphoneContact contact : c) {
@ -277,6 +286,7 @@ public class ContactsManager extends ContentObserver {
} }
} }
} }
Collections.sort(sipContacts);
} }
public synchronized void refreshSipContact(Friend lf) { 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"); Log.w("[Permission] Read contacts permission wasn't granted, only fetch Friends");
} }
Collections.sort(contacts);
Collections.sort(sipContacts);
setContacts(contacts); setContacts(contacts);
setSipContacts(sipContacts); setSipContacts(sipContacts);

View file

@ -75,6 +75,13 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
return fullName.compareTo(contactFullName); return fullName.compareTo(contactFullName);
} }
@Override
public boolean equals(Object obj) {
if (obj.getClass() != LinphoneContact.class) return false;
LinphoneContact contact = (LinphoneContact) obj;
return (this.compareTo(contact) == 0);
}
public void setFullName(String name) { public void setFullName(String name) {
fullName = name; fullName = name;
} }

View file

@ -40,13 +40,20 @@ public class LinphoneNumberOrAddress implements Serializable, Comparable<Linphon
@Override @Override
public int compareTo(LinphoneNumberOrAddress noa) { public int compareTo(LinphoneNumberOrAddress noa) {
if (noa.isSIPAddress() == isSIPAddress()) { if (noa.isSIPAddress() == isSIPAddress() && noa.getValue() != null) {
return noa.getValue().compareTo(getValue()); return noa.getValue().compareTo(getValue());
} else { } else {
return isSIPAddress() ? -1 : 1; return isSIPAddress() ? -1 : 1;
} }
} }
@Override
public boolean equals(Object obj) {
if (obj.getClass() != LinphoneNumberOrAddress.class) return false;
LinphoneNumberOrAddress noa = (LinphoneNumberOrAddress) obj;
return (this != null && this.compareTo(noa) == 0);
}
public boolean isSIPAddress() { public boolean isSIPAddress() {
return isSIPAddress; return isSIPAddress;
} }

View file

@ -39,6 +39,7 @@ public class FirebaseMessaging extends FirebaseMessagingService {
android.util.Log.i("FirebaseMessaging","[Push Notification] Received"); android.util.Log.i("FirebaseMessaging","[Push Notification] Received");
if (!LinphoneService.isReady()) { if (!LinphoneService.isReady()) {
android.util.Log.i("FirebaseMessaging","[Push Notification] Starting Service");
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class)); startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
} else if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) { } else if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) {
LinphoneUtils.dispatchOnUIThread(new Runnable(){ LinphoneUtils.dispatchOnUIThread(new Runnable(){

View file

@ -40,6 +40,8 @@ import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
@ -49,6 +51,7 @@ import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener; import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
@ -350,7 +353,7 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
accountCreator.setListener(this); accountCreator.setListener(this);
PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_sipaccount_key)); final PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_sipaccount_key));
EditTextPreference username = (EditTextPreference) account.getPreference(0); EditTextPreference username = (EditTextPreference) account.getPreference(0);
username.setOnPreferenceChangeListener(usernameChangedListener); username.setOnPreferenceChangeListener(usernameChangedListener);
if (!isNewAccount){ if (!isNewAccount){
@ -485,8 +488,10 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
mainAccount.setEnabled(!mainAccount.isChecked()); mainAccount.setEnabled(!mainAccount.isChecked());
} }
//final AccountCreatorListener fragment = this;
final Preference changePassword = manage.getPreference(2); final Preference changePassword = manage.getPreference(2);
if (mPrefs.getAccountDomain(n).compareTo(getString(R.string.default_domain)) == 0) { /*if (mPrefs.getAccountDomain(n).compareTo(getString(R.string.default_domain)) == 0) {
changePassword.setEnabled(!isNewAccount); changePassword.setEnabled(!isNewAccount);
changePassword.setOnPreferenceClickListener(new OnPreferenceClickListener() { changePassword.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
@ -501,15 +506,19 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
dialog.dismiss(); dialog.dismiss();
} }
}); });
/*alert.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
alert.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
AccountCreator.PasswordStatus status = accountCreator.setPassword(pass1.getText().toString()); AccountCreator.PasswordStatus status = accountCreator.setPassword(pass1.getText().toString());
if (status.equals(AccountCreator.PasswordStatus.Ok)) { if (status.equals(AccountCreator.PasswordStatus.Ok)) {
if (pass1.getText().toString().compareTo(pass2.getText().toString()) == 0) { if (pass1.getText().toString().compareTo(pass2.getText().toString()) == 0) {
accountCreator.setUsername(mPrefs.getAccountUsername(n)); accountCreator.setUsername(mPrefs.getAccountUsername(n));
accountCreator.setDomain(mPrefs.getAccountDomain(n));
accountCreator.setHa1(mPrefs.getAccountHa1(n)); accountCreator.setHa1(mPrefs.getAccountHa1(n));
AccountCreator.Status req_status = accountCreator.updatePassword(pass1.getText().toString()); accountCreator.setListener(fragment);
accountCreator.setPassword(pass1.getText().toString());
AccountCreator.Status req_status = accountCreator.updateAccount();
if (!req_status.equals(AccountCreator.Status.RequestOk)) { if (!req_status.equals(AccountCreator.Status.RequestOk)) {
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(req_status) LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(req_status)
, LinphoneActivity.instance()); , LinphoneActivity.instance());
@ -532,14 +541,14 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
} }
});*/ // TODO FIXME });*/ // TODO FIXME
alert.setView(layout); /*alert.setView(layout);
alert.show(); alert.show();
return true; return true;
} }
}); });
} else { } else {*/
changePassword.setEnabled(false); changePassword.setEnabled(false);
} //}
final Preference delete = manage.getPreference(3); final Preference delete = manage.getPreference(3);
delete.setEnabled(!isNewAccount); delete.setEnabled(!isNewAccount);

View file

@ -476,7 +476,7 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address);
String displayName = null; String displayName = null;
final String sipUri = address.asString(); final String sipUri = (address != null) ? address.asString() : "";
if (c != null) { if (c != null) {
displayName = c.getFullName(); displayName = c.getFullName();
LinphoneUtils.setThumbnailPictureFromUri(LinphoneActivity.instance(), holder.contactPicture, c.getThumbnailUri()); LinphoneUtils.setThumbnailPictureFromUri(LinphoneActivity.instance(), holder.contactPicture, c.getThumbnailUri());

View file

@ -840,6 +840,12 @@ public class SettingsFragment extends PreferencesListFragment {
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean enable = (Boolean) newValue; boolean enable = (Boolean) newValue;
mPrefs.enableVideo(enable); mPrefs.enableVideo(enable);
if (!enable) {
mPrefs.setInitiateVideoCall(false);
mPrefs.setAutomaticallyAcceptVideoRequests(false);
((CheckBoxPreference) findPreference(getString(R.string.pref_video_initiate_call_with_video_key))).setChecked(mPrefs.shouldInitiateVideoCall());
((CheckBoxPreference) findPreference(getString(R.string.pref_video_automatically_accept_video_key))).setChecked(mPrefs.shouldAutomaticallyAcceptVideoRequests());
}
return true; return true;
} }
}); });

@ -1 +1 @@
Subproject commit 06cd2b31438ac632520ebce25796cf6e2ab5a759 Subproject commit ed53ae3c9da4fb15c13454153383014b3257939a

@ -1 +1 @@
Subproject commit b1622d7ddf1cbe6a0f929537861dfa8b45b293c4 Subproject commit ab5416d66620f32ff6882b6e29dec63203dbca41

@ -1 +1 @@
Subproject commit d7b16228a2746644a5dea76be9fff45708773130 Subproject commit 0f999ecc3d304923b6338d3f48d44ac8ddfd9be8

@ -1 +1 @@
Subproject commit 8e841b047641b1812a83880a90e89d702747ca5b Subproject commit cfad8fcc28c7cdba69684c8e35846711aaa16775

@ -1 +1 @@
Subproject commit d9385339a5c2979786cfc844c0527593c14662c5 Subproject commit 83d21d543c26a31943b2bd08c66b029f2ef742be

@ -1 +1 @@
Subproject commit 4a5ea6a64043038f4a4ac0f18d54db02a08d9b92 Subproject commit a1e31c958811b2a03571f5d824913be940288e93

@ -1 +1 @@
Subproject commit 9d5bfe077dc53968ea1a4b386be7a2af14121aa0 Subproject commit 8906fb7b243fa455fd9b091e4ac611536b2dbba4

@ -1 +1 @@
Subproject commit b0f5d446a1b062736a55e681030049f4f4ce4a33 Subproject commit 61e38e3704e1a37c9e884897ca5597158725b202

@ -1 +1 @@
Subproject commit 3dc9288523c1108bc3366a462ffb2944da15a2f3 Subproject commit 54a79f731fea61d345dfff4f8fcb2fc390c2fed7

@ -1 +1 @@
Subproject commit 1fcd6fd1558f26255ae9dac687191ddf988bfd5b Subproject commit 3afc47570a1c9f34bd2f1a759ae00fb7ecd26a0e

View file

@ -1,23 +0,0 @@
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9ee95b62..bb763a24 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -287,15 +287,15 @@
</intent-filter>
</service>
- <provider
+ <!--<provider
android:name="android.support.v4.content.FileProvider"
- android:authorities="org.linphone.provider"
+ android:authorities="org.linphone.provider${linphone_app_id}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
- </provider>
+ </provider>-->
<activity
android:name=".tutorials.TutorialLauncherActivity"