Merge branch 'release/4.2'
This commit is contained in:
commit
3c93974534
122 changed files with 1823 additions and 1092 deletions
|
@ -8,3 +8,4 @@ type = ANDROID
|
||||||
file_filter = app/src/main/res/values-<lang>/strings.xml
|
file_filter = app/src/main/res/values-<lang>/strings.xml
|
||||||
source_file = app/src/main/res/values/strings.xml
|
source_file = app/src/main/res/values/strings.xml
|
||||||
source_lang = en
|
source_lang = en
|
||||||
|
|
||||||
|
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -12,6 +12,14 @@ Group changes to describe their impact on the project, as follows:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
-
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
-
|
||||||
|
|
||||||
|
## [4.2.0] - 2019-12-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Added shortcuts to contacts' latest chat rooms
|
- Added shortcuts to contacts' latest chat rooms
|
||||||
- Improved device's do not disturb policy compliance
|
- Improved device's do not disturb policy compliance
|
||||||
|
@ -22,8 +30,10 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Using new AAudio & Camera2 frameworks for better performances (if available)
|
- Using new AAudio & Camera2 frameworks for better performances (if available)
|
||||||
- Android 10 compatibility
|
- Android 10 compatibility
|
||||||
- New plugin loader to be compatible with app bundle distribution mode
|
- New plugin loader to be compatible with app bundle distribution mode
|
||||||
|
- Restart service if foreground service setting is on when app is updated
|
||||||
|
- Change bluetooth volume while in call if BT device connected and used
|
||||||
|
|
||||||
## Changed
|
### Changed
|
||||||
- Improved performances to reduce startup time
|
- Improved performances to reduce startup time
|
||||||
- Call statistics are now available for each call & conference
|
- Call statistics are now available for each call & conference
|
||||||
- Added our own devices in LIME encrypted chatrooms' security view
|
- Added our own devices in LIME encrypted chatrooms' security view
|
||||||
|
|
30
README.md
30
README.md
|
@ -1,6 +1,34 @@
|
||||||
|
|
||||||
[](https://gitlab.linphone.org/BC/public/linphone-android/commits/master)
|
[](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 an open source softphone for voice and video over IP calling and instant messaging.
|
||||||
|
|
||||||
|
It is fully SIP-based, for all calling, presence and IM features.
|
||||||
|
|
||||||
|
General description is available from [linphone web site](https://www.linphone.org/technical-corner/linphone)
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
Copyright © Belledonne Communications
|
||||||
|
|
||||||
|
Linphone is dual licensed, and is available either :
|
||||||
|
|
||||||
|
- under a [GNU/GPLv3 license](https://www.gnu.org/licenses/gpl-3.0.en.html), for free (open source). Please make sure that you
|
||||||
|
|
||||||
|
understand and agree with the terms of this license before using it (see LICENSE file for
|
||||||
|
|
||||||
|
details).
|
||||||
|
|
||||||
|
- under a proprietary license, for a fee, to be used in closed source applications. Contact
|
||||||
|
|
||||||
|
[Belledonne Communications](https://www.linphone.org/contact) for any question about costs and services.
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Supported features and RFCs : https://www.linphone.org/technical-corner/linphone/features
|
||||||
|
|
||||||
|
- Linphone public wiki : https://wiki.linphone.org/xwiki/wiki/public/view/Linphone/
|
||||||
|
|
||||||
# What's new
|
# What's new
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,7 @@ excludePackage.add('**/LICENSE.txt')
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
// Replace snapshots by releases for releases !
|
url "https://linphone.org/maven_repository"
|
||||||
url "https://linphone.org/snapshots/maven_repository"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +88,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 4129
|
versionCode 4213
|
||||||
versionName "${project.version}"
|
versionName "${project.version}"
|
||||||
applicationId getPackageName()
|
applicationId getPackageName()
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
|
@ -64,7 +64,8 @@
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
android:theme="@style/LinphoneStyle">
|
android:theme="@style/LinphoneStyle"
|
||||||
|
android:requestLegacyExternalStorage="true">
|
||||||
|
|
||||||
<!-- Starting activities -->
|
<!-- Starting activities -->
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@
|
||||||
<!-- Main activities -->
|
<!-- Main activities -->
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.DialerActivity"
|
android:name=".dialer.DialerActivity"
|
||||||
android:launchMode="singleTop">
|
android:launchMode="singleTop">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.DIAL" />
|
<action android:name="android.intent.action.DIAL" />
|
||||||
|
@ -211,7 +212,7 @@
|
||||||
<!-- Services -->
|
<!-- Services -->
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".LinphoneService"
|
android:name=".service.LinphoneService"
|
||||||
android:label="@string/service_name" />
|
android:label="@string/service_name" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
|
@ -252,9 +253,8 @@
|
||||||
<receiver android:name=".receivers.BootReceiver">
|
<receiver android:name=".receivers.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
|
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
|
|
@ -21,28 +21,33 @@ package org.linphone;
|
||||||
|
|
||||||
import static android.content.Intent.ACTION_MAIN;
|
import static android.content.Intent.ACTION_MAIN;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
|
import java.util.ArrayList;
|
||||||
import org.linphone.call.CallActivity;
|
import org.linphone.call.CallActivity;
|
||||||
import org.linphone.call.CallIncomingActivity;
|
import org.linphone.call.CallIncomingActivity;
|
||||||
import org.linphone.call.CallOutgoingActivity;
|
import org.linphone.call.CallOutgoingActivity;
|
||||||
import org.linphone.compatibility.Compatibility;
|
import org.linphone.compatibility.Compatibility;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
|
import org.linphone.core.ConfiguringState;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.Factory;
|
import org.linphone.core.Factory;
|
||||||
|
import org.linphone.core.GlobalState;
|
||||||
import org.linphone.core.LogLevel;
|
import org.linphone.core.LogLevel;
|
||||||
import org.linphone.core.LoggingService;
|
import org.linphone.core.LoggingService;
|
||||||
import org.linphone.core.LoggingServiceListener;
|
import org.linphone.core.LoggingServiceListener;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.mediastream.Version;
|
import org.linphone.mediastream.Version;
|
||||||
import org.linphone.notifications.NotificationsManager;
|
import org.linphone.notifications.NotificationsManager;
|
||||||
|
import org.linphone.service.LinphoneService;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
|
import org.linphone.utils.DeviceUtils;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
|
import org.linphone.utils.PushNotificationUtils;
|
||||||
|
|
||||||
public class LinphoneContext {
|
public class LinphoneContext {
|
||||||
private static LinphoneContext sInstance = null;
|
private static LinphoneContext sInstance = null;
|
||||||
|
@ -78,7 +83,7 @@ public class LinphoneContext {
|
||||||
private NotificationsManager mNotificationManager;
|
private NotificationsManager mNotificationManager;
|
||||||
private LinphoneManager mLinphoneManager;
|
private LinphoneManager mLinphoneManager;
|
||||||
private ContactsManager mContactsManager;
|
private ContactsManager mContactsManager;
|
||||||
private Class<? extends Activity> mIncomingReceivedActivity = CallIncomingActivity.class;
|
private final ArrayList<CoreStartedListener> mCoreStartedListeners;
|
||||||
|
|
||||||
public static boolean isReady() {
|
public static boolean isReady() {
|
||||||
return sInstance != null;
|
return sInstance != null;
|
||||||
|
@ -90,6 +95,7 @@ public class LinphoneContext {
|
||||||
|
|
||||||
public LinphoneContext(Context context) {
|
public LinphoneContext(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
mCoreStartedListeners = new ArrayList<>();
|
||||||
|
|
||||||
LinphonePreferences.instance().setContext(context);
|
LinphonePreferences.instance().setContext(context);
|
||||||
Factory.instance().setLogCollectionPath(context.getFilesDir().getAbsolutePath());
|
Factory.instance().setLogCollectionPath(context.getFilesDir().getAbsolutePath());
|
||||||
|
@ -100,23 +106,40 @@ public class LinphoneContext {
|
||||||
dumpDeviceInformation();
|
dumpDeviceInformation();
|
||||||
dumpLinphoneInformation();
|
dumpLinphoneInformation();
|
||||||
|
|
||||||
String incomingReceivedActivityName =
|
|
||||||
LinphonePreferences.instance().getActivityToLaunchOnIncomingReceived();
|
|
||||||
try {
|
|
||||||
mIncomingReceivedActivity =
|
|
||||||
(Class<? extends Activity>) Class.forName(incomingReceivedActivityName);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
sInstance = this;
|
sInstance = this;
|
||||||
Log.i("[Context] Ready");
|
Log.i("[Context] Ready");
|
||||||
|
|
||||||
mListener =
|
mListener =
|
||||||
new CoreListenerStub() {
|
new CoreListenerStub() {
|
||||||
|
@Override
|
||||||
|
public void onGlobalStateChanged(Core core, GlobalState state, String message) {
|
||||||
|
Log.i("[Context] Global state is [", state, "]");
|
||||||
|
|
||||||
|
if (state == GlobalState.On) {
|
||||||
|
for (CoreStartedListener listener : mCoreStartedListeners) {
|
||||||
|
listener.onCoreStarted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfiguringStatus(
|
||||||
|
Core core, ConfiguringState status, String message) {
|
||||||
|
Log.i("[Context] Configuring state is [", status, "]");
|
||||||
|
|
||||||
|
if (status == ConfiguringState.Successful) {
|
||||||
|
LinphonePreferences.instance()
|
||||||
|
.setPushNotificationEnabled(
|
||||||
|
LinphonePreferences.instance()
|
||||||
|
.isPushNotificationEnabled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCallStateChanged(
|
public void onCallStateChanged(
|
||||||
Core core, Call call, Call.State state, String message) {
|
Core core, Call call, Call.State state, String message) {
|
||||||
|
Log.i("[Context] Call state is [", state, "]");
|
||||||
|
|
||||||
if (mContext.getResources().getBoolean(R.bool.enable_call_notification)) {
|
if (mContext.getResources().getBoolean(R.bool.enable_call_notification)) {
|
||||||
mNotificationManager.displayCallNotification(call);
|
mNotificationManager.displayCallNotification(call);
|
||||||
}
|
}
|
||||||
|
@ -157,12 +180,28 @@ public class LinphoneContext {
|
||||||
|
|
||||||
mLinphoneManager = new LinphoneManager(context);
|
mLinphoneManager = new LinphoneManager(context);
|
||||||
mNotificationManager = new NotificationsManager(context);
|
mNotificationManager = new NotificationsManager(context);
|
||||||
|
|
||||||
|
if (DeviceUtils.isAppUserRestricted(mContext)) {
|
||||||
|
// See https://firebase.google.com/docs/cloud-messaging/android/receive#restricted
|
||||||
|
Log.w(
|
||||||
|
"[Context] Device has been restricted by user (Android 9+), push notifications won't work !");
|
||||||
|
}
|
||||||
|
|
||||||
|
int bucket = DeviceUtils.getAppStandbyBucket(mContext);
|
||||||
|
if (bucket > 0) {
|
||||||
|
Log.w(
|
||||||
|
"[Context] Device is in bucket "
|
||||||
|
+ Compatibility.getAppStandbyBucketNameFromValue(bucket));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PushNotificationUtils.isAvailable(mContext)) {
|
||||||
|
Log.w("[Context] Push notifications won't work !");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(boolean isPush) {
|
public void start(boolean isPush) {
|
||||||
Log.i("[Context] Starting");
|
Log.i("[Context] Starting, push status is ", isPush);
|
||||||
mLinphoneManager.startLibLinphone(isPush);
|
mLinphoneManager.startLibLinphone(isPush, mListener);
|
||||||
LinphoneManager.getCore().addListener(mListener);
|
|
||||||
|
|
||||||
mNotificationManager.onCoreReady();
|
mNotificationManager.onCoreReady();
|
||||||
|
|
||||||
|
@ -236,6 +275,14 @@ public class LinphoneContext {
|
||||||
return mContactsManager;
|
return mContactsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addCoreStartedListener(CoreStartedListener listener) {
|
||||||
|
mCoreStartedListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCoreStartedListener(CoreStartedListener listener) {
|
||||||
|
mCoreStartedListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
/* Log device related information */
|
/* Log device related information */
|
||||||
|
|
||||||
private void dumpDeviceInformation() {
|
private void dumpDeviceInformation() {
|
||||||
|
@ -266,7 +313,7 @@ public class LinphoneContext {
|
||||||
/* Call activities */
|
/* Call activities */
|
||||||
|
|
||||||
private void onIncomingReceived() {
|
private void onIncomingReceived() {
|
||||||
Intent intent = new Intent().setClass(mContext, mIncomingReceivedActivity);
|
Intent intent = new Intent(mContext, CallIncomingActivity.class);
|
||||||
// This flag is required to start an Activity from a Service context
|
// This flag is required to start an Activity from a Service context
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
mContext.startActivity(intent);
|
mContext.startActivity(intent);
|
||||||
|
@ -285,4 +332,8 @@ public class LinphoneContext {
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
mContext.startActivity(intent);
|
mContext.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface CoreStartedListener {
|
||||||
|
void onCoreStarted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,18 +45,18 @@ import java.util.Date;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import org.linphone.assistant.PhoneAccountLinkingAssistantActivity;
|
import org.linphone.assistant.PhoneAccountLinkingAssistantActivity;
|
||||||
|
import org.linphone.call.AndroidAudioManager;
|
||||||
import org.linphone.call.CallManager;
|
import org.linphone.call.CallManager;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.core.AccountCreator;
|
import org.linphone.core.AccountCreator;
|
||||||
import org.linphone.core.AccountCreatorListenerStub;
|
import org.linphone.core.AccountCreatorListenerStub;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.Call.State;
|
import org.linphone.core.Call.State;
|
||||||
import org.linphone.core.ConfiguringState;
|
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
|
import org.linphone.core.CoreListener;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.Factory;
|
import org.linphone.core.Factory;
|
||||||
import org.linphone.core.FriendList;
|
import org.linphone.core.FriendList;
|
||||||
import org.linphone.core.GlobalState;
|
|
||||||
import org.linphone.core.PresenceActivity;
|
import org.linphone.core.PresenceActivity;
|
||||||
import org.linphone.core.PresenceBasicStatus;
|
import org.linphone.core.PresenceBasicStatus;
|
||||||
import org.linphone.core.PresenceModel;
|
import org.linphone.core.PresenceModel;
|
||||||
|
@ -68,7 +68,6 @@ import org.linphone.core.VersionUpdateCheckResult;
|
||||||
import org.linphone.core.tools.H264Helper;
|
import org.linphone.core.tools.H264Helper;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.AndroidAudioManager;
|
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.utils.MediaScanner;
|
import org.linphone.utils.MediaScanner;
|
||||||
import org.linphone.utils.PushNotificationUtils;
|
import org.linphone.utils.PushNotificationUtils;
|
||||||
|
@ -160,37 +159,6 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
|
|
||||||
mCoreListener =
|
mCoreListener =
|
||||||
new CoreListenerStub() {
|
new CoreListenerStub() {
|
||||||
@Override
|
|
||||||
public void onGlobalStateChanged(
|
|
||||||
final Core core, final GlobalState state, final String message) {
|
|
||||||
Log.i("New global state [", state, "]");
|
|
||||||
if (state == GlobalState.On) {
|
|
||||||
try {
|
|
||||||
initLiblinphone(core);
|
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
Log.e(
|
|
||||||
"[Manager] Global State Changed Illegal Argument Exception: "
|
|
||||||
+ iae);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfiguringStatus(
|
|
||||||
Core core, ConfiguringState state, String message) {
|
|
||||||
Log.d(
|
|
||||||
"[Manager] Remote provisioning status = "
|
|
||||||
+ state.toString()
|
|
||||||
+ " ("
|
|
||||||
+ message
|
|
||||||
+ ")");
|
|
||||||
|
|
||||||
LinphonePreferences prefs = LinphonePreferences.instance();
|
|
||||||
if (state == ConfiguringState.Successful) {
|
|
||||||
prefs.setPushNotificationEnabled(prefs.isPushNotificationEnabled());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("Wakelock")
|
@SuppressLint("Wakelock")
|
||||||
@Override
|
@Override
|
||||||
public void onCallStateChanged(
|
public void onCallStateChanged(
|
||||||
|
@ -198,7 +166,7 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
final Call call,
|
final Call call,
|
||||||
final State state,
|
final State state,
|
||||||
final String message) {
|
final String message) {
|
||||||
Log.i("[Manager] New call state [", state, "]");
|
Log.i("[Manager] Call state is [", state, "]");
|
||||||
if (state == State.IncomingReceived
|
if (state == State.IncomingReceived
|
||||||
&& !call.equals(core.getCurrentCall())) {
|
&& !call.equals(core.getCurrentCall())) {
|
||||||
if (call.getReplacedCall() != null) {
|
if (call.getReplacedCall() != null) {
|
||||||
|
@ -388,6 +356,7 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restartCore() {
|
public void restartCore() {
|
||||||
|
Log.w("[Manager] Restarting Core");
|
||||||
mCore.stop();
|
mCore.stop();
|
||||||
mCore.start();
|
mCore.start();
|
||||||
}
|
}
|
||||||
|
@ -395,8 +364,8 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
private void destroyCore() {
|
private void destroyCore() {
|
||||||
Log.w("[Manager] Destroying Core");
|
Log.w("[Manager] Destroying Core");
|
||||||
if (LinphonePreferences.instance() != null) {
|
if (LinphonePreferences.instance() != null) {
|
||||||
// We set network reachable at false before destroy LC to not send register with expires
|
// We set network reachable at false before destroying the Core
|
||||||
// at 0
|
// to not send a register with expires at 0
|
||||||
if (LinphonePreferences.instance().isPushNotificationEnabled()) {
|
if (LinphonePreferences.instance().isPushNotificationEnabled()) {
|
||||||
Log.w(
|
Log.w(
|
||||||
"[Manager] Setting network reachability to False to prevent unregister and allow incoming push notifications");
|
"[Manager] Setting network reachability to False to prevent unregister and allow incoming push notifications");
|
||||||
|
@ -429,7 +398,7 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void startLibLinphone(boolean isPush) {
|
public synchronized void startLibLinphone(boolean isPush, CoreListener listener) {
|
||||||
try {
|
try {
|
||||||
mCore =
|
mCore =
|
||||||
Factory.instance()
|
Factory.instance()
|
||||||
|
@ -437,6 +406,7 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
mPrefs.getLinphoneDefaultConfig(),
|
mPrefs.getLinphoneDefaultConfig(),
|
||||||
mPrefs.getLinphoneFactoryConfig(),
|
mPrefs.getLinphoneFactoryConfig(),
|
||||||
mContext);
|
mContext);
|
||||||
|
mCore.addListener(listener);
|
||||||
mCore.addListener(mCoreListener);
|
mCore.addListener(mCoreListener);
|
||||||
|
|
||||||
if (isPush) {
|
if (isPush) {
|
||||||
|
@ -466,6 +436,8 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
/*use schedule instead of scheduleAtFixedRate to avoid iterate from being call in burst after cpu wake up*/
|
/*use schedule instead of scheduleAtFixedRate to avoid iterate from being call in burst after cpu wake up*/
|
||||||
mTimer = new Timer("Linphone scheduler");
|
mTimer = new Timer("Linphone scheduler");
|
||||||
mTimer.schedule(lTask, 0, 20);
|
mTimer.schedule(lTask, 0, 20);
|
||||||
|
|
||||||
|
configureCore();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(e, "[Manager] Cannot start linphone");
|
Log.e(e, "[Manager] Cannot start linphone");
|
||||||
}
|
}
|
||||||
|
@ -474,8 +446,8 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
H264Helper.setH264Mode(H264Helper.MODE_AUTO, mCore);
|
H264Helper.setH264Mode(H264Helper.MODE_AUTO, mCore);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void initLiblinphone(Core core) {
|
private synchronized void configureCore() {
|
||||||
mCore = core;
|
Log.i("[Manager] Configuring Core");
|
||||||
mAudioManager = new AndroidAudioManager(mContext);
|
mAudioManager = new AndroidAudioManager(mContext);
|
||||||
|
|
||||||
mCore.setZrtpSecretsFile(mBasePath + "/zrtp_secrets");
|
mCore.setZrtpSecretsFile(mBasePath + "/zrtp_secrets");
|
||||||
|
@ -544,6 +516,8 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
mAccountCreator = mCore.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
|
mAccountCreator = mCore.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
|
||||||
mAccountCreator.setListener(mAccountCreatorListener);
|
mAccountCreator.setListener(mAccountCreatorListener);
|
||||||
mCallGsmON = false;
|
mCallGsmON = false;
|
||||||
|
|
||||||
|
Log.i("[Manager] Core configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetCameraFromPreferences() {
|
public void resetCameraFromPreferences() {
|
||||||
|
@ -572,16 +546,28 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
|
|
||||||
/* Account linking */
|
/* Account linking */
|
||||||
|
|
||||||
|
public AccountCreator getAccountCreator() {
|
||||||
|
if (mAccountCreator == null) {
|
||||||
|
Log.w("[Manager] Account creator shouldn't be null !");
|
||||||
|
mAccountCreator =
|
||||||
|
mCore.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
|
||||||
|
mAccountCreator.setListener(mAccountCreatorListener);
|
||||||
|
}
|
||||||
|
return mAccountCreator;
|
||||||
|
}
|
||||||
|
|
||||||
public void isAccountWithAlias() {
|
public void isAccountWithAlias() {
|
||||||
if (mCore.getDefaultProxyConfig() != null) {
|
if (mCore.getDefaultProxyConfig() != null) {
|
||||||
long now = new Timestamp(new Date().getTime()).getTime();
|
long now = new Timestamp(new Date().getTime()).getTime();
|
||||||
if (mAccountCreator != null && LinphonePreferences.instance().getLinkPopupTime() == null
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
|
if (LinphonePreferences.instance().getLinkPopupTime() == null
|
||||||
|| Long.parseLong(LinphonePreferences.instance().getLinkPopupTime()) < now) {
|
|| Long.parseLong(LinphonePreferences.instance().getLinkPopupTime()) < now) {
|
||||||
mAccountCreator.setUsername(
|
accountCreator.reset();
|
||||||
|
accountCreator.setUsername(
|
||||||
LinphonePreferences.instance()
|
LinphonePreferences.instance()
|
||||||
.getAccountUsername(
|
.getAccountUsername(
|
||||||
LinphonePreferences.instance().getDefaultAccountIndex()));
|
LinphonePreferences.instance().getDefaultAccountIndex()));
|
||||||
mAccountCreator.isAccountExist();
|
accountCreator.isAccountExist();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LinphonePreferences.instance().setLinkPopupTime(null);
|
LinphonePreferences.instance().setLinkPopupTime(null);
|
||||||
|
@ -839,7 +825,7 @@ public class LinphoneManager implements SensorEventListener {
|
||||||
|
|
||||||
public void setCallGsmON(boolean on) {
|
public void setCallGsmON(boolean on) {
|
||||||
mCallGsmON = on;
|
mCallGsmON = on;
|
||||||
if (on) {
|
if (on && mCore != null) {
|
||||||
mCore.pauseAllCalls();
|
mCore.pauseAllCalls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@ import android.os.Bundle;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import org.linphone.LinphoneContext;
|
import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.service.LinphoneService;
|
||||||
|
|
||||||
public abstract class LinphoneGenericActivity extends ThemeableActivity {
|
public abstract class LinphoneGenericActivity extends ThemeableActivity {
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,8 +80,15 @@ public abstract class LinphoneGenericActivity extends ThemeableActivity {
|
||||||
if (!LinphoneContext.isReady()) {
|
if (!LinphoneContext.isReady()) {
|
||||||
new LinphoneContext(getApplicationContext());
|
new LinphoneContext(getApplicationContext());
|
||||||
LinphoneContext.instance().start(false);
|
LinphoneContext.instance().start(false);
|
||||||
|
Log.i("[Generic Activity] Context created & started");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i("[Generic Activity] Starting Service");
|
||||||
|
try {
|
||||||
startService(new Intent().setClass(this, LinphoneService.class));
|
startService(new Intent().setClass(this, LinphoneService.class));
|
||||||
|
} catch (IllegalStateException ise) {
|
||||||
|
Log.e("[Generic Activity] Couldn't start service, exception: ", ise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,15 +24,16 @@ import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.assistant.MenuAssistantActivity;
|
import org.linphone.assistant.MenuAssistantActivity;
|
||||||
import org.linphone.chat.ChatActivity;
|
import org.linphone.chat.ChatActivity;
|
||||||
import org.linphone.contacts.ContactsActivity;
|
import org.linphone.contacts.ContactsActivity;
|
||||||
|
import org.linphone.dialer.DialerActivity;
|
||||||
import org.linphone.history.HistoryActivity;
|
import org.linphone.history.HistoryActivity;
|
||||||
|
import org.linphone.service.LinphoneService;
|
||||||
|
import org.linphone.service.ServiceWaitThread;
|
||||||
|
import org.linphone.service.ServiceWaitThreadListener;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.ServiceWaitThread;
|
|
||||||
import org.linphone.utils.ServiceWaitThreadListener;
|
|
||||||
|
|
||||||
/** Creates LinphoneService and wait until Core is ready to start main Activity */
|
/** Creates LinphoneService and wait until Core is ready to start main Activity */
|
||||||
public class LinphoneLauncherActivity extends Activity implements ServiceWaitThreadListener {
|
public class LinphoneLauncherActivity extends Activity implements ServiceWaitThreadListener {
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.linphone.activities;
|
package org.linphone.activities;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
|
@ -46,7 +45,6 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneContext;
|
import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.call.CallActivity;
|
import org.linphone.call.CallActivity;
|
||||||
import org.linphone.call.CallIncomingActivity;
|
import org.linphone.call.CallIncomingActivity;
|
||||||
|
@ -66,6 +64,7 @@ import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.RegistrationState;
|
import org.linphone.core.RegistrationState;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.dialer.DialerActivity;
|
||||||
import org.linphone.fragments.EmptyFragment;
|
import org.linphone.fragments.EmptyFragment;
|
||||||
import org.linphone.fragments.StatusBarFragment;
|
import org.linphone.fragments.StatusBarFragment;
|
||||||
import org.linphone.history.HistoryActivity;
|
import org.linphone.history.HistoryActivity;
|
||||||
|
@ -74,7 +73,6 @@ import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.settings.SettingsActivity;
|
import org.linphone.settings.SettingsActivity;
|
||||||
import org.linphone.utils.DeviceUtils;
|
import org.linphone.utils.DeviceUtils;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.utils.PushNotificationUtils;
|
|
||||||
|
|
||||||
public abstract class MainActivity extends LinphoneGenericActivity
|
public abstract class MainActivity extends LinphoneGenericActivity
|
||||||
implements StatusBarFragment.MenuClikedListener, SideMenuFragment.QuitClikedListener {
|
implements StatusBarFragment.MenuClikedListener, SideMenuFragment.QuitClikedListener {
|
||||||
|
@ -276,23 +274,6 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
requestRequiredPermissions();
|
requestRequiredPermissions();
|
||||||
|
|
||||||
if (DeviceUtils.isAppUserRestricted(this)) {
|
|
||||||
// See https://firebase.google.com/docs/cloud-messaging/android/receive#restricted
|
|
||||||
Log.w(
|
|
||||||
"[Main Activity] Device has been restricted by user (Android 9+), push notifications won't work !");
|
|
||||||
}
|
|
||||||
|
|
||||||
int bucket = DeviceUtils.getAppStandbyBucket(this);
|
|
||||||
if (bucket > 0) {
|
|
||||||
Log.w(
|
|
||||||
"[Main Activity] Device is in bucket "
|
|
||||||
+ Compatibility.getAppStandbyBucketNameFromValue(bucket));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PushNotificationUtils.isAvailable(this)) {
|
|
||||||
Log.w("[Main Activity] Push notifications won't work !");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -443,10 +424,6 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
||||||
|
|
||||||
private void quit() {
|
private void quit() {
|
||||||
goHomeAndClearStack();
|
goHomeAndClearStack();
|
||||||
stopService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class));
|
|
||||||
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
|
||||||
am.killBackgroundProcesses(getString(R.string.sync_account_type));
|
|
||||||
android.os.Process.killProcess(android.os.Process.myPid());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tab, Top and Status bars
|
// Tab, Top and Status bars
|
||||||
|
@ -495,6 +472,14 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
||||||
return granted == PackageManager.PERMISSION_GRANTED;
|
return granted == PackageManager.PERMISSION_GRANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean checkPermissions(String[] permissions) {
|
||||||
|
boolean allGranted = true;
|
||||||
|
for (String permission : permissions) {
|
||||||
|
allGranted &= checkPermission(permission);
|
||||||
|
}
|
||||||
|
return allGranted;
|
||||||
|
}
|
||||||
|
|
||||||
public void requestPermissionIfNotGranted(String permission) {
|
public void requestPermissionIfNotGranted(String permission) {
|
||||||
if (!checkPermission(permission)) {
|
if (!checkPermission(permission)) {
|
||||||
Log.i("[Permission] Requesting " + permission + " permission");
|
Log.i("[Permission] Requesting " + permission + " permission");
|
||||||
|
|
|
@ -31,9 +31,11 @@ import android.widget.RelativeLayout;
|
||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.core.AccountCreator;
|
import org.linphone.core.AccountCreator;
|
||||||
import org.linphone.core.AccountCreatorListenerStub;
|
import org.linphone.core.AccountCreatorListenerStub;
|
||||||
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.DialPlan;
|
import org.linphone.core.DialPlan;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
|
@ -70,20 +72,26 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
|
accountCreator.reset();
|
||||||
mConnect.setEnabled(false);
|
mConnect.setEnabled(false);
|
||||||
|
|
||||||
if (mUsernameConnectionSwitch.isChecked()) {
|
if (mUsernameConnectionSwitch.isChecked()) {
|
||||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
accountCreator.setUsername(mUsername.getText().toString());
|
||||||
mAccountCreator.setPassword(mPassword.getText().toString());
|
accountCreator.setPassword(mPassword.getText().toString());
|
||||||
|
|
||||||
createProxyConfigAndLeaveAssistant();
|
createProxyConfigAndLeaveAssistant();
|
||||||
} else {
|
} else {
|
||||||
mAccountCreator.setUsername(mPhoneNumber.getText().toString());
|
accountCreator.setPhoneNumber(
|
||||||
|
mPhoneNumber.getText().toString(),
|
||||||
|
mPrefix.getText().toString());
|
||||||
|
accountCreator.setUsername(accountCreator.getPhoneNumber());
|
||||||
|
|
||||||
AccountCreator.Status status = mAccountCreator.recoverAccount();
|
AccountCreator.Status status = accountCreator.recoverAccount();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Account Connection] recoverAccount returned " + status);
|
Log.e(
|
||||||
|
"[Account Connection Assistant] recoverAccount returned "
|
||||||
|
+ status);
|
||||||
mConnect.setEnabled(true);
|
mConnect.setEnabled(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -202,7 +210,9 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onRecoverAccount(
|
public void onRecoverAccount(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Account Connection] onRecoverAccount status is " + status);
|
Log.i(
|
||||||
|
"[Account Connection Assistant] onRecoverAccount status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.RequestOk)) {
|
if (status.equals(AccountCreator.Status.RequestOk)) {
|
||||||
Intent intent =
|
Intent intent =
|
||||||
new Intent(
|
new Intent(
|
||||||
|
@ -222,7 +232,12 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
mAccountCreator.addListener(mListener);
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core != null) {
|
||||||
|
reloadLinphoneAccountCreatorConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccountCreator().addListener(mListener);
|
||||||
|
|
||||||
DialPlan dp = getDialPlanForCurrentCountry();
|
DialPlan dp = getDialPlanForCurrentCountry();
|
||||||
displayDialPlan(dp);
|
displayDialPlan(dp);
|
||||||
|
@ -236,7 +251,7 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mAccountCreator.removeListener(mListener);
|
getAccountCreator().removeListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,16 +21,16 @@ package org.linphone.assistant;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import java.util.Locale;
|
||||||
import org.linphone.LinphoneContext;
|
import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.DialerActivity;
|
|
||||||
import org.linphone.activities.LinphoneGenericActivity;
|
import org.linphone.activities.LinphoneGenericActivity;
|
||||||
import org.linphone.core.AccountCreator;
|
import org.linphone.core.AccountCreator;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
|
@ -38,29 +38,16 @@ import org.linphone.core.DialPlan;
|
||||||
import org.linphone.core.Factory;
|
import org.linphone.core.Factory;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.dialer.DialerActivity;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
|
|
||||||
public abstract class AssistantActivity extends LinphoneGenericActivity
|
public abstract class AssistantActivity extends LinphoneGenericActivity
|
||||||
implements CountryPicker.CountryPickedListener {
|
implements CountryPicker.CountryPickedListener {
|
||||||
static AccountCreator mAccountCreator;
|
|
||||||
|
|
||||||
protected ImageView mBack;
|
protected ImageView mBack;
|
||||||
private AlertDialog mCountryPickerDialog;
|
private AlertDialog mCountryPickerDialog;
|
||||||
|
|
||||||
private CountryPicker mCountryPicker;
|
private CountryPicker mCountryPicker;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
if (mAccountCreator == null) {
|
|
||||||
String url = LinphonePreferences.instance().getXmlrpcUrl();
|
|
||||||
Core core = LinphoneManager.getCore();
|
|
||||||
core.loadConfigFromXml(LinphonePreferences.instance().getDefaultDynamicConfigFile());
|
|
||||||
mAccountCreator = core.createAccountCreator(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
@ -104,25 +91,78 @@ public abstract class AssistantActivity extends LinphoneGenericActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createProxyConfigAndLeaveAssistant() {
|
@Override
|
||||||
Core core = LinphoneManager.getCore();
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
boolean useLinphoneDefaultValues =
|
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||||
getString(R.string.default_domain).equals(mAccountCreator.getDomain());
|
if (!mBack.isEnabled()) return true;
|
||||||
if (useLinphoneDefaultValues) {
|
}
|
||||||
core.loadConfigFromXml(LinphonePreferences.instance().getLinphoneDynamicConfigFile());
|
return super.onKeyDown(keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyConfig proxyConfig = mAccountCreator.createProxyConfig();
|
public AccountCreator getAccountCreator() {
|
||||||
|
return LinphoneManager.getInstance().getAccountCreator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reloadAccountCreatorConfig(String path) {
|
||||||
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core != null) {
|
||||||
|
core.loadConfigFromXml(path);
|
||||||
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
|
accountCreator.reset();
|
||||||
|
accountCreator.setLanguage(Locale.getDefault().getLanguage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reloadDefaultAccountCreatorConfig() {
|
||||||
|
Log.i("[Assistant] Reloading configuration with default");
|
||||||
|
reloadAccountCreatorConfig(LinphonePreferences.instance().getDefaultDynamicConfigFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
void reloadLinphoneAccountCreatorConfig() {
|
||||||
|
Log.i("[Assistant] Reloading configuration with specifics");
|
||||||
|
reloadAccountCreatorConfig(LinphonePreferences.instance().getLinphoneDynamicConfigFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
void createProxyConfigAndLeaveAssistant() {
|
||||||
|
createProxyConfigAndLeaveAssistant(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createProxyConfigAndLeaveAssistant(boolean isGenericAccount) {
|
||||||
|
Core core = LinphoneManager.getCore();
|
||||||
|
boolean useLinphoneDefaultValues =
|
||||||
|
getString(R.string.default_domain).equals(getAccountCreator().getDomain());
|
||||||
|
|
||||||
|
if (isGenericAccount) {
|
||||||
|
if (useLinphoneDefaultValues) {
|
||||||
|
Log.i(
|
||||||
|
"[Assistant] Default domain found for generic connection, reloading configuration");
|
||||||
|
core.loadConfigFromXml(
|
||||||
|
LinphonePreferences.instance().getLinphoneDynamicConfigFile());
|
||||||
|
} else {
|
||||||
|
Log.i("[Assistant] Third party domain found, keeping default values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyConfig proxyConfig = getAccountCreator().createProxyConfig();
|
||||||
|
|
||||||
|
if (isGenericAccount) {
|
||||||
if (useLinphoneDefaultValues) {
|
if (useLinphoneDefaultValues) {
|
||||||
// Restore default values
|
// Restore default values
|
||||||
core.loadConfigFromXml(LinphonePreferences.instance().getDefaultDynamicConfigFile());
|
Log.i("[Assistant] Restoring default assistant configuration");
|
||||||
|
core.loadConfigFromXml(
|
||||||
|
LinphonePreferences.instance().getDefaultDynamicConfigFile());
|
||||||
} else {
|
} else {
|
||||||
// If this isn't a sip.linphone.org account, disable push notifications and enable
|
// If this isn't a sip.linphone.org account, disable push notifications and enable
|
||||||
// service notification, otherwise incoming calls won't work (most probably)
|
// service notification, otherwise incoming calls won't work (most probably)
|
||||||
|
if (proxyConfig != null) {
|
||||||
|
proxyConfig.setPushNotificationAllowed(false);
|
||||||
|
}
|
||||||
|
Log.w(
|
||||||
|
"[Assistant] Unknown domain used, push probably won't work, enable service mode");
|
||||||
LinphonePreferences.instance().setServiceNotificationVisibility(true);
|
LinphonePreferences.instance().setServiceNotificationVisibility(true);
|
||||||
LinphoneContext.instance().getNotificationManager().startForeground();
|
LinphoneContext.instance().getNotificationManager().startForeground();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (proxyConfig == null) {
|
if (proxyConfig == null) {
|
||||||
Log.e("[Assistant] Account creator couldn't create proxy config");
|
Log.e("[Assistant] Account creator couldn't create proxy config");
|
||||||
|
@ -206,6 +246,9 @@ public abstract class AssistantActivity extends LinphoneGenericActivity
|
||||||
case PhoneNumberOverused:
|
case PhoneNumberOverused:
|
||||||
message = getString(R.string.phone_number_overuse);
|
message = getString(R.string.phone_number_overuse);
|
||||||
break;
|
break;
|
||||||
|
case AccountNotExist:
|
||||||
|
message = getString(R.string.account_doesnt_exist);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
message = getString(R.string.error_unknown);
|
message = getString(R.string.error_unknown);
|
||||||
break;
|
break;
|
||||||
|
@ -271,7 +314,7 @@ public abstract class AssistantActivity extends LinphoneGenericActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
String phoneNumber = phoneNumberEditText.getText().toString();
|
String phoneNumber = phoneNumberEditText.getText().toString();
|
||||||
return mAccountCreator.setPhoneNumber(phoneNumber, prefix);
|
return getAccountCreator().setPhoneNumber(phoneNumber, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getErrorFromPhoneNumberStatus(int status) {
|
String getErrorFromPhoneNumberStatus(int status) {
|
||||||
|
|
|
@ -30,9 +30,11 @@ import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.core.AccountCreator;
|
import org.linphone.core.AccountCreator;
|
||||||
import org.linphone.core.AccountCreatorListenerStub;
|
import org.linphone.core.AccountCreatorListenerStub;
|
||||||
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
|
@ -65,7 +67,7 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
AccountCreator.UsernameStatus status =
|
AccountCreator.UsernameStatus status =
|
||||||
mAccountCreator.setUsername(s.toString());
|
getAccountCreator().setUsername(s.toString());
|
||||||
mUsernameError.setVisibility(
|
mUsernameError.setVisibility(
|
||||||
status == AccountCreator.UsernameStatus.Ok
|
status == AccountCreator.UsernameStatus.Ok
|
||||||
? View.INVISIBLE
|
? View.INVISIBLE
|
||||||
|
@ -88,7 +90,7 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
AccountCreator.PasswordStatus status =
|
AccountCreator.PasswordStatus status =
|
||||||
mAccountCreator.setPassword(s.toString());
|
getAccountCreator().setPassword(s.toString());
|
||||||
mPasswordError.setVisibility(
|
mPasswordError.setVisibility(
|
||||||
status == AccountCreator.PasswordStatus.Ok
|
status == AccountCreator.PasswordStatus.Ok
|
||||||
? View.INVISIBLE
|
? View.INVISIBLE
|
||||||
|
@ -146,7 +148,8 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
AccountCreator.EmailStatus status = mAccountCreator.setEmail(s.toString());
|
AccountCreator.EmailStatus status =
|
||||||
|
getAccountCreator().setEmail(s.toString());
|
||||||
mEmailError.setVisibility(
|
mEmailError.setVisibility(
|
||||||
status == AccountCreator.EmailStatus.Ok
|
status == AccountCreator.EmailStatus.Ok
|
||||||
? View.INVISIBLE
|
? View.INVISIBLE
|
||||||
|
@ -161,12 +164,13 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
enableButtonsAndFields(false);
|
enableButtonsAndFields(false);
|
||||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
|
||||||
|
|
||||||
AccountCreator.Status status = mAccountCreator.isAccountExist();
|
AccountCreator.Status status = getAccountCreator().isAccountExist();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
Log.e("[Email Account Creation] isAccountExists returned " + status);
|
Log.e(
|
||||||
|
"[Email Account Creation Assistant] isAccountExists returned "
|
||||||
|
+ status);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,15 +181,19 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
new AccountCreatorListenerStub() {
|
new AccountCreatorListenerStub() {
|
||||||
public void onIsAccountExist(
|
public void onIsAccountExist(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Email Account Creation] onIsAccountExist status is " + status);
|
Log.i(
|
||||||
|
"[Email Account Creation Assistant] onIsAccountExist status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.AccountExist)
|
if (status.equals(AccountCreator.Status.AccountExist)
|
||||||
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
|
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
|
||||||
showAccountAlreadyExistsDialog();
|
showAccountAlreadyExistsDialog();
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
} else if (status.equals(AccountCreator.Status.AccountNotExist)) {
|
} else if (status.equals(AccountCreator.Status.AccountNotExist)) {
|
||||||
status = mAccountCreator.createAccount();
|
status = getAccountCreator().createAccount();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Email Account Creation] createAccount returned " + status);
|
Log.e(
|
||||||
|
"[Email Account Creation Assistant] createAccount returned "
|
||||||
|
+ status);
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +206,9 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onCreateAccount(
|
public void onCreateAccount(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Email Account Creation] onCreateAccount status is " + status);
|
Log.i(
|
||||||
|
"[Email Account Creation Assistant] onCreateAccount status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.AccountCreated)) {
|
if (status.equals(AccountCreator.Status.AccountCreated)) {
|
||||||
startActivity(
|
startActivity(
|
||||||
new Intent(
|
new Intent(
|
||||||
|
@ -235,7 +245,12 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
mAccountCreator.addListener(mListener);
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core != null) {
|
||||||
|
reloadLinphoneAccountCreatorConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccountCreator().addListener(mListener);
|
||||||
|
|
||||||
if (getResources().getBoolean(R.bool.pre_fill_email_in_assistant)) {
|
if (getResources().getBoolean(R.bool.pre_fill_email_in_assistant)) {
|
||||||
Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
|
Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
|
||||||
|
@ -252,6 +267,6 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mAccountCreator.removeListener(mListener);
|
getAccountCreator().removeListener(mListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
setContentView(R.layout.assistant_email_account_validation);
|
setContentView(R.layout.assistant_email_account_validation);
|
||||||
|
|
||||||
TextView email = findViewById(R.id.send_email);
|
TextView email = findViewById(R.id.send_email);
|
||||||
email.setText(mAccountCreator.getEmail());
|
email.setText(getAccountCreator().getEmail());
|
||||||
|
|
||||||
mFinishCreation = findViewById(R.id.assistant_check);
|
mFinishCreation = findViewById(R.id.assistant_check);
|
||||||
mFinishCreation.setOnClickListener(
|
mFinishCreation.setOnClickListener(
|
||||||
|
@ -50,9 +50,11 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mFinishCreation.setEnabled(false);
|
mFinishCreation.setEnabled(false);
|
||||||
|
|
||||||
AccountCreator.Status status = mAccountCreator.isAccountActivated();
|
AccountCreator.Status status = getAccountCreator().isAccountActivated();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Email Account Validation] activateAccount returned " + status);
|
Log.e(
|
||||||
|
"[Email Account Validation Assistant] activateAccount returned "
|
||||||
|
+ status);
|
||||||
mFinishCreation.setEnabled(true);
|
mFinishCreation.setEnabled(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +67,7 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
public void onIsAccountActivated(
|
public void onIsAccountActivated(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Email Account Validation] onIsAccountActivated status is "
|
"[Email Account Validation Assistant] onIsAccountActivated status is "
|
||||||
+ status);
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.AccountActivated)) {
|
if (status.equals(AccountCreator.Status.AccountActivated)) {
|
||||||
createProxyConfigAndLeaveAssistant();
|
createProxyConfigAndLeaveAssistant();
|
||||||
|
@ -87,7 +89,7 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mAccountCreator.addListener(mListener);
|
getAccountCreator().addListener(mListener);
|
||||||
|
|
||||||
// Prevent user to go back, it won't be able to come back here after...
|
// Prevent user to go back, it won't be able to come back here after...
|
||||||
mBack.setEnabled(false);
|
mBack.setEnabled(false);
|
||||||
|
@ -96,6 +98,6 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mAccountCreator.removeListener(mListener);
|
getAccountCreator().removeListener(mListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,12 @@ import android.widget.EditText;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.core.AccountCreator;
|
||||||
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.TransportType;
|
import org.linphone.core.TransportType;
|
||||||
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
public class GenericConnectionAssistantActivity extends AssistantActivity implements TextWatcher {
|
public class GenericConnectionAssistantActivity extends AssistantActivity implements TextWatcher {
|
||||||
private TextView mLogin;
|
private TextView mLogin;
|
||||||
|
@ -63,24 +67,31 @@ public class GenericConnectionAssistantActivity extends AssistantActivity implem
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureAccount() {
|
private void configureAccount() {
|
||||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
Core core = LinphoneManager.getCore();
|
||||||
mAccountCreator.setDomain(mDomain.getText().toString());
|
if (core != null) {
|
||||||
mAccountCreator.setPassword(mPassword.getText().toString());
|
Log.i("[Generic Connection Assistant] Reloading configuration with default");
|
||||||
mAccountCreator.setDisplayName(mDisplayName.getText().toString());
|
reloadDefaultAccountCreatorConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
|
accountCreator.setUsername(mUsername.getText().toString());
|
||||||
|
accountCreator.setDomain(mDomain.getText().toString());
|
||||||
|
accountCreator.setPassword(mPassword.getText().toString());
|
||||||
|
accountCreator.setDisplayName(mDisplayName.getText().toString());
|
||||||
|
|
||||||
switch (mTransport.getCheckedRadioButtonId()) {
|
switch (mTransport.getCheckedRadioButtonId()) {
|
||||||
case R.id.transport_udp:
|
case R.id.transport_udp:
|
||||||
mAccountCreator.setTransport(TransportType.Udp);
|
accountCreator.setTransport(TransportType.Udp);
|
||||||
break;
|
break;
|
||||||
case R.id.transport_tcp:
|
case R.id.transport_tcp:
|
||||||
mAccountCreator.setTransport(TransportType.Tcp);
|
accountCreator.setTransport(TransportType.Tcp);
|
||||||
break;
|
break;
|
||||||
case R.id.transport_tls:
|
case R.id.transport_tls:
|
||||||
mAccountCreator.setTransport(TransportType.Tls);
|
accountCreator.setTransport(TransportType.Tls);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
createProxyConfigAndLeaveAssistant();
|
createProxyConfigAndLeaveAssistant(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class OpenH264DownloadAssistantActivity extends AssistantActivity {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mYes.setEnabled(false);
|
mYes.setEnabled(false);
|
||||||
mNo.setEnabled(false);
|
mNo.setEnabled(false);
|
||||||
Log.e("[OpenH264 Downloader] Start download");
|
Log.e("[OpenH264 Downloader Assistant] Start download");
|
||||||
mProgress.setVisibility(View.VISIBLE);
|
mProgress.setVisibility(View.VISIBLE);
|
||||||
mHelper.downloadCodec();
|
mHelper.downloadCodec();
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ public class OpenH264DownloadAssistantActivity extends AssistantActivity {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mYes.setEnabled(false);
|
mYes.setEnabled(false);
|
||||||
mNo.setEnabled(false);
|
mNo.setEnabled(false);
|
||||||
Log.e("[OpenH264 Downloader] Download refused");
|
Log.e("[OpenH264 Downloader Assistant] Download refused");
|
||||||
goToLinphoneActivity();
|
goToLinphoneActivity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -96,7 +96,7 @@ public class OpenH264DownloadAssistantActivity extends AssistantActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnError(String s) {
|
public void OnError(String s) {
|
||||||
Log.e("[OpenH264 Downloader] " + s);
|
Log.e("[OpenH264 Downloader Assistant] " + s);
|
||||||
mYes.setEnabled(true);
|
mYes.setEnabled(true);
|
||||||
mNo.setEnabled(true);
|
mNo.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,11 @@ import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.core.AccountCreator;
|
import org.linphone.core.AccountCreator;
|
||||||
import org.linphone.core.AccountCreatorListenerStub;
|
import org.linphone.core.AccountCreatorListenerStub;
|
||||||
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.DialPlan;
|
import org.linphone.core.DialPlan;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
|
@ -67,18 +69,20 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
enableButtonsAndFields(false);
|
enableButtonsAndFields(false);
|
||||||
|
|
||||||
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
||||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
accountCreator.setUsername(mUsername.getText().toString());
|
||||||
} else {
|
} else {
|
||||||
mAccountCreator.setUsername(mAccountCreator.getPhoneNumber());
|
accountCreator.setUsername(accountCreator.getPhoneNumber());
|
||||||
}
|
}
|
||||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
|
||||||
|
|
||||||
AccountCreator.Status status = mAccountCreator.isAccountExist();
|
AccountCreator.Status status = accountCreator.isAccountExist();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Phone Account Creation] isAccountExists returned " + status);
|
Log.e(
|
||||||
|
"[Phone Account Creation Assistant] isAccountExists returned "
|
||||||
|
+ status);
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -167,15 +171,19 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
new AccountCreatorListenerStub() {
|
new AccountCreatorListenerStub() {
|
||||||
public void onIsAccountExist(
|
public void onIsAccountExist(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Phone Account Creation] onIsAccountExist status is " + status);
|
Log.i(
|
||||||
|
"[Phone Account Creation Assistant] onIsAccountExist status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.AccountExist)
|
if (status.equals(AccountCreator.Status.AccountExist)
|
||||||
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
|
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
|
||||||
showAccountAlreadyExistsDialog();
|
showAccountAlreadyExistsDialog();
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
} else if (status.equals(AccountCreator.Status.AccountNotExist)) {
|
} else if (status.equals(AccountCreator.Status.AccountNotExist)) {
|
||||||
status = mAccountCreator.createAccount();
|
status = getAccountCreator().createAccount();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Phone Account Creation] createAccount returned " + status);
|
Log.e(
|
||||||
|
"[Phone Account Creation Assistant] createAccount returned "
|
||||||
|
+ status);
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +196,9 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onCreateAccount(
|
public void onCreateAccount(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Phone Account Creation] onCreateAccount status is " + status);
|
Log.i(
|
||||||
|
"[Phone Account Creation Assistant] onCreateAccount status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.AccountCreated)) {
|
if (status.equals(AccountCreator.Status.AccountCreated)) {
|
||||||
startActivity(
|
startActivity(
|
||||||
new Intent(
|
new Intent(
|
||||||
|
@ -206,7 +216,12 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
mAccountCreator.addListener(mListener);
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core != null) {
|
||||||
|
reloadLinphoneAccountCreatorConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccountCreator().addListener(mListener);
|
||||||
|
|
||||||
DialPlan dp = getDialPlanForCurrentCountry();
|
DialPlan dp = getDialPlanForCurrentCountry();
|
||||||
displayDialPlan(dp);
|
displayDialPlan(dp);
|
||||||
|
@ -220,7 +235,7 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mAccountCreator.removeListener(mListener);
|
getAccountCreator().removeListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -247,7 +262,7 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) {
|
if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) {
|
||||||
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
||||||
AccountCreator.UsernameStatus usernameStatus =
|
AccountCreator.UsernameStatus usernameStatus =
|
||||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
getAccountCreator().setUsername(mUsername.getText().toString());
|
||||||
if (usernameStatus != AccountCreator.UsernameStatus.Ok) {
|
if (usernameStatus != AccountCreator.UsernameStatus.Ok) {
|
||||||
mCreate.setEnabled(false);
|
mCreate.setEnabled(false);
|
||||||
mError.setText(getErrorFromUsernameStatus(usernameStatus));
|
mError.setText(getErrorFromUsernameStatus(usernameStatus));
|
||||||
|
@ -264,7 +279,7 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
||||||
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
||||||
username = mUsername.getText().toString();
|
username = mUsername.getText().toString();
|
||||||
} else {
|
} else {
|
||||||
username = mAccountCreator.getPhoneNumber();
|
username = getAccountCreator().getPhoneNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
|
|
|
@ -56,42 +56,50 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
||||||
int proxyConfigIndex = getIntent().getExtras().getInt("AccountNumber");
|
int proxyConfigIndex = getIntent().getExtras().getInt("AccountNumber");
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
if (core == null) {
|
if (core == null) {
|
||||||
Log.e("[Account Linking] Core not available");
|
Log.e("[Account Linking Assistant] Core not available");
|
||||||
unexpectedError();
|
unexpectedError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyConfig[] proxyConfigs = core.getProxyConfigList();
|
ProxyConfig[] proxyConfigs = core.getProxyConfigList();
|
||||||
if (proxyConfigIndex >= 0 && proxyConfigIndex < proxyConfigs.length) {
|
if (proxyConfigIndex >= 0 && proxyConfigIndex < proxyConfigs.length) {
|
||||||
ProxyConfig mProxyConfig = proxyConfigs[proxyConfigIndex];
|
ProxyConfig mProxyConfig = proxyConfigs[proxyConfigIndex];
|
||||||
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
|
|
||||||
Address identity = mProxyConfig.getIdentityAddress();
|
Address identity = mProxyConfig.getIdentityAddress();
|
||||||
if (identity == null) {
|
if (identity == null) {
|
||||||
Log.e("[Account Linking] Proxy doesn't have an identity address");
|
Log.e("[Account Linking Assistant] Proxy doesn't have an identity address");
|
||||||
unexpectedError();
|
unexpectedError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!mProxyConfig.getDomain().equals(getString(R.string.default_domain))) {
|
if (!mProxyConfig.getDomain().equals(getString(R.string.default_domain))) {
|
||||||
Log.e(
|
Log.e(
|
||||||
"[Account Linking] Can't link account on domain "
|
"[Account Linking Assistant] Can't link account on domain "
|
||||||
+ mProxyConfig.getDomain());
|
+ mProxyConfig.getDomain());
|
||||||
unexpectedError();
|
unexpectedError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
mAccountCreator.setUsername(identity.getUsername());
|
accountCreator.setUsername(identity.getUsername());
|
||||||
|
|
||||||
AuthInfo authInfo = mProxyConfig.findAuthInfo();
|
AuthInfo authInfo = mProxyConfig.findAuthInfo();
|
||||||
if (authInfo == null) {
|
if (authInfo == null) {
|
||||||
Log.e("[Account Linking] Auth info not found");
|
Log.e("[Account Linking Assistant] Auth info not found");
|
||||||
unexpectedError();
|
unexpectedError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
mAccountCreator.setHa1(authInfo.getHa1());
|
accountCreator.setHa1(authInfo.getHa1());
|
||||||
|
accountCreator.setAlgorithm((authInfo.getAlgorithm()));
|
||||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
|
||||||
} else {
|
} else {
|
||||||
Log.e("[Account Linking] Proxy config index out of bounds: " + proxyConfigIndex);
|
Log.e(
|
||||||
|
"[Account Linking Assistant] Proxy config index out of bounds: "
|
||||||
|
+ proxyConfigIndex);
|
||||||
unexpectedError();
|
unexpectedError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e("[Account Linking] Proxy config index not found");
|
Log.e("[Account Linking Assistant] Proxy config index not found");
|
||||||
unexpectedError();
|
unexpectedError();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCountryPicker = findViewById(R.id.select_country);
|
mCountryPicker = findViewById(R.id.select_country);
|
||||||
|
@ -112,9 +120,11 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
enableButtonsAndFields(false);
|
enableButtonsAndFields(false);
|
||||||
|
|
||||||
AccountCreator.Status status = mAccountCreator.isAliasUsed();
|
AccountCreator.Status status = getAccountCreator().isAliasUsed();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Phone Account Linking] isAliasUsed returned " + status);
|
Log.e(
|
||||||
|
"[Phone Account Linking Assistant] isAliasUsed returned "
|
||||||
|
+ status);
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -178,11 +188,15 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onIsAliasUsed(
|
public void onIsAliasUsed(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Phone Account Linking] onIsAliasUsed status is " + status);
|
Log.i(
|
||||||
|
"[Phone Account Linking Assistant] onIsAliasUsed status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.AliasNotExist)) {
|
if (status.equals(AccountCreator.Status.AliasNotExist)) {
|
||||||
status = mAccountCreator.linkAccount();
|
status = getAccountCreator().linkAccount();
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e("[Phone Account Linking] linkAccount returned " + status);
|
Log.e(
|
||||||
|
"[Phone Account Linking Assistant] linkAccount returned "
|
||||||
|
+ status);
|
||||||
enableButtonsAndFields(true);
|
enableButtonsAndFields(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
}
|
}
|
||||||
|
@ -200,7 +214,9 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onLinkAccount(
|
public void onLinkAccount(
|
||||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
Log.i("[Phone Account Linking] onLinkAccount status is " + status);
|
Log.i(
|
||||||
|
"[Phone Account Linking Assistant] onLinkAccount status is "
|
||||||
|
+ status);
|
||||||
if (status.equals(AccountCreator.Status.RequestOk)) {
|
if (status.equals(AccountCreator.Status.RequestOk)) {
|
||||||
Intent intent =
|
Intent intent =
|
||||||
new Intent(
|
new Intent(
|
||||||
|
@ -220,7 +236,12 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
mAccountCreator.addListener(mListener);
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core != null) {
|
||||||
|
reloadLinphoneAccountCreatorConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccountCreator().addListener(mListener);
|
||||||
|
|
||||||
DialPlan dp = getDialPlanForCurrentCountry();
|
DialPlan dp = getDialPlanForCurrentCountry();
|
||||||
displayDialPlan(dp);
|
displayDialPlan(dp);
|
||||||
|
@ -234,7 +255,7 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mAccountCreator.removeListener(mListener);
|
getAccountCreator().removeListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
private ClipboardManager mClipboard;
|
private ClipboardManager mClipboard;
|
||||||
|
|
||||||
private int mActivationCodeLength;
|
private int mActivationCodeLength;
|
||||||
private boolean mIsLinking;
|
private boolean mIsLinking = false, mIsLogin = false;
|
||||||
private AccountCreatorListenerStub mListener;
|
private AccountCreatorListenerStub mListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,20 +50,21 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
setContentView(R.layout.assistant_phone_account_validation);
|
setContentView(R.layout.assistant_phone_account_validation);
|
||||||
|
|
||||||
if (getIntent() != null && getIntent().getBooleanExtra("isLoginVerification", false)) {
|
if (getIntent() != null && getIntent().getBooleanExtra("isLoginVerification", false)) {
|
||||||
findViewById(R.id.title_account_creation).setVisibility(View.VISIBLE);
|
findViewById(R.id.title_account_login).setVisibility(View.VISIBLE);
|
||||||
|
mIsLogin = true;
|
||||||
} else if (getIntent() != null
|
} else if (getIntent() != null
|
||||||
&& getIntent().getBooleanExtra("isLinkingVerification", false)) {
|
&& getIntent().getBooleanExtra("isLinkingVerification", false)) {
|
||||||
mIsLinking = true;
|
mIsLinking = true;
|
||||||
findViewById(R.id.title_account_linking).setVisibility(View.VISIBLE);
|
findViewById(R.id.title_account_linking).setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
findViewById(R.id.title_account_activation).setVisibility(View.VISIBLE);
|
findViewById(R.id.title_account_creation).setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mActivationCodeLength =
|
mActivationCodeLength =
|
||||||
getResources().getInteger(R.integer.phone_number_validation_code_length);
|
getResources().getInteger(R.integer.phone_number_validation_code_length);
|
||||||
|
|
||||||
TextView phoneNumber = findViewById(R.id.phone_number);
|
TextView phoneNumber = findViewById(R.id.phone_number);
|
||||||
phoneNumber.setText(mAccountCreator.getPhoneNumber());
|
phoneNumber.setText(getAccountCreator().getPhoneNumber());
|
||||||
|
|
||||||
mSmsCode = findViewById(R.id.sms_code);
|
mSmsCode = findViewById(R.id.sms_code);
|
||||||
mSmsCode.addTextChangedListener(
|
mSmsCode.addTextChangedListener(
|
||||||
|
@ -87,21 +88,27 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
AccountCreator accountCreator = getAccountCreator();
|
||||||
mFinishCreation.setEnabled(false);
|
mFinishCreation.setEnabled(false);
|
||||||
mAccountCreator.setActivationCode(mSmsCode.getText().toString());
|
accountCreator.setActivationCode(mSmsCode.getText().toString());
|
||||||
|
|
||||||
AccountCreator.Status status;
|
AccountCreator.Status status;
|
||||||
if (mIsLinking) {
|
if (mIsLinking) {
|
||||||
status = mAccountCreator.activateAlias();
|
status = accountCreator.activateAlias();
|
||||||
|
} else if (mIsLogin) {
|
||||||
|
status = accountCreator.loginLinphoneAccount();
|
||||||
} else {
|
} else {
|
||||||
status = mAccountCreator.activateAccount();
|
status = accountCreator.activateAccount();
|
||||||
}
|
}
|
||||||
if (status != AccountCreator.Status.RequestOk) {
|
if (status != AccountCreator.Status.RequestOk) {
|
||||||
Log.e(
|
Log.e(
|
||||||
"[Phone Account Validation] "
|
"[Phone Account Validation] "
|
||||||
+ (mIsLinking
|
+ (mIsLinking
|
||||||
? "linkAccount"
|
? "linkAccount"
|
||||||
: "activateAccount" + " returned ")
|
: (mIsLogin
|
||||||
|
? "loginLinphoneAccount"
|
||||||
|
: "activateAccount")
|
||||||
|
+ " returned ")
|
||||||
+ status);
|
+ status);
|
||||||
mFinishCreation.setEnabled(true);
|
mFinishCreation.setEnabled(true);
|
||||||
showGenericErrorDialog(status);
|
showGenericErrorDialog(status);
|
||||||
|
@ -118,12 +125,7 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
if (status.equals(AccountCreator.Status.AccountActivated)) {
|
if (status.equals(AccountCreator.Status.AccountActivated)) {
|
||||||
createProxyConfigAndLeaveAssistant();
|
createProxyConfigAndLeaveAssistant();
|
||||||
} else {
|
} else {
|
||||||
mFinishCreation.setEnabled(true);
|
onError(status);
|
||||||
showGenericErrorDialog(status);
|
|
||||||
|
|
||||||
if (status.equals(AccountCreator.Status.WrongActivationCode)) {
|
|
||||||
// TODO do something so the server re-send a SMS
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,13 +137,21 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
LinphonePreferences.instance().setLinkPopupTime("");
|
LinphonePreferences.instance().setLinkPopupTime("");
|
||||||
goToLinphoneActivity();
|
goToLinphoneActivity();
|
||||||
} else {
|
} else {
|
||||||
mFinishCreation.setEnabled(true);
|
onError(status);
|
||||||
showGenericErrorDialog(status);
|
|
||||||
|
|
||||||
if (status.equals(AccountCreator.Status.WrongActivationCode)) {
|
|
||||||
// TODO do something so the server re-send a SMS
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoginLinphoneAccount(
|
||||||
|
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||||
|
Log.i(
|
||||||
|
"[Phone Account Validation] onLoginLinphoneAccount status is "
|
||||||
|
+ status);
|
||||||
|
if (status.equals(AccountCreator.Status.RequestOk)) {
|
||||||
|
createProxyConfigAndLeaveAssistant();
|
||||||
|
} else {
|
||||||
|
onError(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,7 +174,7 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mAccountCreator.addListener(mListener);
|
getAccountCreator().addListener(mListener);
|
||||||
|
|
||||||
// Prevent user to go back, it won't be able to come back here after...
|
// Prevent user to go back, it won't be able to come back here after...
|
||||||
mBack.setEnabled(false);
|
mBack.setEnabled(false);
|
||||||
|
@ -173,6 +183,15 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mAccountCreator.removeListener(mListener);
|
getAccountCreator().removeListener(mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onError(AccountCreator.Status status) {
|
||||||
|
mFinishCreation.setEnabled(true);
|
||||||
|
showGenericErrorDialog(status);
|
||||||
|
|
||||||
|
if (status.equals(AccountCreator.Status.WrongActivationCode)) {
|
||||||
|
// TODO do something so the server re-send a SMS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.utils;
|
package org.linphone.call;
|
||||||
|
|
||||||
import static android.media.AudioManager.MODE_RINGTONE;
|
import static android.media.AudioManager.MODE_RINGTONE;
|
||||||
import static android.media.AudioManager.STREAM_RING;
|
import static android.media.AudioManager.STREAM_RING;
|
||||||
|
@ -54,8 +54,6 @@ import org.linphone.receivers.HeadsetReceiver;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
|
|
||||||
public class AndroidAudioManager {
|
public class AndroidAudioManager {
|
||||||
private static final int LINPHONE_VOLUME_STREAM = STREAM_VOICE_CALL;
|
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private AudioManager mAudioManager;
|
private AudioManager mAudioManager;
|
||||||
private Call mRingingCall;
|
private Call mRingingCall;
|
||||||
|
@ -415,10 +413,22 @@ public class AndroidAudioManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustVolume(int i) {
|
private void adjustVolume(int i) {
|
||||||
// starting from ICS, volume must be adjusted by the application, at least for
|
if (mAudioManager.isVolumeFixed()) {
|
||||||
// STREAM_VOICE_CALL volume stream
|
Log.e("[Audio Manager] Can't adjust volume, device has it fixed...");
|
||||||
|
// Keep going just in case...
|
||||||
|
}
|
||||||
|
|
||||||
|
int stream = STREAM_VOICE_CALL;
|
||||||
|
if (mIsBluetoothHeadsetScoConnected) {
|
||||||
|
Log.i(
|
||||||
|
"[Audio Manager] Bluetooth is connected, try to change the volume on STREAM_BLUETOOTH_SCO");
|
||||||
|
stream = 6; // STREAM_BLUETOOTH_SCO, it's hidden...
|
||||||
|
}
|
||||||
|
|
||||||
|
// starting from ICS, volume must be adjusted by the application,
|
||||||
|
// at least for STREAM_VOICE_CALL volume stream
|
||||||
mAudioManager.adjustStreamVolume(
|
mAudioManager.adjustStreamVolume(
|
||||||
LINPHONE_VOLUME_STREAM,
|
stream,
|
||||||
i < 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_RAISE,
|
i < 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_RAISE,
|
||||||
AudioManager.FLAG_SHOW_UI);
|
AudioManager.FLAG_SHOW_UI);
|
||||||
}
|
}
|
||||||
|
@ -428,6 +438,7 @@ public class AndroidAudioManager {
|
||||||
public synchronized void bluetoothHeadetConnectionChanged(boolean connected) {
|
public synchronized void bluetoothHeadetConnectionChanged(boolean connected) {
|
||||||
mIsBluetoothHeadsetConnected = connected;
|
mIsBluetoothHeadsetConnected = connected;
|
||||||
mAudioManager.setBluetoothScoOn(connected);
|
mAudioManager.setBluetoothScoOn(connected);
|
||||||
|
LinphoneManager.getCallManager().refreshInCallActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void bluetoothHeadetAudioConnectionChanged(boolean connected) {
|
public synchronized void bluetoothHeadetAudioConnectionChanged(boolean connected) {
|
||||||
|
@ -475,8 +486,10 @@ public class AndroidAudioManager {
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
boolean resultAcknoledged;
|
Log.i("[Audio Manager] [Bluetooth] SCO start/stop thread started");
|
||||||
|
boolean resultAcknowledged;
|
||||||
int retries = 0;
|
int retries = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
|
@ -496,26 +509,17 @@ public class AndroidAudioManager {
|
||||||
+ retries);
|
+ retries);
|
||||||
mAudioManager.stopBluetoothSco();
|
mAudioManager.stopBluetoothSco();
|
||||||
}
|
}
|
||||||
resultAcknoledged = isUsingBluetoothAudioRoute() == enable;
|
resultAcknowledged = isUsingBluetoothAudioRoute() == enable;
|
||||||
retries++;
|
retries++;
|
||||||
}
|
}
|
||||||
} while (!resultAcknoledged && retries < 10);
|
} while (!resultAcknowledged && retries < 10);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startBluetooth() {
|
public void bluetoothAdapterStateChanged() {
|
||||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
if (mBluetoothAdapter != null) {
|
|
||||||
Log.i("[Audio Manager] [Bluetooth] Adapter found");
|
|
||||||
if (mAudioManager.isBluetoothScoAvailableOffCall()) {
|
|
||||||
Log.i("[Audio Manager] [Bluetooth] SCO available off call, continue");
|
|
||||||
} else {
|
|
||||||
Log.w("[Audio Manager] [Bluetooth] SCO not available off call !");
|
|
||||||
}
|
|
||||||
if (mBluetoothAdapter.isEnabled()) {
|
if (mBluetoothAdapter.isEnabled()) {
|
||||||
Log.i("[Audio Manager] [Bluetooth] Adapter enabled");
|
Log.i("[Audio Manager] [Bluetooth] Adapter enabled");
|
||||||
mBluetoothReceiver = new BluetoothReceiver();
|
|
||||||
mIsBluetoothHeadsetConnected = false;
|
mIsBluetoothHeadsetConnected = false;
|
||||||
mIsBluetoothHeadsetScoConnected = false;
|
mIsBluetoothHeadsetScoConnected = false;
|
||||||
|
|
||||||
|
@ -534,19 +538,18 @@ public class AndroidAudioManager {
|
||||||
bluetoothHeadetConnectionChanged(true);
|
bluetoothHeadetConnectionChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(
|
Log.i("[Audio Manager] [Bluetooth] Registering bluetooth receiver");
|
||||||
"[Audio Manager] [Bluetooth] Registering bluetooth receiver");
|
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
|
filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
|
||||||
filter.addAction(
|
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
||||||
BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
|
||||||
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
|
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
|
||||||
filter.addAction(
|
filter.addAction(
|
||||||
BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
|
BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
|
||||||
|
|
||||||
Intent sticky =
|
Intent sticky =
|
||||||
mContext.registerReceiver(mBluetoothReceiver, filter);
|
mContext.registerReceiver(mBluetoothReceiver, filter);
|
||||||
|
Log.i("[Audio Manager] [Bluetooth] Bluetooth receiver registered");
|
||||||
int state =
|
int state =
|
||||||
sticky.getIntExtra(
|
sticky.getIntExtra(
|
||||||
AudioManager.EXTRA_SCO_AUDIO_STATE,
|
AudioManager.EXTRA_SCO_AUDIO_STATE,
|
||||||
|
@ -575,18 +578,37 @@ public class AndroidAudioManager {
|
||||||
|
|
||||||
public void onServiceDisconnected(int profile) {
|
public void onServiceDisconnected(int profile) {
|
||||||
if (profile == BluetoothProfile.HEADSET) {
|
if (profile == BluetoothProfile.HEADSET) {
|
||||||
Log.i(
|
Log.i("[Audio Manager] [Bluetooth] HEADSET profile disconnected");
|
||||||
"[Audio Manager] [Bluetooth] HEADSET profile disconnected");
|
|
||||||
mBluetoothHeadset = null;
|
mBluetoothHeadset = null;
|
||||||
mIsBluetoothHeadsetConnected = false;
|
mIsBluetoothHeadsetConnected = false;
|
||||||
mIsBluetoothHeadsetScoConnected = false;
|
mIsBluetoothHeadsetScoConnected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mBluetoothAdapter.getProfileProxy(
|
mBluetoothAdapter.getProfileProxy(
|
||||||
mContext, bluetoothServiceListener, BluetoothProfile.HEADSET);
|
mContext, bluetoothServiceListener, BluetoothProfile.HEADSET);
|
||||||
|
} else {
|
||||||
|
Log.w("[Audio Manager] [Bluetooth] Adapter disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startBluetooth() {
|
||||||
|
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
if (mBluetoothAdapter != null) {
|
||||||
|
Log.i("[Audio Manager] [Bluetooth] Adapter found");
|
||||||
|
if (mAudioManager.isBluetoothScoAvailableOffCall()) {
|
||||||
|
Log.i("[Audio Manager] [Bluetooth] SCO available off call, continue");
|
||||||
|
} else {
|
||||||
|
Log.w("[Audio Manager] [Bluetooth] SCO not available off call !");
|
||||||
|
}
|
||||||
|
|
||||||
|
mBluetoothReceiver = new BluetoothReceiver();
|
||||||
|
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
|
||||||
|
mContext.registerReceiver(mBluetoothReceiver, filter);
|
||||||
|
|
||||||
|
bluetoothAdapterStateChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HEADSET
|
// HEADSET
|
|
@ -48,16 +48,16 @@ import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.DialerActivity;
|
|
||||||
import org.linphone.activities.LinphoneGenericActivity;
|
import org.linphone.activities.LinphoneGenericActivity;
|
||||||
import org.linphone.chat.ChatActivity;
|
import org.linphone.chat.ChatActivity;
|
||||||
import org.linphone.compatibility.Compatibility;
|
import org.linphone.compatibility.Compatibility;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.ContactsUpdatedListener;
|
import org.linphone.contacts.ContactsUpdatedListener;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.ChatMessage;
|
import org.linphone.core.ChatMessage;
|
||||||
|
@ -66,10 +66,10 @@ import org.linphone.core.Core;
|
||||||
import org.linphone.core.CoreListener;
|
import org.linphone.core.CoreListener;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.dialer.DialerActivity;
|
||||||
|
import org.linphone.service.LinphoneService;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.AndroidAudioManager;
|
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class CallActivity extends LinphoneGenericActivity
|
public class CallActivity extends LinphoneGenericActivity
|
||||||
implements CallStatusBarFragment.StatsClikedListener,
|
implements CallStatusBarFragment.StatsClikedListener,
|
||||||
|
@ -82,6 +82,7 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
private static final int MIC_TO_DISABLE_MUTE = 1;
|
private static final int MIC_TO_DISABLE_MUTE = 1;
|
||||||
private static final int WRITE_EXTERNAL_STORAGE_FOR_RECORDING = 2;
|
private static final int WRITE_EXTERNAL_STORAGE_FOR_RECORDING = 2;
|
||||||
private static final int CAMERA_TO_ACCEPT_UPDATE = 3;
|
private static final int CAMERA_TO_ACCEPT_UPDATE = 3;
|
||||||
|
private static final int ALL_PERMISSIONS = 4;
|
||||||
|
|
||||||
private static class HideControlsRunnable implements Runnable {
|
private static class HideControlsRunnable implements Runnable {
|
||||||
private WeakReference<CallActivity> mWeakCallActivity;
|
private WeakReference<CallActivity> mWeakCallActivity;
|
||||||
|
@ -306,13 +307,13 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
findViewById(R.id.numpad)
|
View numpad = findViewById(R.id.numpad);
|
||||||
.setVisibility(
|
boolean isNumpadVisible = numpad.getVisibility() == View.VISIBLE;
|
||||||
findViewById(R.id.numpad).getVisibility() == View.VISIBLE
|
numpad.setVisibility(isNumpadVisible ? View.GONE : View.VISIBLE);
|
||||||
? View.GONE
|
v.setSelected(!isNumpadVisible);
|
||||||
: View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
numpadButton.setSelected(false);
|
||||||
|
|
||||||
ImageView hangUp = findViewById(R.id.hang_up);
|
ImageView hangUp = findViewById(R.id.hang_up);
|
||||||
hangUp.setOnClickListener(
|
hangUp.setOnClickListener(
|
||||||
|
@ -387,6 +388,8 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
if (state == Call.State.End || state == Call.State.Released) {
|
if (state == Call.State.End || state == Call.State.Released) {
|
||||||
if (core.getCallsNb() == 0) {
|
if (core.getCallsNb() == 0) {
|
||||||
finish();
|
finish();
|
||||||
|
} else {
|
||||||
|
showVideoControls(false);
|
||||||
}
|
}
|
||||||
} else if (state == Call.State.PausedByRemote) {
|
} else if (state == Call.State.PausedByRemote) {
|
||||||
if (core.getCurrentCall() != null) {
|
if (core.getCurrentCall() != null) {
|
||||||
|
@ -437,6 +440,7 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
Call call = mCore.getCurrentCall();
|
Call call = mCore.getCurrentCall();
|
||||||
boolean videoEnabled =
|
boolean videoEnabled =
|
||||||
LinphonePreferences.instance().isVideoEnabled()
|
LinphonePreferences.instance().isVideoEnabled()
|
||||||
|
&& call != null
|
||||||
&& call.getCurrentParams().videoEnabled();
|
&& call.getCurrentParams().videoEnabled();
|
||||||
|
|
||||||
if (videoEnabled) {
|
if (videoEnabled) {
|
||||||
|
@ -451,6 +455,11 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
|
// This also must be done here in case of an outgoing call accepted
|
||||||
|
// before user granted or denied permissions
|
||||||
|
// or if an incoming call was answer from the notification
|
||||||
|
checkAndRequestCallPermissions();
|
||||||
|
|
||||||
mCore = LinphoneManager.getCore();
|
mCore = LinphoneManager.getCore();
|
||||||
if (mCore != null) {
|
if (mCore != null) {
|
||||||
mCore.setNativeVideoWindowId(mRemoteVideo);
|
mCore.setNativeVideoWindowId(mRemoteVideo);
|
||||||
|
@ -557,11 +566,6 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onNewIntent(Intent intent) {
|
|
||||||
super.onNewIntent(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
if (mAudioManager.onKeyVolumeAdjust(keyCode)) return true;
|
if (mAudioManager.onKeyVolumeAdjust(keyCode)) return true;
|
||||||
|
@ -581,8 +585,21 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
public void onRequestPermissionsResult(
|
public void onRequestPermissionsResult(
|
||||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
// Permission not granted, won't change anything
|
// Permission not granted, won't change anything
|
||||||
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) return;
|
|
||||||
|
|
||||||
|
if (requestCode == ALL_PERMISSIONS) {
|
||||||
|
for (int index = 0; index < permissions.length; index++) {
|
||||||
|
int granted = grantResults[index];
|
||||||
|
if (granted == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
String permission = permissions[index];
|
||||||
|
if (Manifest.permission.RECORD_AUDIO.equals(permission)) {
|
||||||
|
toggleMic();
|
||||||
|
} else if (Manifest.permission.CAMERA.equals(permission)) {
|
||||||
|
LinphoneUtils.reloadVideoDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) return;
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case CAMERA_TO_TOGGLE_VIDEO:
|
case CAMERA_TO_TOGGLE_VIDEO:
|
||||||
LinphoneUtils.reloadVideoDevices();
|
LinphoneUtils.reloadVideoDevices();
|
||||||
|
@ -600,6 +617,7 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkPermission(String permission) {
|
private boolean checkPermission(String permission) {
|
||||||
int granted = getPackageManager().checkPermission(permission, getPackageName());
|
int granted = getPackageManager().checkPermission(permission, getPackageName());
|
||||||
|
@ -620,6 +638,57 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkAndRequestCallPermissions() {
|
||||||
|
ArrayList<String> permissionsList = new ArrayList<>();
|
||||||
|
|
||||||
|
int recordAudio =
|
||||||
|
getPackageManager()
|
||||||
|
.checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName());
|
||||||
|
Log.i(
|
||||||
|
"[Permission] Record audio permission is "
|
||||||
|
+ (recordAudio == PackageManager.PERMISSION_GRANTED
|
||||||
|
? "granted"
|
||||||
|
: "denied"));
|
||||||
|
int camera =
|
||||||
|
getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName());
|
||||||
|
Log.i(
|
||||||
|
"[Permission] Camera permission is "
|
||||||
|
+ (camera == PackageManager.PERMISSION_GRANTED ? "granted" : "denied"));
|
||||||
|
|
||||||
|
int readPhoneState =
|
||||||
|
getPackageManager()
|
||||||
|
.checkPermission(Manifest.permission.READ_PHONE_STATE, getPackageName());
|
||||||
|
Log.i(
|
||||||
|
"[Permission] Read phone state permission is "
|
||||||
|
+ (camera == PackageManager.PERMISSION_GRANTED ? "granted" : "denied"));
|
||||||
|
|
||||||
|
if (recordAudio != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i("[Permission] Asking for record audio");
|
||||||
|
permissionsList.add(Manifest.permission.RECORD_AUDIO);
|
||||||
|
}
|
||||||
|
if (readPhoneState != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i("[Permission] Asking for read phone state");
|
||||||
|
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Call call = mCore.getCurrentCall();
|
||||||
|
if (LinphonePreferences.instance().shouldInitiateVideoCall()
|
||||||
|
|| (LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()
|
||||||
|
&& call != null
|
||||||
|
&& call.getRemoteParams().videoEnabled())) {
|
||||||
|
if (camera != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i("[Permission] Asking for camera");
|
||||||
|
permissionsList.add(Manifest.permission.CAMERA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permissionsList.size() > 0) {
|
||||||
|
String[] permissions = new String[permissionsList.size()];
|
||||||
|
permissions = permissionsList.toArray(permissions);
|
||||||
|
ActivityCompat.requestPermissions(this, permissions, ALL_PERMISSIONS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContactsUpdated() {
|
public void onContactsUpdated() {
|
||||||
setCurrentCallContactInformation();
|
setCurrentCallContactInformation();
|
||||||
|
@ -825,6 +894,7 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
|
|
||||||
boolean videoEnabled =
|
boolean videoEnabled =
|
||||||
LinphonePreferences.instance().isVideoEnabled()
|
LinphonePreferences.instance().isVideoEnabled()
|
||||||
|
&& call != null
|
||||||
&& call.getCurrentParams().videoEnabled();
|
&& call.getCurrentParams().videoEnabled();
|
||||||
showVideoControls(videoEnabled);
|
showVideoControls(videoEnabled);
|
||||||
}
|
}
|
||||||
|
@ -1024,7 +1094,7 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
mConferenceList.removeAllViews();
|
mConferenceList.removeAllViews();
|
||||||
|
|
||||||
for (Call call : mCore.getCalls()) {
|
for (Call call : mCore.getCalls()) {
|
||||||
if (call.getConference() != null) {
|
if (call != null && call.getConference() != null) {
|
||||||
if (mCore.isInConference()) {
|
if (mCore.isInConference()) {
|
||||||
displayConferenceCall(call);
|
displayConferenceCall(call);
|
||||||
conferenceDisplayed = true;
|
conferenceDisplayed = true;
|
||||||
|
@ -1032,11 +1102,16 @@ public class CallActivity extends LinphoneGenericActivity
|
||||||
displayPausedConference();
|
displayPausedConference();
|
||||||
pausedConferenceDisplayed = true;
|
pausedConferenceDisplayed = true;
|
||||||
}
|
}
|
||||||
} else if (call != currentCall) {
|
} else if (call != null && call != currentCall) {
|
||||||
|
Call.State state = call.getState();
|
||||||
|
if (state == Call.State.Paused
|
||||||
|
|| state == Call.State.PausedByRemote
|
||||||
|
|| state == Call.State.Pausing) {
|
||||||
displayPausedCall(call);
|
displayPausedCall(call);
|
||||||
callThatIsNotCurrentFound = true;
|
callThatIsNotCurrentFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mCallsList.setVisibility(
|
mCallsList.setVisibility(
|
||||||
pausedConferenceDisplayed || callThatIsNotCurrentFound ? View.VISIBLE : View.GONE);
|
pausedConferenceDisplayed || callThatIsNotCurrentFound ? View.VISIBLE : View.GONE);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import android.os.Bundle;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.TextureView;
|
import android.view.TextureView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -36,9 +37,13 @@ import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.LinphoneGenericActivity;
|
import org.linphone.activities.LinphoneGenericActivity;
|
||||||
|
import org.linphone.call.views.CallIncomingAnswerButton;
|
||||||
|
import org.linphone.call.views.CallIncomingButtonListener;
|
||||||
|
import org.linphone.call.views.CallIncomingDeclineButton;
|
||||||
import org.linphone.compatibility.Compatibility;
|
import org.linphone.compatibility.Compatibility;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.Call.State;
|
import org.linphone.core.Call.State;
|
||||||
|
@ -47,10 +52,6 @@ import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.CallIncomingAnswerButton;
|
|
||||||
import org.linphone.views.CallIncomingButtonListener;
|
|
||||||
import org.linphone.views.CallIncomingDeclineButton;
|
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class CallIncomingActivity extends LinphoneGenericActivity {
|
public class CallIncomingActivity extends LinphoneGenericActivity {
|
||||||
private TextView mName, mNumber;
|
private TextView mName, mNumber;
|
||||||
|
@ -63,6 +64,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
Compatibility.setShowWhenLocked(this, true);
|
Compatibility.setShowWhenLocked(this, true);
|
||||||
Compatibility.setTurnScreenOn(this, true);
|
Compatibility.setTurnScreenOn(this, true);
|
||||||
|
|
||||||
|
@ -122,13 +124,13 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
||||||
Core core, Call call, State state, String message) {
|
Core core, Call call, State state, String message) {
|
||||||
if (call == mCall) {
|
if (call == mCall) {
|
||||||
if (state == State.Connected) {
|
if (state == State.Connected) {
|
||||||
// This is done by the Service listener now
|
// This is done by the LinphoneContext listener now
|
||||||
// startActivity(new Intent(CallOutgoingActivity.this,
|
// startActivity(new Intent(CallOutgoingActivity.this,
|
||||||
// CallActivity.class));
|
// CallActivity.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LinphoneManager.getCore().getCallsNb() == 0) {
|
if (state == State.End || state == State.Released) {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,6 +232,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
||||||
mAlreadyAcceptedOrDeniedCall = true;
|
mAlreadyAcceptedOrDeniedCall = true;
|
||||||
|
|
||||||
mCall.terminate();
|
mCall.terminate();
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void answer() {
|
private void answer() {
|
||||||
|
@ -276,8 +279,9 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
||||||
Log.i("[Permission] Asking for read phone state");
|
Log.i("[Permission] Asking for read phone state");
|
||||||
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
||||||
}
|
}
|
||||||
if (LinphonePreferences.instance().shouldInitiateVideoCall()
|
if (LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()
|
||||||
|| LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
|
&& mCall != null
|
||||||
|
&& mCall.getRemoteParams().videoEnabled()) {
|
||||||
if (camera != PackageManager.PERMISSION_GRANTED) {
|
if (camera != PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.i("[Permission] Asking for camera");
|
Log.i("[Permission] Asking for camera");
|
||||||
permissionsList.add(Manifest.permission.CAMERA);
|
permissionsList.add(Manifest.permission.CAMERA);
|
||||||
|
|
|
@ -35,11 +35,11 @@ import org.linphone.core.Core;
|
||||||
import org.linphone.core.MediaEncryption;
|
import org.linphone.core.MediaEncryption;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.dialer.views.AddressType;
|
||||||
import org.linphone.mediastream.Version;
|
import org.linphone.mediastream.Version;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.FileUtils;
|
import org.linphone.utils.FileUtils;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.AddressType;
|
|
||||||
|
|
||||||
/** Handle call updating, reinvites. */
|
/** Handle call updating, reinvites. */
|
||||||
public class CallManager {
|
public class CallManager {
|
||||||
|
@ -87,32 +87,26 @@ public class CallManager {
|
||||||
|
|
||||||
public void switchCamera() {
|
public void switchCamera() {
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
try {
|
if (core == null) return;
|
||||||
|
|
||||||
String currentDevice = core.getVideoDevice();
|
String currentDevice = core.getVideoDevice();
|
||||||
|
Log.i("[Call Manager] Current camera device is " + currentDevice);
|
||||||
|
|
||||||
String[] devices = core.getVideoDevicesList();
|
String[] devices = core.getVideoDevicesList();
|
||||||
int index = 0;
|
|
||||||
for (String d : devices) {
|
for (String d : devices) {
|
||||||
if (d.equals(currentDevice)) {
|
if (!d.equals(currentDevice) && !d.equals("StaticImage: Static picture")) {
|
||||||
|
Log.i("[Call Manager] New camera device will be " + d);
|
||||||
|
core.setVideoDevice(d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String newDevice;
|
|
||||||
if (index == 1) newDevice = devices[0];
|
|
||||||
else if (devices.length > 1) newDevice = devices[1];
|
|
||||||
else newDevice = devices[index];
|
|
||||||
core.setVideoDevice(newDevice);
|
|
||||||
|
|
||||||
Call call = core.getCurrentCall();
|
Call call = core.getCurrentCall();
|
||||||
if (call == null) {
|
if (call == null) {
|
||||||
Log.w("[Call Manager] Trying to switch camera while not in call");
|
Log.i("[Call Manager] Switching camera while not in call");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
call.update(null);
|
call.update(null);
|
||||||
} catch (ArithmeticException ae) {
|
|
||||||
Log.e("[Call Manager] [Video] Cannot switch camera: no camera");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean acceptCall(Call call) {
|
public boolean acceptCall(Call call) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.linphone.R;
|
||||||
import org.linphone.activities.LinphoneGenericActivity;
|
import org.linphone.activities.LinphoneGenericActivity;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.Call.State;
|
import org.linphone.core.Call.State;
|
||||||
|
@ -46,7 +47,6 @@ import org.linphone.core.Reason;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class CallOutgoingActivity extends LinphoneGenericActivity implements OnClickListener {
|
public class CallOutgoingActivity extends LinphoneGenericActivity implements OnClickListener {
|
||||||
private TextView mName, mNumber;
|
private TextView mName, mNumber;
|
||||||
|
@ -125,12 +125,12 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
} else if (state == State.Connected) {
|
} else if (state == State.Connected) {
|
||||||
// This is done by the Service listener now
|
// This is done by the LinphoneContext listener now
|
||||||
// startActivity(new Intent(CallOutgoingActivity.this,
|
// startActivity(new Intent(CallOutgoingActivity.this,
|
||||||
// CallActivity.class));
|
// CallActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LinphoneManager.getCore().getCallsNb() == 0) {
|
if (state == State.End || state == State.Released) {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,8 +283,7 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
|
||||||
Log.i("[Permission] Asking for read phone state");
|
Log.i("[Permission] Asking for read phone state");
|
||||||
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
||||||
}
|
}
|
||||||
if (LinphonePreferences.instance().shouldInitiateVideoCall()
|
if (LinphonePreferences.instance().shouldInitiateVideoCall()) {
|
||||||
|| LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
|
|
||||||
if (camera != PackageManager.PERMISSION_GRANTED) {
|
if (camera != PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.i("[Permission] Asking for camera");
|
Log.i("[Permission] Asking for camera");
|
||||||
permissionsList.add(Manifest.permission.CAMERA);
|
permissionsList.add(Manifest.permission.CAMERA);
|
||||||
|
|
|
@ -29,9 +29,9 @@ import java.util.List;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class CallStatsAdapter extends BaseExpandableListAdapter {
|
public class CallStatsAdapter extends BaseExpandableListAdapter {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
|
@ -55,8 +55,8 @@ public class CallStatsFragment extends Fragment {
|
||||||
new CoreListenerStub() {
|
new CoreListenerStub() {
|
||||||
@Override
|
@Override
|
||||||
public void onCallStateChanged(
|
public void onCallStateChanged(
|
||||||
Core lc, Call call, Call.State cstate, String message) {
|
Core core, Call call, Call.State state, String message) {
|
||||||
if (cstate == Call.State.End || cstate == Call.State.Error) {
|
if (state == Call.State.End || state == Call.State.Error) {
|
||||||
mAdapter.updateListItems(
|
mAdapter.updateListItems(
|
||||||
Arrays.asList(LinphoneManager.getCore().getCalls()));
|
Arrays.asList(LinphoneManager.getCore().getCalls()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,9 +288,19 @@ public class CallStatusBarFragment extends Fragment {
|
||||||
|
|
||||||
public void refreshStatusItems(final Call call) {
|
public void refreshStatusItems(final Call call) {
|
||||||
if (call != null) {
|
if (call != null) {
|
||||||
MediaEncryption mediaEncryption = call.getCurrentParams().getMediaEncryption();
|
if (call.getDir() == Call.Dir.Incoming
|
||||||
|
&& call.getState() == Call.State.IncomingReceived
|
||||||
|
&& LinphonePreferences.instance().isMediaEncryptionMandatory()) {
|
||||||
|
// If the incoming call view is displayed while encryption is mandatory,
|
||||||
|
// we can safely show the security_ok icon
|
||||||
|
mEncryption.setImageResource(R.drawable.security_ok);
|
||||||
mEncryption.setVisibility(View.VISIBLE);
|
mEncryption.setVisibility(View.VISIBLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaEncryption mediaEncryption = call.getCurrentParams().getMediaEncryption();
|
||||||
|
mEncryption.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if (mediaEncryption == MediaEncryption.SRTP
|
if (mediaEncryption == MediaEncryption.SRTP
|
||||||
|| (mediaEncryption == MediaEncryption.ZRTP
|
|| (mediaEncryption == MediaEncryption.ZRTP
|
||||||
&& call.getAuthenticationTokenVerified())
|
&& call.getAuthenticationTokenVerified())
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -30,6 +30,8 @@ import org.linphone.core.Call;
|
||||||
import org.linphone.core.CallLog;
|
import org.linphone.core.CallLog;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
|
import org.linphone.dialer.views.AddressAware;
|
||||||
|
import org.linphone.dialer.views.AddressText;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
|
|
||||||
@SuppressLint("AppCompatCustomView")
|
@SuppressLint("AppCompatCustomView")
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
public interface CallIncomingButtonListener {
|
public interface CallIncomingButtonListener {
|
||||||
void onAction();
|
void onAction();
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.call.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
|
@ -20,6 +20,7 @@
|
||||||
package org.linphone.chat;
|
package org.linphone.chat;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
|
import android.app.FragmentManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -258,7 +259,18 @@ public class ChatActivity extends MainActivity {
|
||||||
ArrayList<ContactAddress> participants,
|
ArrayList<ContactAddress> participants,
|
||||||
String subject,
|
String subject,
|
||||||
boolean encrypted,
|
boolean encrypted,
|
||||||
boolean isGroupChatRoom) {
|
boolean isGroupChatRoom,
|
||||||
|
boolean cleanBackStack) {
|
||||||
|
if (cleanBackStack) {
|
||||||
|
FragmentManager fm = getFragmentManager();
|
||||||
|
while (fm.getBackStackEntryCount() > 0) {
|
||||||
|
fm.popBackStackImmediate();
|
||||||
|
}
|
||||||
|
if (isTablet()) {
|
||||||
|
showEmptyChildFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
if (peerAddress != null) {
|
if (peerAddress != null) {
|
||||||
extras.putSerializable("RemoteSipUri", peerAddress.asStringUriOnly());
|
extras.putSerializable("RemoteSipUri", peerAddress.asStringUriOnly());
|
||||||
|
|
|
@ -50,6 +50,7 @@ import java.util.List;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatMessage;
|
import org.linphone.core.ChatMessage;
|
||||||
import org.linphone.core.Content;
|
import org.linphone.core.Content;
|
||||||
|
@ -57,7 +58,6 @@ import org.linphone.core.tools.Log;
|
||||||
import org.linphone.utils.FileUtils;
|
import org.linphone.utils.FileUtils;
|
||||||
import org.linphone.utils.ImageUtils;
|
import org.linphone.utils.ImageUtils;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
private final RelativeLayout singleFileContent;
|
private final RelativeLayout singleFileContent;
|
||||||
|
|
||||||
public final CheckBox delete;
|
public final CheckBox delete;
|
||||||
|
public boolean isEditionEnabled;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ChatMessageViewHolderClickListener mListener;
|
private ChatMessageViewHolderClickListener mListener;
|
||||||
|
@ -275,8 +276,12 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
if (isEditionEnabled) {
|
||||||
|
ChatMessageViewHolder.this.onClick(v);
|
||||||
|
} else {
|
||||||
openFile(filePath);
|
openFile(filePath);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
downloadOrCancel.setVisibility(View.VISIBLE);
|
downloadOrCancel.setVisibility(View.VISIBLE);
|
||||||
|
@ -315,6 +320,9 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
if (isEditionEnabled) {
|
||||||
|
ChatMessageViewHolder.this.onClick(v);
|
||||||
|
} else {
|
||||||
Content c = (Content) v.getTag();
|
Content c = (Content) v.getTag();
|
||||||
if (!message.isFileTransferInProgress()) {
|
if (!message.isFileTransferInProgress()) {
|
||||||
message.downloadContent(c);
|
message.downloadContent(c);
|
||||||
|
@ -322,6 +330,7 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
message.cancelFileTransfer();
|
message.cancelFileTransfer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Log.w(
|
Log.w(
|
||||||
|
|
|
@ -119,6 +119,7 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
|
||||||
holder.bubbleLayout.setVisibility(View.GONE);
|
holder.bubbleLayout.setVisibility(View.GONE);
|
||||||
holder.sendInProgress.setVisibility(View.GONE);
|
holder.sendInProgress.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
holder.isEditionEnabled = isEditionEnabled();
|
||||||
if (isEditionEnabled()) {
|
if (isEditionEnabled()) {
|
||||||
holder.delete.setVisibility(View.VISIBLE);
|
holder.delete.setVisibility(View.VISIBLE);
|
||||||
holder.delete.setChecked(isSelected(position));
|
holder.delete.setChecked(isSelected(position));
|
||||||
|
|
|
@ -349,7 +349,7 @@ public class ChatMessagesFragment extends Fragment
|
||||||
new CoreListenerStub() {
|
new CoreListenerStub() {
|
||||||
@Override
|
@Override
|
||||||
public void onCallStateChanged(
|
public void onCallStateChanged(
|
||||||
Core lc, Call call, Call.State state, String message) {
|
Core core, Call call, Call.State state, String message) {
|
||||||
displayChatRoomHeader();
|
displayChatRoomHeader();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,12 +43,14 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||||
import org.linphone.contacts.ContactAddress;
|
import org.linphone.contacts.ContactAddress;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.ContactsUpdatedListener;
|
import org.linphone.contacts.ContactsUpdatedListener;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
import org.linphone.contacts.SearchContactViewHolder;
|
import org.linphone.contacts.SearchContactViewHolder;
|
||||||
import org.linphone.contacts.SearchContactsAdapter;
|
import org.linphone.contacts.SearchContactsAdapter;
|
||||||
|
import org.linphone.contacts.views.ContactSelectView;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatRoom;
|
import org.linphone.core.ChatRoom;
|
||||||
import org.linphone.core.ChatRoomBackend;
|
import org.linphone.core.ChatRoomBackend;
|
||||||
|
@ -61,8 +63,6 @@ import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.SearchResult;
|
import org.linphone.core.SearchResult;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.views.ContactSelectView;
|
|
||||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
|
||||||
|
|
||||||
public class ChatRoomCreationFragment extends Fragment
|
public class ChatRoomCreationFragment extends Fragment
|
||||||
implements View.OnClickListener,
|
implements View.OnClickListener,
|
||||||
|
@ -143,8 +143,8 @@ public class ChatRoomCreationFragment extends Fragment
|
||||||
if (mChatRoomAddress == null && mChatRoomSubject == null) {
|
if (mChatRoomAddress == null && mChatRoomSubject == null) {
|
||||||
mContactsSelectedLayout.removeAllViews();
|
mContactsSelectedLayout.removeAllViews();
|
||||||
} else {
|
} else {
|
||||||
// Pop the back stack twice so we don't have in stack Group -> Creation
|
// Pop the back stack twice so we don't have in stack
|
||||||
// -> Group
|
// Group -> Creation -> Group
|
||||||
getFragmentManager().popBackStack();
|
getFragmentManager().popBackStack();
|
||||||
getFragmentManager().popBackStack();
|
getFragmentManager().popBackStack();
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,10 @@ public class ChatRoomCreationFragment extends Fragment
|
||||||
mChatRoom.getLocalAddress(), mChatRoom.getPeerAddress());
|
mChatRoom.getLocalAddress(), mChatRoom.getPeerAddress());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ChatRoom chatRoom = core.getChatRoom(address);
|
ChatRoom chatRoom = null;
|
||||||
|
if (lpc != null) chatRoom = core.getChatRoom(address, lpc.getIdentityAddress());
|
||||||
|
else chatRoom = core.getChatRoom(address);
|
||||||
|
|
||||||
if (chatRoom != null) {
|
if (chatRoom != null) {
|
||||||
// Pop back stack so back button takes to the chat rooms list
|
// Pop back stack so back button takes to the chat rooms list
|
||||||
getFragmentManager().popBackStack();
|
getFragmentManager().popBackStack();
|
||||||
|
|
|
@ -28,6 +28,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatMessage;
|
import org.linphone.core.ChatMessage;
|
||||||
import org.linphone.core.ChatRoom;
|
import org.linphone.core.ChatRoom;
|
||||||
|
@ -35,7 +36,6 @@ import org.linphone.core.ChatRoomCapabilities;
|
||||||
import org.linphone.core.Content;
|
import org.linphone.core.Content;
|
||||||
import org.linphone.core.Participant;
|
import org.linphone.core.Participant;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class ChatRoomViewHolder extends RecyclerView.ViewHolder
|
public class ChatRoomViewHolder extends RecyclerView.ViewHolder
|
||||||
implements View.OnClickListener, View.OnLongClickListener {
|
implements View.OnClickListener, View.OnLongClickListener {
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.util.List;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.MainActivity;
|
import org.linphone.activities.MainActivity;
|
||||||
|
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.ContactsUpdatedListener;
|
import org.linphone.contacts.ContactsUpdatedListener;
|
||||||
import org.linphone.core.ChatMessage;
|
import org.linphone.core.ChatMessage;
|
||||||
|
@ -44,7 +45,6 @@ import org.linphone.core.Core;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.utils.SelectableHelper;
|
import org.linphone.utils.SelectableHelper;
|
||||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
|
||||||
|
|
||||||
public class ChatRoomsFragment extends Fragment
|
public class ChatRoomsFragment extends Fragment
|
||||||
implements ContactsUpdatedListener,
|
implements ContactsUpdatedListener,
|
||||||
|
@ -108,7 +108,7 @@ public class ChatRoomsFragment extends Fragment
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
((ChatActivity) getActivity())
|
((ChatActivity) getActivity())
|
||||||
.showChatRoomCreation(null, null, null, false, false);
|
.showChatRoomCreation(null, null, null, false, false, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ public class ChatRoomsFragment extends Fragment
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
((ChatActivity) getActivity())
|
((ChatActivity) getActivity())
|
||||||
.showChatRoomCreation(null, null, null, false, true);
|
.showChatRoomCreation(null, null, null, false, true, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -137,8 +137,13 @@ public class ChatRoomsFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(Core core, ChatRoom cr, ChatMessage message) {
|
public void onMessageReceived(Core core, ChatRoom room, ChatMessage message) {
|
||||||
refreshChatRoom(cr);
|
refreshChatRoom(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChatRoomSubjectChanged(Core core, ChatRoom room) {
|
||||||
|
refreshChatRoom(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -154,9 +159,10 @@ public class ChatRoomsFragment extends Fragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChatRoomStateChanged(
|
public void onChatRoomStateChanged(
|
||||||
Core core, ChatRoom cr, ChatRoom.State state) {
|
Core core, ChatRoom room, ChatRoom.State state) {
|
||||||
if (state == ChatRoom.State.Created) {
|
if (state == ChatRoom.State.Created) {
|
||||||
refreshChatRoom(cr);
|
refreshChatRoom(room);
|
||||||
|
scrollToTop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -253,6 +259,9 @@ public class ChatRoomsFragment extends Fragment
|
||||||
mWaitLayout.setVisibility(View.VISIBLE);
|
mWaitLayout.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
((ChatActivity) getActivity()).displayMissedChats();
|
((ChatActivity) getActivity()).displayMissedChats();
|
||||||
|
|
||||||
|
if (getResources().getBoolean(R.bool.isTablet))
|
||||||
|
((ChatActivity) getActivity()).showEmptyChildFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -263,6 +272,10 @@ public class ChatRoomsFragment extends Fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scrollToTop() {
|
||||||
|
mChatRoomsList.getLayoutManager().scrollToPosition(0);
|
||||||
|
}
|
||||||
|
|
||||||
private void refreshChatRoom(ChatRoom cr) {
|
private void refreshChatRoom(ChatRoom cr) {
|
||||||
ChatRoomViewHolder holder = (ChatRoomViewHolder) cr.getUserData();
|
ChatRoomViewHolder holder = (ChatRoomViewHolder) cr.getUserData();
|
||||||
if (holder != null) {
|
if (holder != null) {
|
||||||
|
|
|
@ -29,12 +29,12 @@ import java.util.List;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatRoomSecurityLevel;
|
import org.linphone.core.ChatRoomSecurityLevel;
|
||||||
import org.linphone.core.Participant;
|
import org.linphone.core.Participant;
|
||||||
import org.linphone.core.ParticipantDevice;
|
import org.linphone.core.ParticipantDevice;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
class DevicesAdapter extends BaseExpandableListAdapter {
|
class DevicesAdapter extends BaseExpandableListAdapter {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
|
@ -26,16 +26,12 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ExpandableListView;
|
import android.widget.ExpandableListView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
|
||||||
import org.linphone.contacts.LinphoneContact;
|
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatRoom;
|
import org.linphone.core.ChatRoom;
|
||||||
import org.linphone.core.ChatRoomCapabilities;
|
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.Factory;
|
import org.linphone.core.Factory;
|
||||||
import org.linphone.core.Participant;
|
import org.linphone.core.Participant;
|
||||||
|
@ -43,7 +39,6 @@ import org.linphone.core.ParticipantDevice;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
|
|
||||||
public class DevicesFragment extends Fragment {
|
public class DevicesFragment extends Fragment {
|
||||||
private TextView mTitle;
|
|
||||||
private ExpandableListView mExpandableList;
|
private ExpandableListView mExpandableList;
|
||||||
private DevicesAdapter mAdapter;
|
private DevicesAdapter mAdapter;
|
||||||
|
|
||||||
|
@ -114,9 +109,6 @@ public class DevicesFragment extends Fragment {
|
||||||
|
|
||||||
initChatRoom();
|
initChatRoom();
|
||||||
|
|
||||||
mTitle = view.findViewById(R.id.title);
|
|
||||||
initHeader();
|
|
||||||
|
|
||||||
ImageView backButton = view.findViewById(R.id.back);
|
ImageView backButton = view.findViewById(R.id.back);
|
||||||
backButton.setOnClickListener(
|
backButton.setOnClickListener(
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
|
@ -146,24 +138,6 @@ public class DevicesFragment extends Fragment {
|
||||||
mRoom = core.getChatRoom(mRoomAddr, mLocalSipAddr);
|
mRoom = core.getChatRoom(mRoomAddr, mLocalSipAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initHeader() {
|
|
||||||
if (mRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) {
|
|
||||||
Address remoteParticipantAddr = mRoomAddr;
|
|
||||||
if (mRoom.getParticipants().length > 0) {
|
|
||||||
remoteParticipantAddr = mRoom.getParticipants()[0].getAddress();
|
|
||||||
}
|
|
||||||
LinphoneContact c =
|
|
||||||
ContactsManager.getInstance().findContactFromAddress(remoteParticipantAddr);
|
|
||||||
String displayName;
|
|
||||||
if (c != null) {
|
|
||||||
displayName = c.getFullName();
|
|
||||||
} else {
|
|
||||||
displayName = LinphoneUtils.getAddressDisplayName(remoteParticipantAddr);
|
|
||||||
}
|
|
||||||
mTitle.setText(getString(R.string.chat_room_devices).replace("%s", displayName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initValues() {
|
private void initValues() {
|
||||||
if (mAdapter == null) {
|
if (mAdapter == null) {
|
||||||
mAdapter = new DevicesAdapter(getActivity());
|
mAdapter = new DevicesAdapter(getActivity());
|
||||||
|
|
|
@ -30,9 +30,9 @@ import org.linphone.LinphoneContext;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactAddress;
|
import org.linphone.contacts.ContactAddress;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.ChatRoom;
|
import org.linphone.core.ChatRoom;
|
||||||
import org.linphone.core.Participant;
|
import org.linphone.core.Participant;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoViewHolder> {
|
class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoViewHolder> {
|
||||||
private List<ContactAddress> mItems;
|
private List<ContactAddress> mItems;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentManager;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
@ -42,6 +41,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||||
import org.linphone.contacts.ContactAddress;
|
import org.linphone.contacts.ContactAddress;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
@ -56,7 +56,6 @@ import org.linphone.core.Factory;
|
||||||
import org.linphone.core.Participant;
|
import org.linphone.core.Participant;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
|
||||||
|
|
||||||
public class GroupInfoFragment extends Fragment {
|
public class GroupInfoFragment extends Fragment {
|
||||||
private ImageView mConfirmButton;
|
private ImageView mConfirmButton;
|
||||||
|
@ -146,7 +145,11 @@ public class GroupInfoFragment extends Fragment {
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
|
if (mIsAlreadyCreatedGroup) {
|
||||||
((ChatActivity) getActivity()).goBack();
|
((ChatActivity) getActivity()).goBack();
|
||||||
|
} else {
|
||||||
|
goBackToChatCreationFragment();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -262,6 +265,16 @@ public class GroupInfoFragment extends Fragment {
|
||||||
public void onSubjectChanged(ChatRoom cr, EventLog event_log) {
|
public void onSubjectChanged(ChatRoom cr, EventLog event_log) {
|
||||||
mSubjectField.setText(event_log.getSubject());
|
mSubjectField.setText(event_log.getSubject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onParticipantAdded(ChatRoom cr, EventLog eventLog) {
|
||||||
|
refreshParticipantsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onParticipantRemoved(ChatRoom cr, EventLog eventLog) {
|
||||||
|
refreshParticipantsList();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mChatRoom != null) {
|
if (mChatRoom != null) {
|
||||||
|
@ -300,26 +313,14 @@ public class GroupInfoFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void goBackToChatCreationFragment() {
|
private void goBackToChatCreationFragment() {
|
||||||
boolean previousFragmentInBackStackIsChatRoomCreation = false;
|
|
||||||
FragmentManager fragmentManager = getActivity().getFragmentManager();
|
|
||||||
int count = fragmentManager.getBackStackEntryCount();
|
|
||||||
if (count > 1) {
|
|
||||||
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(count - 1);
|
|
||||||
if ("Chat room creation".equals(entry.getName())) {
|
|
||||||
previousFragmentInBackStackIsChatRoomCreation = true;
|
|
||||||
((ChatActivity) getActivity()).goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!previousFragmentInBackStackIsChatRoomCreation) {
|
|
||||||
((ChatActivity) getActivity())
|
((ChatActivity) getActivity())
|
||||||
.showChatRoomCreation(
|
.showChatRoomCreation(
|
||||||
mGroupChatRoomAddress,
|
mGroupChatRoomAddress,
|
||||||
mParticipants,
|
mParticipants,
|
||||||
mSubject,
|
mSubject,
|
||||||
mIsEncryptionEnabled,
|
mIsEncryptionEnabled,
|
||||||
true);
|
true,
|
||||||
}
|
!mIsAlreadyCreatedGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshParticipantsList() {
|
private void refreshParticipantsList() {
|
||||||
|
@ -485,7 +486,9 @@ public class GroupInfoFragment extends Fragment {
|
||||||
}
|
}
|
||||||
Address[] participantsToAdd = new Address[toAdd.size()];
|
Address[] participantsToAdd = new Address[toAdd.size()];
|
||||||
toAdd.toArray(participantsToAdd);
|
toAdd.toArray(participantsToAdd);
|
||||||
mChatRoom.addParticipants(participantsToAdd);
|
if (!mChatRoom.addParticipants(participantsToAdd)) {
|
||||||
|
// TODO error
|
||||||
|
}
|
||||||
// Pop back stack to go back to the Messages fragment
|
// Pop back stack to go back to the Messages fragment
|
||||||
getFragmentManager().popBackStack();
|
getFragmentManager().popBackStack();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatMessage;
|
import org.linphone.core.ChatMessage;
|
||||||
import org.linphone.core.ChatMessageListenerStub;
|
import org.linphone.core.ChatMessageListenerStub;
|
||||||
|
@ -40,7 +41,6 @@ import org.linphone.core.Core;
|
||||||
import org.linphone.core.Factory;
|
import org.linphone.core.Factory;
|
||||||
import org.linphone.core.ParticipantImdnState;
|
import org.linphone.core.ParticipantImdnState;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class ImdnFragment extends Fragment {
|
public class ImdnFragment extends Fragment {
|
||||||
private LayoutInflater mInflater;
|
private LayoutInflater mInflater;
|
||||||
|
|
|
@ -140,7 +140,6 @@ class ApiTwentyFourPlus {
|
||||||
return new Notification.Builder(context)
|
return new Notification.Builder(context)
|
||||||
.setStyle(new Notification.DecoratedCustomViewStyle())
|
.setStyle(new Notification.DecoratedCustomViewStyle())
|
||||||
.setSmallIcon(R.drawable.topbar_call_notification)
|
.setSmallIcon(R.drawable.topbar_call_notification)
|
||||||
.setLargeIcon(contactIcon)
|
|
||||||
.setContentTitle(contactName)
|
.setContentTitle(contactName)
|
||||||
.setContentText(context.getString(R.string.incall_notif_incoming))
|
.setContentText(context.getString(R.string.incall_notif_incoming))
|
||||||
.setContentIntent(intent)
|
.setContentIntent(intent)
|
||||||
|
|
|
@ -183,7 +183,7 @@ class ApiTwentyOnePlus {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Notification createMissedCallNotification(
|
public static Notification createMissedCallNotification(
|
||||||
Context context, String title, String text, PendingIntent intent) {
|
Context context, String title, String text, PendingIntent intent, int count) {
|
||||||
|
|
||||||
return new Notification.Builder(context)
|
return new Notification.Builder(context)
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
|
@ -201,6 +201,7 @@ class ApiTwentyOnePlus {
|
||||||
.setPriority(Notification.PRIORITY_HIGH)
|
.setPriority(Notification.PRIORITY_HIGH)
|
||||||
.setWhen(System.currentTimeMillis())
|
.setWhen(System.currentTimeMillis())
|
||||||
.setShowWhen(true)
|
.setShowWhen(true)
|
||||||
|
.setNumber(count)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ class ApiTwentySixPlus {
|
||||||
CharSequence name = context.getString(R.string.content_title_notification_service);
|
CharSequence name = context.getString(R.string.content_title_notification_service);
|
||||||
String description = context.getString(R.string.content_title_notification_service);
|
String description = context.getString(R.string.content_title_notification_service);
|
||||||
NotificationChannel channel =
|
NotificationChannel channel =
|
||||||
new NotificationChannel(id, name, NotificationManager.IMPORTANCE_NONE);
|
new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
|
||||||
channel.setDescription(description);
|
channel.setDescription(description);
|
||||||
channel.enableVibration(false);
|
channel.enableVibration(false);
|
||||||
channel.enableLights(false);
|
channel.enableLights(false);
|
||||||
|
@ -191,7 +191,6 @@ class ApiTwentySixPlus {
|
||||||
context, context.getString(R.string.notification_channel_id))
|
context, context.getString(R.string.notification_channel_id))
|
||||||
.setStyle(new Notification.DecoratedCustomViewStyle())
|
.setStyle(new Notification.DecoratedCustomViewStyle())
|
||||||
.setSmallIcon(R.drawable.topbar_call_notification)
|
.setSmallIcon(R.drawable.topbar_call_notification)
|
||||||
.setLargeIcon(contactIcon)
|
|
||||||
.setContentTitle(contactName)
|
.setContentTitle(contactName)
|
||||||
.setContentText(context.getString(R.string.incall_notif_incoming))
|
.setContentText(context.getString(R.string.incall_notif_incoming))
|
||||||
.setContentIntent(intent)
|
.setContentIntent(intent)
|
||||||
|
@ -255,7 +254,7 @@ class ApiTwentySixPlus {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Notification createMissedCallNotification(
|
public static Notification createMissedCallNotification(
|
||||||
Context context, String title, String text, PendingIntent intent) {
|
Context context, String title, String text, PendingIntent intent, int count) {
|
||||||
return new Notification.Builder(
|
return new Notification.Builder(
|
||||||
context, context.getString(R.string.notification_channel_id))
|
context, context.getString(R.string.notification_channel_id))
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
|
@ -269,6 +268,7 @@ class ApiTwentySixPlus {
|
||||||
.setPriority(Notification.PRIORITY_HIGH)
|
.setPriority(Notification.PRIORITY_HIGH)
|
||||||
.setWhen(System.currentTimeMillis())
|
.setWhen(System.currentTimeMillis())
|
||||||
.setShowWhen(true)
|
.setShowWhen(true)
|
||||||
|
.setNumber(count)
|
||||||
.setColor(context.getColor(R.color.notification_led_color))
|
.setColor(context.getColor(R.color.notification_led_color))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.annotation.TargetApi;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
|
@ -111,4 +112,8 @@ class ApiTwentyThreePlus {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StatusBarNotification[] getActiveNotifications(NotificationManager manager) {
|
||||||
|
return manager.getActiveNotifications();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.linphone.compatibility;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
|
@ -30,6 +31,7 @@ import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.mediastream.Version;
|
import org.linphone.mediastream.Version;
|
||||||
import org.linphone.notifications.Notifiable;
|
import org.linphone.notifications.Notifiable;
|
||||||
|
@ -103,11 +105,12 @@ public class Compatibility {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Notification createMissedCallNotification(
|
public static Notification createMissedCallNotification(
|
||||||
Context context, String title, String text, PendingIntent intent) {
|
Context context, String title, String text, PendingIntent intent, int count) {
|
||||||
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||||
return ApiTwentySixPlus.createMissedCallNotification(context, title, text, intent);
|
return ApiTwentySixPlus.createMissedCallNotification(
|
||||||
|
context, title, text, intent, count);
|
||||||
}
|
}
|
||||||
return ApiTwentyOnePlus.createMissedCallNotification(context, title, text, intent);
|
return ApiTwentyOnePlus.createMissedCallNotification(context, title, text, intent, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Notification createInCallNotification(
|
public static Notification createInCallNotification(
|
||||||
|
@ -308,4 +311,12 @@ public class Compatibility {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StatusBarNotification[] getActiveNotifications(NotificationManager manager) {
|
||||||
|
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||||
|
return ApiTwentyThreePlus.getActiveNotifications(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StatusBarNotification[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.content.ContentProviderOperation;
|
||||||
import android.content.ContentProviderResult;
|
import android.content.ContentProviderResult;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
|
@ -30,6 +31,8 @@ import android.provider.ContactsContract.CommonDataKinds;
|
||||||
import android.provider.ContactsContract.Contacts;
|
import android.provider.ContactsContract.Contacts;
|
||||||
import android.provider.ContactsContract.Data;
|
import android.provider.ContactsContract.Data;
|
||||||
import android.provider.ContactsContract.RawContacts;
|
import android.provider.ContactsContract.RawContacts;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneContext;
|
import org.linphone.LinphoneContext;
|
||||||
|
@ -41,10 +44,12 @@ class AndroidContact implements Serializable {
|
||||||
private String mAndroidRawId;
|
private String mAndroidRawId;
|
||||||
private boolean isAndroidRawIdLinphone;
|
private boolean isAndroidRawIdLinphone;
|
||||||
private final transient ArrayList<ContentProviderOperation> mChangesToCommit;
|
private final transient ArrayList<ContentProviderOperation> mChangesToCommit;
|
||||||
|
private byte[] mTempPicture;
|
||||||
|
|
||||||
AndroidContact() {
|
AndroidContact() {
|
||||||
mChangesToCommit = new ArrayList<>();
|
mChangesToCommit = new ArrayList<>();
|
||||||
isAndroidRawIdLinphone = false;
|
isAndroidRawIdLinphone = false;
|
||||||
|
mTempPicture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getAndroidId() {
|
String getAndroidId() {
|
||||||
|
@ -78,6 +83,12 @@ class AndroidContact implements Serializable {
|
||||||
String rawId = String.valueOf(ContentUris.parseId(results[0].uri));
|
String rawId = String.valueOf(ContentUris.parseId(results[0].uri));
|
||||||
if (mAndroidId == null) {
|
if (mAndroidId == null) {
|
||||||
Log.i("[Contact] Contact created with RAW ID " + rawId);
|
Log.i("[Contact] Contact created with RAW ID " + rawId);
|
||||||
|
mAndroidRawId = rawId;
|
||||||
|
if (mTempPicture != null) {
|
||||||
|
Log.i(
|
||||||
|
"[Contact] Contact has been created, raw is is available, time to set the photo");
|
||||||
|
setPhoto(mTempPicture);
|
||||||
|
}
|
||||||
|
|
||||||
final String[] projection =
|
final String[] projection =
|
||||||
new String[] {ContactsContract.RawContacts.CONTACT_ID};
|
new String[] {ContactsContract.RawContacts.CONTACT_ID};
|
||||||
|
@ -146,6 +157,7 @@ class AndroidContact implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteAndroidContact() {
|
void deleteAndroidContact() {
|
||||||
|
Log.i("[Contact] Deleting Android contact ", this);
|
||||||
ContactsManager.getInstance().delete(mAndroidId);
|
ContactsManager.getInstance().delete(mAndroidId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,33 +562,44 @@ class AndroidContact implements Serializable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAndroidId == null) {
|
if (mAndroidRawId == null) {
|
||||||
Log.i("[Contact] Setting picture to new contact.");
|
Log.w("[Contact] Can't set picture for not already created contact, will do it later");
|
||||||
addChangesToCommit(
|
mTempPicture = photo;
|
||||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
|
||||||
.withValue(
|
|
||||||
ContactsContract.Data.MIMETYPE,
|
|
||||||
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
|
|
||||||
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
|
|
||||||
.build());
|
|
||||||
} else {
|
} else {
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Contact] Setting picture to existing contact "
|
"[Contact] Setting picture to an already created raw contact [",
|
||||||
+ mAndroidId
|
mAndroidRawId,
|
||||||
+ " ("
|
"]");
|
||||||
+ mAndroidRawId
|
try {
|
||||||
+ ")");
|
long rawId = Long.parseLong(mAndroidRawId);
|
||||||
addChangesToCommit(
|
|
||||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
Uri rawContactPhotoUri =
|
||||||
.withValue(ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
|
Uri.withAppendedPath(
|
||||||
.withValue(
|
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawId),
|
||||||
ContactsContract.Data.MIMETYPE,
|
RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
|
||||||
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
|
|
||||||
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
|
if (rawContactPhotoUri != null) {
|
||||||
.withValue(ContactsContract.Data.IS_PRIMARY, 1)
|
ContentResolver resolver =
|
||||||
.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
|
LinphoneContext.instance().getApplicationContext().getContentResolver();
|
||||||
.build());
|
AssetFileDescriptor fd =
|
||||||
|
resolver.openAssetFileDescriptor(rawContactPhotoUri, "rw");
|
||||||
|
OutputStream os = fd.createOutputStream();
|
||||||
|
os.write(photo);
|
||||||
|
os.close();
|
||||||
|
fd.close();
|
||||||
|
} else {
|
||||||
|
Log.e(
|
||||||
|
"[Contact] Failed to get raw contact photo URI for raw contact id [",
|
||||||
|
rawId,
|
||||||
|
"], aborting");
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
Log.e("[Contact] Couldn't parse raw id [", mAndroidId, "], aborting");
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.e("[Contact] Couldn't set picture, IO error: ", ioe);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("[Contact] Couldn't set picture, unknown error: ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,21 +79,6 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
protected AsyncContactsData doInBackground(Void... params) {
|
protected AsyncContactsData doInBackground(Void... params) {
|
||||||
Log.i("[Contacts Manager] Background synchronization started");
|
Log.i("[Contacts Manager] Background synchronization started");
|
||||||
|
|
||||||
String selection = null;
|
|
||||||
if (mContext.getResources().getBoolean(R.bool.fetch_contacts_from_default_directory)) {
|
|
||||||
Log.i("[Contacts Manager] Only fetching contacts in default directory");
|
|
||||||
selection = ContactsContract.Data.IN_DEFAULT_DIRECTORY + " == 1";
|
|
||||||
}
|
|
||||||
|
|
||||||
Cursor c =
|
|
||||||
mContext.getContentResolver()
|
|
||||||
.query(
|
|
||||||
ContactsContract.Data.CONTENT_URI,
|
|
||||||
PROJECTION,
|
|
||||||
selection,
|
|
||||||
null,
|
|
||||||
null);
|
|
||||||
|
|
||||||
HashMap<String, LinphoneContact> androidContactsCache = new HashMap<>();
|
HashMap<String, LinphoneContact> androidContactsCache = new HashMap<>();
|
||||||
AsyncContactsData data = new AsyncContactsData();
|
AsyncContactsData data = new AsyncContactsData();
|
||||||
List<String> nativeIds = new ArrayList<>();
|
List<String> nativeIds = new ArrayList<>();
|
||||||
|
@ -111,10 +96,12 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
|
|
||||||
LinphoneContact contact = (LinphoneContact) friend.getUserData();
|
LinphoneContact contact = (LinphoneContact) friend.getUserData();
|
||||||
if (contact != null) {
|
if (contact != null) {
|
||||||
contact.clearAddresses();
|
|
||||||
if (contact.getAndroidId() != null) {
|
if (contact.getAndroidId() != null) {
|
||||||
|
contact.clearAddresses();
|
||||||
androidContactsCache.put(contact.getAndroidId(), contact);
|
androidContactsCache.put(contact.getAndroidId(), contact);
|
||||||
nativeIds.add(contact.getAndroidId());
|
nativeIds.add(contact.getAndroidId());
|
||||||
|
} else {
|
||||||
|
data.contacts.add(contact);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (friend.getRefKey() != null) {
|
if (friend.getRefKey() != null) {
|
||||||
|
@ -134,6 +121,21 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ContactsManager.getInstance().hasReadContactsAccess()) {
|
||||||
|
String selection = null;
|
||||||
|
if (mContext.getResources().getBoolean(R.bool.fetch_contacts_from_default_directory)) {
|
||||||
|
Log.i("[Contacts Manager] Only fetching contacts in default directory");
|
||||||
|
selection = ContactsContract.Data.IN_DEFAULT_DIRECTORY + " == 1";
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor c =
|
||||||
|
mContext.getContentResolver()
|
||||||
|
.query(
|
||||||
|
ContactsContract.Data.CONTENT_URI,
|
||||||
|
PROJECTION,
|
||||||
|
selection,
|
||||||
|
null,
|
||||||
|
null);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
Log.i("[Contacts Manager] Found " + c.getCount() + " entries in cursor");
|
Log.i("[Contacts Manager] Found " + c.getCount() + " entries in cursor");
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
|
@ -142,6 +144,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
String id = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
|
String id = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
|
||||||
boolean starred =
|
boolean starred =
|
||||||
c.getInt(c.getColumnIndex(ContactsContract.Contacts.STARRED)) == 1;
|
c.getInt(c.getColumnIndex(ContactsContract.Contacts.STARRED)) == 1;
|
||||||
|
@ -161,8 +164,14 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
}
|
}
|
||||||
|
|
||||||
contact.syncValuesFromAndroidCusor(c);
|
contact.syncValuesFromAndroidCusor(c);
|
||||||
|
} catch (IllegalStateException ise) {
|
||||||
|
Log.e(
|
||||||
|
"[Contacts Manager] Couldn't get values from cursor, exception: ",
|
||||||
|
ise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c.close();
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
FriendList[] friendLists = core.getFriendsLists();
|
FriendList[] friendLists = core.getFriendsLists();
|
||||||
for (FriendList list : friendLists) {
|
for (FriendList list : friendLists) {
|
||||||
|
@ -188,7 +197,13 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<LinphoneContact> contacts = androidContactsCache.values();
|
Collection<LinphoneContact> contacts = androidContactsCache.values();
|
||||||
Log.i("[Contacts Manager] Found " + contacts.size() + " contacts");
|
// New friends count will be 0 after the first contacts fetch
|
||||||
|
Log.i(
|
||||||
|
"[Contacts Manager] Found "
|
||||||
|
+ contacts.size()
|
||||||
|
+ " native contacts plus "
|
||||||
|
+ data.contacts.size()
|
||||||
|
+ " friends in the configuration file");
|
||||||
for (LinphoneContact contact : contacts) {
|
for (LinphoneContact contact : contacts) {
|
||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
Log.w("[Contacts Manager] Task cancelled");
|
Log.w("[Contacts Manager] Task cancelled");
|
||||||
|
|
|
@ -36,6 +36,7 @@ import android.widget.TableLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.ChatRoom;
|
import org.linphone.core.ChatRoom;
|
||||||
import org.linphone.core.ChatRoomBackend;
|
import org.linphone.core.ChatRoomBackend;
|
||||||
|
@ -50,7 +51,6 @@ import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class ContactDetailsFragment extends Fragment implements ContactsUpdatedListener {
|
public class ContactDetailsFragment extends Fragment implements ContactsUpdatedListener {
|
||||||
private LinphoneContact mContact;
|
private LinphoneContact mContact;
|
||||||
|
@ -90,6 +90,11 @@ public class ContactDetailsFragment extends Fragment implements ContactsUpdatedL
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (mContact != null
|
||||||
|
&& getResources().getBoolean(R.bool.forbid_pure_linphone_contacts_edition)) {
|
||||||
|
editContact.setVisibility(mContact.isAndroidContact() ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
ImageView deleteContact = mView.findViewById(R.id.deleteContact);
|
ImageView deleteContact = mView.findViewById(R.id.deleteContact);
|
||||||
deleteContact.setOnClickListener(
|
deleteContact.setOnClickListener(
|
||||||
new OnClickListener() {
|
new OnClickListener() {
|
||||||
|
@ -359,6 +364,8 @@ public class ContactDetailsFragment extends Fragment implements ContactsUpdatedL
|
||||||
|
|
||||||
private void goToChat(String tag, boolean isSecured) {
|
private void goToChat(String tag, boolean isSecured) {
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core == null) return;
|
||||||
|
|
||||||
Address participant = Factory.instance().createAddress(tag);
|
Address participant = Factory.instance().createAddress(tag);
|
||||||
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
|
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
|
||||||
|
|
||||||
|
@ -404,6 +411,18 @@ public class ContactDetailsFragment extends Fragment implements ContactsUpdatedL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (isSecured) {
|
||||||
|
Log.e(
|
||||||
|
"[Contact Details Fragment] Can't create a secured chat room without proxy config");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatRoom room = core.getChatRoom(participant);
|
||||||
|
if (room != null) {
|
||||||
|
((ContactsActivity) getActivity())
|
||||||
|
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,12 @@ import android.app.Dialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.media.ExifInterface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.provider.ContactsContract.DisplayPhoto;
|
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
@ -53,12 +52,13 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.mediastream.Version;
|
import org.linphone.mediastream.Version;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.FileUtils;
|
import org.linphone.utils.FileUtils;
|
||||||
|
import org.linphone.utils.ImageUtils;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class ContactEditorFragment extends Fragment {
|
public class ContactEditorFragment extends Fragment {
|
||||||
private static final int ADD_PHOTO = 1337;
|
private static final int ADD_PHOTO = 1337;
|
||||||
|
@ -136,12 +136,15 @@ public class ContactEditorFragment extends Fragment {
|
||||||
if (mIsNewContact) {
|
if (mIsNewContact) {
|
||||||
boolean areAllFielsEmpty = true;
|
boolean areAllFielsEmpty = true;
|
||||||
for (LinphoneNumberOrAddress nounoa : mNumbersAndAddresses) {
|
for (LinphoneNumberOrAddress nounoa : mNumbersAndAddresses) {
|
||||||
if (nounoa.getValue() != null && !nounoa.getValue().equals("")) {
|
String value = nounoa.getValue();
|
||||||
|
if (value != null && !value.trim().isEmpty()) {
|
||||||
areAllFielsEmpty = false;
|
areAllFielsEmpty = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (areAllFielsEmpty) {
|
if (areAllFielsEmpty) {
|
||||||
|
Log.i(
|
||||||
|
"[Contact Editor] All SIP and phone fields are empty, aborting");
|
||||||
getFragmentManager().popBackStackImmediate();
|
getFragmentManager().popBackStackImmediate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -154,37 +157,36 @@ public class ContactEditorFragment extends Fragment {
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (mPhotoToAdd != null) {
|
if (mPhotoToAdd != null) {
|
||||||
|
Log.i("[Contact Editor] Found picture to set to contact");
|
||||||
mContact.setPhoto(mPhotoToAdd);
|
mContact.setPhoto(mPhotoToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LinphoneNumberOrAddress noa : mNumbersAndAddresses) {
|
for (LinphoneNumberOrAddress noa : mNumbersAndAddresses) {
|
||||||
if (noa.getValue() == null || noa.getValue().isEmpty()) {
|
String value = noa.getValue();
|
||||||
if (noa.getOldValue() != null && !noa.getOldValue().isEmpty()) {
|
String oldValue = noa.getOldValue();
|
||||||
Log.i("[Contact Editor] Removing number " + noa.getOldValue());
|
|
||||||
|
if (value == null || value.trim().isEmpty()) {
|
||||||
|
if (oldValue != null && !oldValue.isEmpty()) {
|
||||||
|
Log.i("[Contact Editor] Removing number: ", oldValue);
|
||||||
mContact.removeNumberOrAddress(noa);
|
mContact.removeNumberOrAddress(noa);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (noa.getOldValue() != null
|
if (oldValue != null && oldValue.equals(value)) {
|
||||||
&& noa.getOldValue().equals(noa.getValue())) {
|
Log.i("[Contact Editor] Keeping existing number: ", value);
|
||||||
Log.i(
|
|
||||||
"[Contact Editor] Keeping existing number "
|
|
||||||
+ noa.getValue());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noa.isSIPAddress()) {
|
if (noa.isSIPAddress()) {
|
||||||
|
noa.setValue(LinphoneUtils.getFullAddressFromUsername(value));
|
||||||
noa.setValue(
|
|
||||||
LinphoneUtils.getFullAddressFromUsername(
|
|
||||||
noa.getValue()));
|
|
||||||
}
|
}
|
||||||
Log.i("[Contact Editor] Adding new number " + noa.getValue());
|
Log.i("[Contact Editor] Adding new number: ", value);
|
||||||
|
|
||||||
mContact.addOrUpdateNumberOrAddress(noa);
|
mContact.addOrUpdateNumberOrAddress(noa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mOrganization.getText().toString().isEmpty() || !mIsNewContact) {
|
if (!mOrganization.getText().toString().isEmpty() || !mIsNewContact) {
|
||||||
|
Log.i("[Contact Editor] Setting organization field: ", mOrganization);
|
||||||
mContact.setOrganization(mOrganization.getText().toString(), true);
|
mContact.setOrganization(mOrganization.getText().toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +196,8 @@ public class ContactEditorFragment extends Fragment {
|
||||||
// Ensure fetch will be done so the new contact appears in the contacts
|
// Ensure fetch will be done so the new contact appears in the contacts
|
||||||
// list: contacts content observer may not be notified if contacts sync
|
// list: contacts content observer may not be notified if contacts sync
|
||||||
// is disabled at system level
|
// is disabled at system level
|
||||||
|
Log.i(
|
||||||
|
"[Contact Editor] New contact created, starting fetch contacts task");
|
||||||
ContactsManager.getInstance().fetchContactsAsync();
|
ContactsManager.getInstance().fetchContactsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,9 +310,18 @@ public class ContactEditorFragment extends Fragment {
|
||||||
new OnClickListener() {
|
new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
|
ContactsActivity contactsActivity = ((ContactsActivity) getActivity());
|
||||||
|
if (contactsActivity != null) {
|
||||||
|
String[] permissions = {
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
|
Manifest.permission.CAMERA
|
||||||
|
};
|
||||||
|
if (contactsActivity.checkPermissions(permissions)) {
|
||||||
pickImage();
|
pickImage();
|
||||||
((ContactsActivity) getActivity())
|
} else {
|
||||||
.requestPermissionIfNotGranted(Manifest.permission.CAMERA);
|
contactsActivity.requestPermissionsIfNotGranted(permissions);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -386,15 +399,18 @@ public class ContactEditorFragment extends Fragment {
|
||||||
editContactPicture(null, bm);
|
editContactPicture(null, bm);
|
||||||
} else if (data != null && data.getData() != null) {
|
} else if (data != null && data.getData() != null) {
|
||||||
Uri selectedImageUri = data.getData();
|
Uri selectedImageUri = data.getData();
|
||||||
|
String filePath = FileUtils.getRealPathFromURI(getActivity(), selectedImageUri);
|
||||||
|
if (filePath != null) {
|
||||||
|
editContactPicture(filePath, null);
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
Bitmap selectedImage =
|
Bitmap selectedImage =
|
||||||
MediaStore.Images.Media.getBitmap(
|
MediaStore.Images.Media.getBitmap(
|
||||||
getActivity().getContentResolver(), selectedImageUri);
|
getActivity().getContentResolver(), selectedImageUri);
|
||||||
selectedImage =
|
|
||||||
Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false);
|
|
||||||
editContactPicture(null, selectedImage);
|
editContactPicture(null, selectedImage);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(e);
|
Log.e("[Contact Editor] IO error: ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (mPickedPhotoForContactUri != null) {
|
} else if (mPickedPhotoForContactUri != null) {
|
||||||
String filePath = mPickedPhotoForContactUri.getPath();
|
String filePath = mPickedPhotoForContactUri.getPath();
|
||||||
|
@ -426,11 +442,13 @@ public class ContactEditorFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mPhotoToAdd == null) {
|
||||||
if (mContact != null) {
|
if (mContact != null) {
|
||||||
ContactAvatar.displayAvatar(mContact, mView.findViewById(R.id.avatar_layout));
|
ContactAvatar.displayAvatar(mContact, mView.findViewById(R.id.avatar_layout));
|
||||||
} else {
|
} else {
|
||||||
ContactAvatar.displayAvatar("", mView.findViewById(R.id.avatar_layout));
|
ContactAvatar.displayAvatar("", mView.findViewById(R.id.avatar_layout));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mSipAddresses = initSipAddressFields(mContact);
|
mSipAddresses = initSipAddressFields(mContact);
|
||||||
mNumbers = initNumbersFields(mContact);
|
mNumbers = initNumbersFields(mContact);
|
||||||
|
@ -438,27 +456,24 @@ public class ContactEditorFragment extends Fragment {
|
||||||
|
|
||||||
private void pickImage() {
|
private void pickImage() {
|
||||||
mPickedPhotoForContactUri = null;
|
mPickedPhotoForContactUri = null;
|
||||||
final List<Intent> cameraIntents = new ArrayList<>();
|
List<Intent> cameraIntents = new ArrayList<>();
|
||||||
final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
|
||||||
|
// Handles image & video picking
|
||||||
|
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
|
||||||
|
galleryIntent.setType("image/*");
|
||||||
|
|
||||||
|
// Allows to capture directly from the camera
|
||||||
|
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||||
File file =
|
File file =
|
||||||
new File(
|
new File(
|
||||||
FileUtils.getStorageDirectory(getActivity()),
|
FileUtils.getStorageDirectory(getActivity()),
|
||||||
getString(R.string.temp_photo_name));
|
getString(R.string.temp_photo_name_with_date)
|
||||||
|
.replace("%s", System.currentTimeMillis() + ".jpeg"));
|
||||||
mPickedPhotoForContactUri = Uri.fromFile(file);
|
mPickedPhotoForContactUri = Uri.fromFile(file);
|
||||||
captureIntent.putExtra("outputX", PHOTO_SIZE);
|
|
||||||
captureIntent.putExtra("outputY", PHOTO_SIZE);
|
|
||||||
captureIntent.putExtra("aspectX", 0);
|
|
||||||
captureIntent.putExtra("aspectY", 0);
|
|
||||||
captureIntent.putExtra("scale", true);
|
|
||||||
captureIntent.putExtra("return-data", false);
|
|
||||||
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mPickedPhotoForContactUri);
|
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mPickedPhotoForContactUri);
|
||||||
cameraIntents.add(captureIntent);
|
cameraIntents.add(captureIntent);
|
||||||
|
|
||||||
final Intent galleryIntent = new Intent();
|
Intent chooserIntent =
|
||||||
galleryIntent.setType("image/*");
|
|
||||||
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
|
|
||||||
|
|
||||||
final Intent chooserIntent =
|
|
||||||
Intent.createChooser(galleryIntent, getString(R.string.image_picker_title));
|
Intent.createChooser(galleryIntent, getString(R.string.image_picker_title));
|
||||||
chooserIntent.putExtra(
|
chooserIntent.putExtra(
|
||||||
Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {}));
|
Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {}));
|
||||||
|
@ -467,44 +482,59 @@ public class ContactEditorFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void editContactPicture(String filePath, Bitmap image) {
|
private void editContactPicture(String filePath, Bitmap image) {
|
||||||
|
int orientation = ExifInterface.ORIENTATION_NORMAL;
|
||||||
|
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
|
Log.i(
|
||||||
|
"[Contact Editor] Bitmap is null, trying to decode image from file [",
|
||||||
|
filePath,
|
||||||
|
"]");
|
||||||
image = BitmapFactory.decodeFile(filePath);
|
image = BitmapFactory.decodeFile(filePath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ExifInterface ei = new ExifInterface(filePath);
|
||||||
|
orientation =
|
||||||
|
ei.getAttributeInt(
|
||||||
|
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
|
||||||
|
Log.i("[Contact Editor] Exif rotation is ", orientation);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("[Contact Editor] Failed to get Exif rotation, error is ", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (image == null) {
|
||||||
|
Log.e(
|
||||||
|
"[Contact Editor] Couldn't get bitmap from either filePath [",
|
||||||
|
filePath,
|
||||||
|
"] nor image");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap scaledPhoto;
|
switch (orientation) {
|
||||||
int size = getThumbnailSize();
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
if (size > 0) {
|
image = ImageUtils.rotateImage(image, 90);
|
||||||
scaledPhoto = Bitmap.createScaledBitmap(image, size, size, false);
|
break;
|
||||||
} else {
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
scaledPhoto = Bitmap.createBitmap(image);
|
image = ImageUtils.rotateImage(image, 180);
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
image = ImageUtils.rotateImage(image, 270);
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_NORMAL:
|
||||||
|
// Nothing to do
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.w("[Contact Editor] Unexpected orientation ", orientation);
|
||||||
}
|
}
|
||||||
image.recycle();
|
|
||||||
|
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
scaledPhoto.compress(Bitmap.CompressFormat.PNG, 0, stream);
|
image.compress(Bitmap.CompressFormat.JPEG, 100, stream);
|
||||||
mContactPicture.setImageBitmap(scaledPhoto);
|
|
||||||
mPhotoToAdd = stream.toByteArray();
|
mPhotoToAdd = stream.toByteArray();
|
||||||
}
|
|
||||||
|
|
||||||
private int getThumbnailSize() {
|
Bitmap roundPicture = ImageUtils.getRoundBitmap(image);
|
||||||
int value = -1;
|
ContactAvatar.displayAvatar(roundPicture, mView.findViewById(R.id.avatar_layout));
|
||||||
Cursor c =
|
image.recycle();
|
||||||
getActivity()
|
|
||||||
.getContentResolver()
|
|
||||||
.query(
|
|
||||||
DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
|
|
||||||
new String[] {DisplayPhoto.THUMBNAIL_MAX_DIM},
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null);
|
|
||||||
try {
|
|
||||||
c.moveToFirst();
|
|
||||||
value = c.getInt(0);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
c.close();
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinearLayout initNumbersFields(final LinphoneContact contact) {
|
private LinearLayout initNumbersFields(final LinphoneContact contact) {
|
||||||
|
|
|
@ -102,6 +102,15 @@ public class ContactsActivity extends MainActivity {
|
||||||
mContactsSelected.setVisibility(View.VISIBLE);
|
mContactsSelected.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
// From the moment this activity is leaved, clear these values
|
||||||
|
mEditDisplayName = null;
|
||||||
|
mEditSipUri = null;
|
||||||
|
mEditOnClick = false;
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
|
|
@ -31,10 +31,10 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.SelectableAdapter;
|
import org.linphone.utils.SelectableAdapter;
|
||||||
import org.linphone.utils.SelectableHelper;
|
import org.linphone.utils.SelectableHelper;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class ContactsAdapter extends SelectableAdapter<ContactViewHolder>
|
public class ContactsAdapter extends SelectableAdapter<ContactViewHolder>
|
||||||
implements SectionIndexer {
|
implements SectionIndexer {
|
||||||
|
|
|
@ -39,8 +39,8 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||||
import org.linphone.utils.SelectableHelper;
|
import org.linphone.utils.SelectableHelper;
|
||||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
|
||||||
|
|
||||||
public class ContactsFragment extends Fragment
|
public class ContactsFragment extends Fragment
|
||||||
implements OnItemClickListener,
|
implements OnItemClickListener,
|
||||||
|
|
|
@ -55,7 +55,8 @@ import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
|
|
||||||
public class ContactsManager extends ContentObserver implements FriendListListener {
|
public class ContactsManager extends ContentObserver
|
||||||
|
implements FriendListListener, LinphoneContext.CoreStartedListener {
|
||||||
private List<LinphoneContact> mContacts, mSipContacts;
|
private List<LinphoneContact> mContacts, mSipContacts;
|
||||||
private final ArrayList<ContactsUpdatedListener> mContactsUpdatedListeners;
|
private final ArrayList<ContactsUpdatedListener> mContactsUpdatedListeners;
|
||||||
private MagicSearch mMagicSearch;
|
private MagicSearch mMagicSearch;
|
||||||
|
@ -79,6 +80,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
mMagicSearch = LinphoneManager.getCore().createMagicSearch();
|
mMagicSearch = LinphoneManager.getCore().createMagicSearch();
|
||||||
mMagicSearch.setLimitedSearch(false); // Do not limit the number of results
|
mMagicSearch.setLimitedSearch(false); // Do not limit the number of results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinphoneContext.instance().addCoreStartedListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addContactsListener(ContactsUpdatedListener listener) {
|
public void addContactsListener(ContactsUpdatedListener listener) {
|
||||||
|
@ -104,6 +107,13 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
fetchContactsAsync();
|
fetchContactsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCoreStarted() {
|
||||||
|
// Core has been started, fetch contacts again in case there are some
|
||||||
|
// in the configuration file or remote provisioning
|
||||||
|
fetchContactsAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized List<LinphoneContact> getContacts() {
|
public synchronized List<LinphoneContact> getContacts() {
|
||||||
return mContacts;
|
return mContacts;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +132,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
mContext.getContentResolver().unregisterContentObserver(this);
|
mContext.getContentResolver().unregisterContentObserver(this);
|
||||||
|
LinphoneContext.instance().removeCoreStartedListener(this);
|
||||||
|
|
||||||
if (mLoadContactTask != null) {
|
if (mLoadContactTask != null) {
|
||||||
mLoadContactTask.cancel(true);
|
mLoadContactTask.cancel(true);
|
||||||
|
@ -149,10 +160,12 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
if (mLoadContactTask != null) {
|
if (mLoadContactTask != null) {
|
||||||
mLoadContactTask.cancel(true);
|
mLoadContactTask.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasReadContactsAccess()) {
|
if (!hasReadContactsAccess()) {
|
||||||
Log.w("[Contacts Manager] Can't fetch contact without READ permission");
|
Log.w(
|
||||||
return;
|
"[Contacts Manager] Can't fetch native contacts without READ_CONTACTS permission");
|
||||||
}
|
}
|
||||||
|
|
||||||
mLoadContactTask = new AsyncContactsLoader(mContext);
|
mLoadContactTask = new AsyncContactsLoader(mContext);
|
||||||
mContactsFetchedOnce = true;
|
mContactsFetchedOnce = true;
|
||||||
mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR);
|
mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||||
|
@ -212,6 +225,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
if (mContext == null) {
|
if (mContext == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean contactsR =
|
boolean contactsR =
|
||||||
(PackageManager.PERMISSION_GRANTED
|
(PackageManager.PERMISSION_GRANTED
|
||||||
== mContext.getPackageManager()
|
== mContext.getPackageManager()
|
||||||
|
@ -226,6 +240,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
if (mContext == null) {
|
if (mContext == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (PackageManager.PERMISSION_GRANTED
|
return (PackageManager.PERMISSION_GRANTED
|
||||||
== mContext.getPackageManager()
|
== mContext.getPackageManager()
|
||||||
.checkPermission(
|
.checkPermission(
|
||||||
|
@ -236,6 +251,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
if (mContext == null) {
|
if (mContext == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (PackageManager.PERMISSION_GRANTED
|
return (PackageManager.PERMISSION_GRANTED
|
||||||
== mContext.getPackageManager()
|
== mContext.getPackageManager()
|
||||||
.checkPermission(
|
.checkPermission(
|
||||||
|
@ -264,10 +280,6 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mContext != null && getContacts().isEmpty() && hasReadContactsAccess()) {
|
|
||||||
fetchContactsAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeContactAccountVisible() {
|
private void makeContactAccountVisible() {
|
||||||
|
@ -366,6 +378,11 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = address.getUsername();
|
String username = address.getUsername();
|
||||||
|
if (username == null) {
|
||||||
|
Log.w("[Contacts Manager] Address ", address.asString(), " doesn't have a username!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (android.util.Patterns.PHONE.matcher(username).matches()) {
|
if (android.util.Patterns.PHONE.matcher(username).matches()) {
|
||||||
return findContactFromPhoneNumber(username);
|
return findContactFromPhoneNumber(username);
|
||||||
}
|
}
|
||||||
|
@ -421,6 +438,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAddressOrNumberForAndroidContact(ContentResolver resolver, Uri contactUri) {
|
public String getAddressOrNumberForAndroidContact(ContentResolver resolver, Uri contactUri) {
|
||||||
|
if (resolver == null || contactUri == null) return null;
|
||||||
|
|
||||||
// Phone Numbers
|
// Phone Numbers
|
||||||
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
|
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
|
||||||
Cursor c = resolver.query(contactUri, projection, null, null, null);
|
Cursor c = resolver.query(contactUri, projection, null, null, null);
|
||||||
|
@ -431,8 +450,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
c.close();
|
c.close();
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
c.close();
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
|
projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
|
||||||
c = resolver.query(contactUri, projection, null, null, null);
|
c = resolver.query(contactUri, projection, null, null, null);
|
||||||
|
@ -444,12 +463,14 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
c.close();
|
c.close();
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
c.close();
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean refreshSipContact(Friend lf) {
|
private synchronized boolean refreshSipContact(Friend lf) {
|
||||||
|
if (lf == null) return false;
|
||||||
LinphoneContact contact = (LinphoneContact) lf.getUserData();
|
LinphoneContact contact = (LinphoneContact) lf.getUserData();
|
||||||
|
|
||||||
if (contact != null) {
|
if (contact != null) {
|
||||||
|
@ -486,6 +507,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
||||||
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
|
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
|
||||||
|
|
||||||
for (String id : ids) {
|
for (String id : ids) {
|
||||||
|
Log.i("[Contacts Manager] Adding Android contact id ", id, " to batch removal");
|
||||||
String[] args = new String[] {id};
|
String[] args = new String[] {id};
|
||||||
ops.add(
|
ops.add(
|
||||||
ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
|
ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.linphone.core.Address;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.Friend;
|
import org.linphone.core.Friend;
|
||||||
import org.linphone.core.FriendCapability;
|
import org.linphone.core.FriendCapability;
|
||||||
import org.linphone.core.FriendList;
|
|
||||||
import org.linphone.core.PresenceBasicStatus;
|
import org.linphone.core.PresenceBasicStatus;
|
||||||
import org.linphone.core.PresenceModel;
|
import org.linphone.core.PresenceModel;
|
||||||
import org.linphone.core.SubscribePolicy;
|
import org.linphone.core.SubscribePolicy;
|
||||||
|
@ -195,7 +194,7 @@ public class LinphoneContact extends AndroidContact
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPhotoUri(Uri uri) {
|
private void setPhotoUri(Uri uri) {
|
||||||
if (uri.equals(mPhotoUri)) return;
|
if (uri != null && uri.equals(mPhotoUri)) return;
|
||||||
mPhotoUri = uri;
|
mPhotoUri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +203,7 @@ public class LinphoneContact extends AndroidContact
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setThumbnailUri(Uri uri) {
|
private void setThumbnailUri(Uri uri) {
|
||||||
if (uri.equals(mThumbnailUri)) return;
|
if (uri != null && uri.equals(mThumbnailUri)) return;
|
||||||
mThumbnailUri = uri;
|
mThumbnailUri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,14 +215,16 @@ public class LinphoneContact extends AndroidContact
|
||||||
if (noa == null) return;
|
if (noa == null) return;
|
||||||
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
String normalizedPhone = noa.getNormalizedPhone();
|
||||||
// Check for duplicated phone numbers but with different formats
|
// Check for duplicated phone numbers but with different formats
|
||||||
for (LinphoneNumberOrAddress number : mAddresses) {
|
for (LinphoneNumberOrAddress number : mAddresses) {
|
||||||
if (!number.isSIPAddress()) {
|
if (!number.isSIPAddress()) {
|
||||||
if ((!noa.isSIPAddress()
|
if ((!noa.isSIPAddress()
|
||||||
&& noa.getNormalizedPhone().equals(number.getNormalizedPhone()))
|
&& normalizedPhone != null
|
||||||
|
&& normalizedPhone.equals(number.getNormalizedPhone()))
|
||||||
|| (noa.isSIPAddress()
|
|| (noa.isSIPAddress()
|
||||||
&& noa.getValue().equals(number.getNormalizedPhone()))
|
&& noa.getValue().equals(number.getNormalizedPhone()))
|
||||||
|| (noa.getNormalizedPhone().equals(number.getValue()))) {
|
|| (normalizedPhone != null && normalizedPhone.equals(number.getValue()))) {
|
||||||
Log.d("[Linphone Contact] Duplicated entry detected: " + noa);
|
Log.d("[Linphone Contact] Duplicated entry detected: " + noa);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -247,7 +248,8 @@ public class LinphoneContact extends AndroidContact
|
||||||
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
||||||
if (noa.isSIPAddress()) {
|
if (noa.isSIPAddress()) {
|
||||||
String value = noa.getValue();
|
String value = noa.getValue();
|
||||||
if (address.startsWith(value) || value.equals("sip:" + address)) {
|
if (value != null
|
||||||
|
&& (address.startsWith(value) || value.equals("sip:" + address))) {
|
||||||
// Startswith is to workaround the fact that the
|
// Startswith is to workaround the fact that the
|
||||||
// address may have a ;gruu= at the end...
|
// address may have a ;gruu= at the end...
|
||||||
return true;
|
return true;
|
||||||
|
@ -274,7 +276,8 @@ public class LinphoneContact extends AndroidContact
|
||||||
}
|
}
|
||||||
LinphoneNumberOrAddress toRemove = null;
|
LinphoneNumberOrAddress toRemove = null;
|
||||||
for (LinphoneNumberOrAddress address : mAddresses) {
|
for (LinphoneNumberOrAddress address : mAddresses) {
|
||||||
if (noa.getOldValue().equals(address.getValue())
|
if (noa.getOldValue() != null
|
||||||
|
&& noa.getOldValue().equals(address.getValue())
|
||||||
&& noa.isSIPAddress() == address.isSIPAddress()) {
|
&& noa.isSIPAddress() == address.isSIPAddress()) {
|
||||||
toRemove = address;
|
toRemove = address;
|
||||||
break;
|
break;
|
||||||
|
@ -305,7 +308,8 @@ public class LinphoneContact extends AndroidContact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (LinphoneNumberOrAddress address : mAddresses) {
|
for (LinphoneNumberOrAddress address : mAddresses) {
|
||||||
if (noa.getOldValue().equals(address.getValue())
|
if (noa.getOldValue() != null
|
||||||
|
&& noa.getOldValue().equals(address.getValue())
|
||||||
&& noa.isSIPAddress() == address.isSIPAddress()) {
|
&& noa.isSIPAddress() == address.isSIPAddress()) {
|
||||||
address.setValue(noa.getValue());
|
address.setValue(noa.getValue());
|
||||||
break;
|
break;
|
||||||
|
@ -352,10 +356,11 @@ public class LinphoneContact extends AndroidContact
|
||||||
if (mFriend.getVcard() != null) {
|
if (mFriend.getVcard() != null) {
|
||||||
mFriend.getVcard().setFamilyName(mLastName);
|
mFriend.getVcard().setFamilyName(mLastName);
|
||||||
mFriend.getVcard().setGivenName(mFirstName);
|
mFriend.getVcard().setGivenName(mFirstName);
|
||||||
}
|
|
||||||
if (mOrganization != null) {
|
if (mOrganization != null) {
|
||||||
mFriend.getVcard().setOrganization(mOrganization);
|
mFriend.getVcard().setOrganization(mOrganization);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!created) {
|
if (!created) {
|
||||||
for (Address address : mFriend.getAddresses()) {
|
for (Address address : mFriend.getAddresses()) {
|
||||||
|
@ -395,12 +400,12 @@ public class LinphoneContact extends AndroidContact
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteFriend() {
|
public void deleteFriend() {
|
||||||
|
if (mFriend == null) return;
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
if (mFriend != null && core != null) {
|
if (core == null) return;
|
||||||
for (FriendList list : core.getFriendsLists()) {
|
|
||||||
list.removeFriend(mFriend);
|
Log.i("[Contact] Deleting friend ", mFriend.getName(), " for contact ", this);
|
||||||
}
|
mFriend.remove();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createOrUpdateFriendFromNativeContact() {
|
public void createOrUpdateFriendFromNativeContact() {
|
||||||
|
@ -427,7 +432,9 @@ public class LinphoneContact extends AndroidContact
|
||||||
if (mFriend == null) return false;
|
if (mFriend == null) return false;
|
||||||
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
||||||
PresenceModel pm = mFriend.getPresenceModelForUriOrTel(noa.getValue());
|
PresenceModel pm = mFriend.getPresenceModelForUriOrTel(noa.getValue());
|
||||||
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
|
if (pm != null
|
||||||
|
&& pm.getBasicStatus() != null
|
||||||
|
&& pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,14 +456,22 @@ public class LinphoneContact extends AndroidContact
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPresenceModelForUriOrTelCapability(String uri, FriendCapability capability) {
|
public boolean hasPresenceModelForUriOrTelCapability(String uri, FriendCapability capability) {
|
||||||
if (mFriend == null) return false;
|
if (mFriend == null || uri == null) return false;
|
||||||
if (mFriend.getPresenceModelForUriOrTel(uri) != null) {
|
|
||||||
return mFriend.getPresenceModelForUriOrTel(uri).hasCapability(capability);
|
PresenceModel presence = mFriend.getPresenceModelForUriOrTel(uri);
|
||||||
|
if (presence != null) {
|
||||||
|
return presence.hasCapability(capability);
|
||||||
} else {
|
} else {
|
||||||
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
||||||
if (getContactFromPresenceModelForUriOrTel(noa.getValue()).equals(uri)) {
|
String value = noa.getValue();
|
||||||
return mFriend.getPresenceModelForUriOrTel(noa.getValue())
|
if (value != null) {
|
||||||
.hasCapability(capability);
|
String contact = getContactFromPresenceModelForUriOrTel(value);
|
||||||
|
if (contact != null && contact.equals(uri)) {
|
||||||
|
presence = mFriend.getPresenceModelForUriOrTel(value);
|
||||||
|
if (presence != null) {
|
||||||
|
return presence.hasCapability(capability);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,12 +562,18 @@ public class LinphoneContact extends AndroidContact
|
||||||
String data3 = c.getString(c.getColumnIndex("data3"));
|
String data3 = c.getString(c.getColumnIndex("data3"));
|
||||||
String data4 = c.getString(c.getColumnIndex("data4"));
|
String data4 = c.getString(c.getColumnIndex("data4"));
|
||||||
|
|
||||||
if (getFullName() == null) {
|
String fullName = getFullName();
|
||||||
|
if (fullName == null || !fullName.equals(displayName)) {
|
||||||
Log.d("[Linphone Contact] Setting display name " + displayName);
|
Log.d("[Linphone Contact] Setting display name " + displayName);
|
||||||
setFullName(displayName);
|
setFullName(displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) {
|
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) {
|
||||||
|
if (data1 == null && data4 == null) {
|
||||||
|
Log.e("[Linphone Contact] Phone number data are both null !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("[Linphone Contact] Found phone number " + data1 + " (" + data4 + ")");
|
Log.d("[Linphone Contact] Found phone number " + data1 + " (" + data4 + ")");
|
||||||
addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
|
addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
|
||||||
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime)
|
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime)
|
||||||
|
@ -560,12 +581,27 @@ public class LinphoneContact extends AndroidContact
|
||||||
.getApplicationContext()
|
.getApplicationContext()
|
||||||
.getString(R.string.linphone_address_mime_type)
|
.getString(R.string.linphone_address_mime_type)
|
||||||
.equals(mime)) {
|
.equals(mime)) {
|
||||||
|
if (data1 == null) {
|
||||||
|
Log.e("[Linphone Contact] SIP address is null !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("[Linphone Contact] Found SIP address " + data1);
|
Log.d("[Linphone Contact] Found SIP address " + data1);
|
||||||
addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
|
addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
|
||||||
} else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mime)) {
|
} else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mime)) {
|
||||||
|
if (data1 == null) {
|
||||||
|
Log.e("[Linphone Contact] Organization is null !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("[Linphone Contact] Found organization " + data1);
|
Log.d("[Linphone Contact] Found organization " + data1);
|
||||||
setOrganization(data1, false);
|
setOrganization(data1, false);
|
||||||
} else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(mime)) {
|
} else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(mime)) {
|
||||||
|
if (data2 == null && data3 == null) {
|
||||||
|
Log.e("[Linphone Contact] Firstname and lastname are both null !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("[Linphone Contact] Found first name " + data2 + " and last name " + data3);
|
Log.d("[Linphone Contact] Found first name " + data2 + " and last name " + data3);
|
||||||
setFirstNameAndLastName(data2, data3, false);
|
setFirstNameAndLastName(data2, data3, false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -592,7 +628,9 @@ public class LinphoneContact extends AndroidContact
|
||||||
// Test presence of the value
|
// Test presence of the value
|
||||||
PresenceModel pm = getFriend().getPresenceModelForUriOrTel(value);
|
PresenceModel pm = getFriend().getPresenceModelForUriOrTel(value);
|
||||||
// If presence is not null
|
// If presence is not null
|
||||||
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
|
if (pm != null
|
||||||
|
&& pm.getBasicStatus() != null
|
||||||
|
&& pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
|
||||||
Log.d("[Contact] Found presence information for phone number " + value);
|
Log.d("[Contact] Found presence information for phone number " + value);
|
||||||
if (!isLinphoneAddressMimeEntryAlreadyExisting(value)) {
|
if (!isLinphoneAddressMimeEntryAlreadyExisting(value)) {
|
||||||
// Do the action on the contact only once if it has not been done yet
|
// Do the action on the contact only once if it has not been done yet
|
||||||
|
@ -605,12 +643,19 @@ public class LinphoneContact extends AndroidContact
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
saveChangesCommited();
|
saveChangesCommited();
|
||||||
|
if (getAndroidId() != null) {
|
||||||
|
setThumbnailUri(getContactThumbnailPictureUri());
|
||||||
|
setPhotoUri(getContactPictureUri());
|
||||||
|
}
|
||||||
syncValuesFromAndroidContact(LinphoneContext.instance().getApplicationContext());
|
syncValuesFromAndroidContact(LinphoneContext.instance().getApplicationContext());
|
||||||
createOrUpdateFriend();
|
createOrUpdateFriend();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
Log.i("[Contact] Deleting contact ", this);
|
||||||
|
if (isAndroidContact()) {
|
||||||
deleteAndroidContact();
|
deleteAndroidContact();
|
||||||
|
}
|
||||||
if (isFriend()) {
|
if (isFriend()) {
|
||||||
deleteFriend();
|
deleteFriend();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,11 @@ public class SearchContactViewHolder extends RecyclerView.ViewHolder
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (mListener != null) {
|
if (mListener != null) {
|
||||||
|
if (disabled.getVisibility() == View.GONE) {
|
||||||
mListener.onItemClicked(getAdapterPosition());
|
mListener.onItemClicked(getAdapterPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface ClickListener {
|
public interface ClickListener {
|
||||||
void onItemClicked(int position);
|
void onItemClicked(int position);
|
||||||
|
|
|
@ -30,13 +30,14 @@ import java.util.Objects;
|
||||||
import org.linphone.LinphoneContext;
|
import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.FriendCapability;
|
import org.linphone.core.FriendCapability;
|
||||||
import org.linphone.core.PresenceBasicStatus;
|
import org.linphone.core.PresenceBasicStatus;
|
||||||
import org.linphone.core.PresenceModel;
|
import org.linphone.core.PresenceModel;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.SearchResult;
|
import org.linphone.core.SearchResult;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactViewHolder> {
|
public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactViewHolder> {
|
||||||
private List<SearchResult> mContacts;
|
private List<SearchResult> mContacts;
|
||||||
|
@ -118,8 +119,20 @@ public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactVie
|
||||||
holder.name.setText(searchResult.getAddress().getDisplayName());
|
holder.name.setText(searchResult.getAddress().getDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.disabled.setVisibility(View.GONE);
|
holder.disabled.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if (mSecurityEnabled || !mIsOnlyOnePersonSelection) {
|
||||||
|
Core core = LinphoneManager.getCore();
|
||||||
|
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
|
||||||
|
if (defaultProxyConfig != null) {
|
||||||
|
// SDK won't accept ourselves in the list of participants
|
||||||
|
if (defaultProxyConfig.getIdentityAddress().weakEqual(searchResult.getAddress())) {
|
||||||
|
// Disable row, we can't use our own address in a group chat room
|
||||||
|
holder.disabled.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (contact != null) {
|
if (contact != null) {
|
||||||
if (contact.getFullName() == null
|
if (contact.getFullName() == null
|
||||||
&& contact.getFirstName() == null
|
&& contact.getFirstName() == null
|
||||||
|
@ -137,15 +150,6 @@ public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactVie
|
||||||
&& !searchResult.hasCapability(FriendCapability.LimeX3Dh))) {
|
&& !searchResult.hasCapability(FriendCapability.LimeX3Dh))) {
|
||||||
// Disable row, contact doesn't have the required capabilities
|
// Disable row, contact doesn't have the required capabilities
|
||||||
holder.disabled.setVisibility(View.VISIBLE);
|
holder.disabled.setVisibility(View.VISIBLE);
|
||||||
} else if (mSecurityEnabled || !mIsOnlyOnePersonSelection) {
|
|
||||||
ProxyConfig lpc =
|
|
||||||
Objects.requireNonNull(LinphoneManager.getCore()).getDefaultProxyConfig();
|
|
||||||
if (lpc != null
|
|
||||||
&& searchResult.getAddress() != null
|
|
||||||
&& lpc.getIdentityAddress().weakEqual(searchResult.getAddress())) {
|
|
||||||
// Disable row, we can't use our own address in a group chat room
|
|
||||||
holder.disabled.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout);
|
ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout);
|
||||||
|
|
|
@ -17,49 +17,25 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.contacts.views;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
import org.linphone.core.ChatRoomSecurityLevel;
|
import org.linphone.core.ChatRoomSecurityLevel;
|
||||||
import org.linphone.utils.ImageUtils;
|
import org.linphone.utils.ImageUtils;
|
||||||
|
|
||||||
class ContactAvatarHolder {
|
|
||||||
public final ImageView contactPicture;
|
|
||||||
public final ImageView avatarBorder;
|
|
||||||
public final ImageView securityLevel;
|
|
||||||
public final TextView generatedAvatar;
|
|
||||||
public final ImageView generatedAvatarBackground;
|
|
||||||
|
|
||||||
public ContactAvatarHolder(View v) {
|
|
||||||
contactPicture = v.findViewById(R.id.contact_picture);
|
|
||||||
securityLevel = v.findViewById(R.id.security_level);
|
|
||||||
generatedAvatar = v.findViewById(R.id.generated_avatar);
|
|
||||||
generatedAvatarBackground = v.findViewById(R.id.generated_avatar_background);
|
|
||||||
avatarBorder = v.findViewById(R.id.border);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
contactPicture.setVisibility(View.VISIBLE);
|
|
||||||
generatedAvatar.setVisibility(View.VISIBLE);
|
|
||||||
generatedAvatarBackground.setVisibility(View.VISIBLE);
|
|
||||||
securityLevel.setVisibility(View.GONE);
|
|
||||||
avatarBorder.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ContactAvatar {
|
public class ContactAvatar {
|
||||||
|
|
||||||
private static String generateAvatar(String displayName) {
|
private static String generateAvatar(String displayName) {
|
||||||
String[] names = displayName.split(" ");
|
String[] names = displayName.split(" ");
|
||||||
StringBuilder generatedAvatarText = new StringBuilder();
|
StringBuilder generatedAvatarText = new StringBuilder();
|
||||||
|
int count = 0;
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
if (name != null && name.length() > 0) {
|
if (name != null && name.length() > 0 && count < 2) {
|
||||||
generatedAvatarText.append(name.charAt(0));
|
generatedAvatarText.append(name.charAt(0));
|
||||||
|
count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return generatedAvatarText.toString().toUpperCase();
|
return generatedAvatarText.toString().toUpperCase();
|
||||||
|
@ -161,10 +137,7 @@ public class ContactAvatar {
|
||||||
|
|
||||||
Bitmap bm = ImageUtils.getRoundBitmapFromUri(v.getContext(), contact.getThumbnailUri());
|
Bitmap bm = ImageUtils.getRoundBitmapFromUri(v.getContext(), contact.getThumbnailUri());
|
||||||
if (bm != null) {
|
if (bm != null) {
|
||||||
holder.contactPicture.setImageBitmap(bm);
|
displayAvatar(bm, holder);
|
||||||
holder.contactPicture.setVisibility(View.VISIBLE);
|
|
||||||
holder.generatedAvatar.setVisibility(View.GONE);
|
|
||||||
holder.generatedAvatarBackground.setVisibility(View.GONE);
|
|
||||||
} else if (generated_avatars) {
|
} else if (generated_avatars) {
|
||||||
holder.generatedAvatar.setVisibility(View.VISIBLE);
|
holder.generatedAvatar.setVisibility(View.VISIBLE);
|
||||||
holder.generatedAvatarBackground.setVisibility(View.VISIBLE);
|
holder.generatedAvatarBackground.setVisibility(View.VISIBLE);
|
||||||
|
@ -175,6 +148,27 @@ public class ContactAvatar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void displayAvatar(Bitmap bm, ContactAvatarHolder holder) {
|
||||||
|
holder.contactPicture.setImageBitmap(bm);
|
||||||
|
holder.contactPicture.setVisibility(View.VISIBLE);
|
||||||
|
holder.generatedAvatar.setVisibility(View.GONE);
|
||||||
|
holder.generatedAvatarBackground.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void displayAvatar(Bitmap bm, View v) {
|
||||||
|
if (bm == null || v == null) return;
|
||||||
|
|
||||||
|
ContactAvatarHolder holder = new ContactAvatarHolder(v);
|
||||||
|
holder.init();
|
||||||
|
|
||||||
|
holder.generatedAvatar.setVisibility(View.GONE);
|
||||||
|
holder.generatedAvatarBackground.setVisibility(View.GONE);
|
||||||
|
holder.contactPicture.setVisibility(View.VISIBLE);
|
||||||
|
holder.securityLevel.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
displayAvatar(bm, holder);
|
||||||
|
}
|
||||||
|
|
||||||
public static void displayAvatar(LinphoneContact contact, View v) {
|
public static void displayAvatar(LinphoneContact contact, View v) {
|
||||||
displayAvatar(contact, v, false);
|
displayAvatar(contact, v, false);
|
||||||
}
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2019 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.contacts.views;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.linphone.R;
|
||||||
|
|
||||||
|
class ContactAvatarHolder {
|
||||||
|
public final ImageView contactPicture;
|
||||||
|
public final ImageView avatarBorder;
|
||||||
|
public final ImageView securityLevel;
|
||||||
|
public final TextView generatedAvatar;
|
||||||
|
public final ImageView generatedAvatarBackground;
|
||||||
|
|
||||||
|
public ContactAvatarHolder(View v) {
|
||||||
|
contactPicture = v.findViewById(R.id.contact_picture);
|
||||||
|
securityLevel = v.findViewById(R.id.security_level);
|
||||||
|
generatedAvatar = v.findViewById(R.id.generated_avatar);
|
||||||
|
generatedAvatarBackground = v.findViewById(R.id.generated_avatar_background);
|
||||||
|
avatarBorder = v.findViewById(R.id.border);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
contactPicture.setVisibility(View.VISIBLE);
|
||||||
|
generatedAvatar.setVisibility(View.VISIBLE);
|
||||||
|
generatedAvatarBackground.setVisibility(View.VISIBLE);
|
||||||
|
securityLevel.setVisibility(View.GONE);
|
||||||
|
avatarBorder.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.contacts.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities;
|
package org.linphone.dialer;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -37,17 +37,18 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.activities.MainActivity;
|
||||||
|
import org.linphone.call.views.CallButton;
|
||||||
import org.linphone.contacts.ContactsActivity;
|
import org.linphone.contacts.ContactsActivity;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.dialer.views.AddressText;
|
||||||
|
import org.linphone.dialer.views.Digit;
|
||||||
|
import org.linphone.dialer.views.EraseButton;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.views.AddressText;
|
|
||||||
import org.linphone.views.CallButton;
|
|
||||||
import org.linphone.views.Digit;
|
|
||||||
import org.linphone.views.EraseButton;
|
|
||||||
|
|
||||||
public class DialerActivity extends MainActivity implements AddressText.AddressChangedListener {
|
public class DialerActivity extends MainActivity implements AddressText.AddressChangedListener {
|
||||||
private static final String ACTION_CALL_LINPHONE = "org.linphone.intent.action.CallLaunched";
|
private static final String ACTION_CALL_LINPHONE = "org.linphone.intent.action.CallLaunched";
|
||||||
|
@ -220,14 +221,15 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
||||||
private void enableVideoPreviewIfTablet(boolean enable) {
|
private void enableVideoPreviewIfTablet(boolean enable) {
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
TextureView preview = findViewById(R.id.video_preview);
|
TextureView preview = findViewById(R.id.video_preview);
|
||||||
if (preview != null && core != null) {
|
ImageView changeCamera = findViewById(R.id.video_preview_change_camera);
|
||||||
|
|
||||||
|
if (preview != null && changeCamera != null && core != null) {
|
||||||
if (enable && isTablet() && LinphonePreferences.instance().isVideoPreviewEnabled()) {
|
if (enable && isTablet() && LinphonePreferences.instance().isVideoPreviewEnabled()) {
|
||||||
preview.setVisibility(View.VISIBLE);
|
preview.setVisibility(View.VISIBLE);
|
||||||
core.setNativePreviewWindowId(preview);
|
core.setNativePreviewWindowId(preview);
|
||||||
core.enableVideoPreview(true);
|
core.enableVideoPreview(true);
|
||||||
|
|
||||||
ImageView changeCamera = findViewById(R.id.video_preview_change_camera);
|
if (core.getVideoDevicesList().length > 1) {
|
||||||
if (changeCamera != null && core.getVideoDevicesList().length > 1) {
|
|
||||||
changeCamera.setVisibility(View.VISIBLE);
|
changeCamera.setVisibility(View.VISIBLE);
|
||||||
changeCamera.setOnClickListener(
|
changeCamera.setOnClickListener(
|
||||||
new View.OnClickListener() {
|
new View.OnClickListener() {
|
||||||
|
@ -239,6 +241,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
preview.setVisibility(View.GONE);
|
preview.setVisibility(View.GONE);
|
||||||
|
changeCamera.setVisibility(View.GONE);
|
||||||
core.setNativePreviewWindowId(null);
|
core.setNativePreviewWindowId(null);
|
||||||
core.enableVideoPreview(false);
|
core.enableVideoPreview(false);
|
||||||
}
|
}
|
||||||
|
@ -259,9 +262,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAddressChanged() {
|
public void onAddressChanged() {
|
||||||
Core core = LinphoneManager.getCore();
|
mAddContact.setEnabled(!mAddress.getText().toString().isEmpty());
|
||||||
mAddContact.setEnabled(
|
|
||||||
core != null && core.getCallsNb() > 0 || !mAddress.getText().toString().equals(""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLayout() {
|
private void updateLayout() {
|
||||||
|
@ -273,6 +274,8 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
||||||
boolean atLeastOneCall = core.getCallsNb() > 0;
|
boolean atLeastOneCall = core.getCallsNb() > 0;
|
||||||
mStartCall.setVisibility(atLeastOneCall ? View.GONE : View.VISIBLE);
|
mStartCall.setVisibility(atLeastOneCall ? View.GONE : View.VISIBLE);
|
||||||
mAddContact.setVisibility(atLeastOneCall ? View.GONE : View.VISIBLE);
|
mAddContact.setVisibility(atLeastOneCall ? View.GONE : View.VISIBLE);
|
||||||
|
mAddContact.setEnabled(!mAddress.getText().toString().isEmpty());
|
||||||
|
|
||||||
if (!atLeastOneCall) {
|
if (!atLeastOneCall) {
|
||||||
if (core.getVideoActivationPolicy().getAutomaticallyInitiate()) {
|
if (core.getVideoActivationPolicy().getAutomaticallyInitiate()) {
|
||||||
mStartCall.setImageResource(R.drawable.call_video_start);
|
mStartCall.setImageResource(R.drawable.call_video_start);
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.dialer.views;
|
||||||
|
|
||||||
public interface AddressAware {
|
public interface AddressAware {
|
||||||
void setAddressWidget(AddressText address);
|
void setAddressWidget(AddressText address);
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.dialer.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.dialer.views;
|
||||||
|
|
||||||
public interface AddressType {
|
public interface AddressType {
|
||||||
CharSequence getText();
|
CharSequence getText();
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.dialer.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.views;
|
package org.linphone.dialer.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
|
@ -37,7 +37,7 @@ public class FirebaseMessaging extends FirebaseMessagingService {
|
||||||
android.util.Log.i(
|
android.util.Log.i(
|
||||||
"FirebaseMessaging", "[Push Notification] Starting context");
|
"FirebaseMessaging", "[Push Notification] Starting context");
|
||||||
new LinphoneContext(getApplicationContext());
|
new LinphoneContext(getApplicationContext());
|
||||||
LinphoneContext.instance().start(false);
|
LinphoneContext.instance().start(true);
|
||||||
} else {
|
} else {
|
||||||
Log.i("[Push Notification] Notifying Core");
|
Log.i("[Push Notification] Notifying Core");
|
||||||
if (LinphoneManager.getInstance() != null) {
|
if (LinphoneManager.getInstance() != null) {
|
||||||
|
|
|
@ -79,10 +79,8 @@ public class StatusBarFragment extends Fragment {
|
||||||
final RegistrationState state,
|
final RegistrationState state,
|
||||||
String smessage) {
|
String smessage) {
|
||||||
if (core.getProxyConfigList() == null) {
|
if (core.getProxyConfigList() == null) {
|
||||||
mStatusLed.setImageResource(R.drawable.led_disconnected);
|
showNoAccountConfigured();
|
||||||
mStatusText.setText(getString(R.string.no_account));
|
return;
|
||||||
} else {
|
|
||||||
mStatusLed.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((core.getDefaultProxyConfig() != null
|
if ((core.getDefaultProxyConfig() != null
|
||||||
|
@ -152,6 +150,8 @@ public class StatusBarFragment extends Fragment {
|
||||||
ProxyConfig lpc = core.getDefaultProxyConfig();
|
ProxyConfig lpc = core.getDefaultProxyConfig();
|
||||||
if (lpc != null) {
|
if (lpc != null) {
|
||||||
mListener.onRegistrationStateChanged(core, lpc, lpc.getState(), null);
|
mListener.onRegistrationStateChanged(core, lpc, lpc.getState(), null);
|
||||||
|
} else {
|
||||||
|
showNoAccountConfigured();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mStatusText.setVisibility(View.VISIBLE);
|
mStatusText.setVisibility(View.VISIBLE);
|
||||||
|
@ -178,11 +178,15 @@ public class StatusBarFragment extends Fragment {
|
||||||
mVoicemailCount.setVisibility(View.VISIBLE);
|
mVoicemailCount.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if (core.getProxyConfigList().length == 0) {
|
if (core.getProxyConfigList().length == 0) {
|
||||||
|
showNoAccountConfigured();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNoAccountConfigured() {
|
||||||
mStatusLed.setImageResource(R.drawable.led_disconnected);
|
mStatusLed.setImageResource(R.drawable.led_disconnected);
|
||||||
mStatusText.setText(getString(R.string.no_account));
|
mStatusText.setText(getString(R.string.no_account));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getStatusIconResource(RegistrationState state) {
|
private int getStatusIconResource(RegistrationState state) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.app.Fragment;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.MainActivity;
|
import org.linphone.activities.MainActivity;
|
||||||
|
@ -71,6 +72,7 @@ public class HistoryActivity extends MainActivity {
|
||||||
mHistorySelected.setVisibility(View.VISIBLE);
|
mHistorySelected.setVisibility(View.VISIBLE);
|
||||||
LinphoneManager.getCore().resetMissedCallsCount();
|
LinphoneManager.getCore().resetMissedCallsCount();
|
||||||
displayMissedCalls();
|
displayMissedCalls();
|
||||||
|
LinphoneContext.instance().getNotificationManager().dismissMissedCallNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,13 +30,13 @@ import java.util.List;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.CallLog;
|
import org.linphone.core.CallLog;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.utils.SelectableAdapter;
|
import org.linphone.utils.SelectableAdapter;
|
||||||
import org.linphone.utils.SelectableHelper;
|
import org.linphone.utils.SelectableHelper;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
|
public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
|
||||||
private final List<CallLog> mLogs;
|
private final List<CallLog> mLogs;
|
||||||
|
|
|
@ -35,20 +35,22 @@ import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.LinphoneContact;
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.contacts.views.ContactAvatar;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.CallLog;
|
import org.linphone.core.CallLog;
|
||||||
import org.linphone.core.ChatRoom;
|
import org.linphone.core.ChatRoom;
|
||||||
import org.linphone.core.ChatRoomBackend;
|
import org.linphone.core.ChatRoomBackend;
|
||||||
import org.linphone.core.ChatRoomListenerStub;
|
import org.linphone.core.ChatRoomListenerStub;
|
||||||
import org.linphone.core.ChatRoomParams;
|
import org.linphone.core.ChatRoomParams;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.Factory;
|
import org.linphone.core.Factory;
|
||||||
import org.linphone.core.FriendCapability;
|
import org.linphone.core.FriendCapability;
|
||||||
import org.linphone.core.ProxyConfig;
|
import org.linphone.core.ProxyConfig;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
import org.linphone.views.ContactAvatar;
|
|
||||||
|
|
||||||
public class HistoryDetailFragment extends Fragment {
|
public class HistoryDetailFragment extends Fragment {
|
||||||
private ImageView mAddToContacts;
|
private ImageView mAddToContacts;
|
||||||
|
@ -60,6 +62,7 @@ public class HistoryDetailFragment extends Fragment {
|
||||||
private ChatRoom mChatRoom;
|
private ChatRoom mChatRoom;
|
||||||
private ChatRoomListenerStub mChatRoomCreationListener;
|
private ChatRoomListenerStub mChatRoomCreationListener;
|
||||||
private ListView mLogsList;
|
private ListView mLogsList;
|
||||||
|
private CoreListenerStub mListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(
|
public View onCreateView(
|
||||||
|
@ -157,7 +160,7 @@ public class HistoryDetailFragment extends Fragment {
|
||||||
mWaitLayout.setVisibility(View.GONE);
|
mWaitLayout.setVisibility(View.GONE);
|
||||||
((HistoryActivity) getActivity()).displayChatRoomError();
|
((HistoryActivity) getActivity()).displayChatRoomError();
|
||||||
Log.e(
|
Log.e(
|
||||||
"Group mChat room for address "
|
"[History Detail Fragment] Group mChat room for address "
|
||||||
+ cr.getPeerAddress()
|
+ cr.getPeerAddress()
|
||||||
+ " has failed !");
|
+ " has failed !");
|
||||||
}
|
}
|
||||||
|
@ -165,16 +168,36 @@ public class HistoryDetailFragment extends Fragment {
|
||||||
};
|
};
|
||||||
|
|
||||||
mLogsList = view.findViewById(R.id.logs_list);
|
mLogsList = view.findViewById(R.id.logs_list);
|
||||||
|
|
||||||
|
mListener =
|
||||||
|
new CoreListenerStub() {
|
||||||
|
@Override
|
||||||
|
public void onCallStateChanged(
|
||||||
|
Core core, Call call, Call.State state, String message) {
|
||||||
|
if (state == Call.State.End || state == Call.State.Error) {
|
||||||
displayHistory();
|
displayHistory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
LinphoneManager.getCore().addListener(mListener);
|
||||||
|
displayHistory();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
if (mChatRoom != null) {
|
if (mChatRoom != null) {
|
||||||
mChatRoom.removeListener(mChatRoomCreationListener);
|
mChatRoom.removeListener(mChatRoomCreationListener);
|
||||||
}
|
}
|
||||||
|
LinphoneManager.getCore().removeListener(mListener);
|
||||||
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,24 +257,29 @@ public class HistoryDetailFragment extends Fragment {
|
||||||
|
|
||||||
private void goToChat(boolean isSecured) {
|
private void goToChat(boolean isSecured) {
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
|
if (core == null) return;
|
||||||
|
|
||||||
Address participant = Factory.instance().createAddress(mSipUri);
|
Address participant = Factory.instance().createAddress(mSipUri);
|
||||||
|
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
|
||||||
|
|
||||||
|
if (defaultProxyConfig != null) {
|
||||||
ChatRoom room =
|
ChatRoom room =
|
||||||
core.findOneToOneChatRoom(
|
core.findOneToOneChatRoom(
|
||||||
core.getDefaultProxyConfig().getContact(), participant, isSecured);
|
defaultProxyConfig.getContact(), participant, isSecured);
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
((HistoryActivity) getActivity())
|
((HistoryActivity) getActivity())
|
||||||
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
|
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
|
||||||
} else {
|
} else {
|
||||||
ProxyConfig lpc = core.getDefaultProxyConfig();
|
if (defaultProxyConfig.getConferenceFactoryUri() != null
|
||||||
if (lpc != null
|
&& (isSecured
|
||||||
&& lpc.getConferenceFactoryUri() != null
|
|| !LinphonePreferences.instance().useBasicChatRoomFor1To1())) {
|
||||||
&& (isSecured || !LinphonePreferences.instance().useBasicChatRoomFor1To1())) {
|
|
||||||
mWaitLayout.setVisibility(View.VISIBLE);
|
mWaitLayout.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
ChatRoomParams params = core.createDefaultChatRoomParams();
|
ChatRoomParams params = core.createDefaultChatRoomParams();
|
||||||
params.enableEncryption(isSecured);
|
params.enableEncryption(isSecured);
|
||||||
params.enableGroup(false);
|
params.enableGroup(false);
|
||||||
// We don't want a basic chat room
|
// We don't want a basic chat room,
|
||||||
|
// so if isSecured is false we have to set this manually
|
||||||
params.setBackend(ChatRoomBackend.FlexisipChat);
|
params.setBackend(ChatRoomBackend.FlexisipChat);
|
||||||
|
|
||||||
Address[] participants = new Address[1];
|
Address[] participants = new Address[1];
|
||||||
|
@ -259,7 +287,9 @@ public class HistoryDetailFragment extends Fragment {
|
||||||
|
|
||||||
mChatRoom =
|
mChatRoom =
|
||||||
core.createChatRoom(
|
core.createChatRoom(
|
||||||
params, getString(R.string.dummy_group_chat_subject), participants);
|
params,
|
||||||
|
getString(R.string.dummy_group_chat_subject),
|
||||||
|
participants);
|
||||||
if (mChatRoom != null) {
|
if (mChatRoom != null) {
|
||||||
mChatRoom.addListener(mChatRoomCreationListener);
|
mChatRoom.addListener(mChatRoomCreationListener);
|
||||||
} else {
|
} else {
|
||||||
|
@ -274,5 +304,18 @@ public class HistoryDetailFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (isSecured) {
|
||||||
|
Log.e(
|
||||||
|
"[History Detail Fragment] Can't create a secured chat room without proxy config");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatRoom room = core.getChatRoom(participant);
|
||||||
|
if (room != null) {
|
||||||
|
((HistoryActivity) getActivity())
|
||||||
|
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,23 +35,26 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.linphone.LinphoneContext;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
|
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||||
import org.linphone.contacts.ContactsManager;
|
import org.linphone.contacts.ContactsManager;
|
||||||
import org.linphone.contacts.ContactsUpdatedListener;
|
import org.linphone.contacts.ContactsUpdatedListener;
|
||||||
import org.linphone.core.Address;
|
import org.linphone.core.Address;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.CallLog;
|
import org.linphone.core.CallLog;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.utils.SelectableHelper;
|
import org.linphone.utils.SelectableHelper;
|
||||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
|
||||||
|
|
||||||
public class HistoryFragment extends Fragment
|
public class HistoryFragment extends Fragment
|
||||||
implements OnClickListener,
|
implements OnClickListener,
|
||||||
OnItemClickListener,
|
OnItemClickListener,
|
||||||
HistoryViewHolder.ClickListener,
|
HistoryViewHolder.ClickListener,
|
||||||
ContactsUpdatedListener,
|
ContactsUpdatedListener,
|
||||||
SelectableHelper.DeleteListener {
|
SelectableHelper.DeleteListener,
|
||||||
|
LinphoneContext.CoreStartedListener {
|
||||||
private RecyclerView mHistoryList;
|
private RecyclerView mHistoryList;
|
||||||
private TextView mNoCallHistory, mNoMissedCallHistory;
|
private TextView mNoCallHistory, mNoMissedCallHistory;
|
||||||
private ImageView mMissedCalls, mAllCalls;
|
private ImageView mMissedCalls, mAllCalls;
|
||||||
|
@ -60,6 +63,7 @@ public class HistoryFragment extends Fragment
|
||||||
private List<CallLog> mLogs;
|
private List<CallLog> mLogs;
|
||||||
private HistoryAdapter mHistoryAdapter;
|
private HistoryAdapter mHistoryAdapter;
|
||||||
private SelectableHelper mSelectionHelper;
|
private SelectableHelper mSelectionHelper;
|
||||||
|
private CoreListenerStub mListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(
|
public View onCreateView(
|
||||||
|
@ -94,26 +98,37 @@ public class HistoryFragment extends Fragment
|
||||||
mAllCalls.setEnabled(false);
|
mAllCalls.setEnabled(false);
|
||||||
mOnlyDisplayMissedCalls = false;
|
mOnlyDisplayMissedCalls = false;
|
||||||
|
|
||||||
|
mListener =
|
||||||
|
new CoreListenerStub() {
|
||||||
|
@Override
|
||||||
|
public void onCallStateChanged(
|
||||||
|
Core core, Call call, Call.State state, String message) {
|
||||||
|
if (state == Call.State.End || state == Call.State.Error) {
|
||||||
|
reloadData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
ContactsManager.getInstance().addContactsListener(this);
|
|
||||||
|
|
||||||
mLogs = Arrays.asList(LinphoneManager.getCore().getCallLogs());
|
ContactsManager.getInstance().addContactsListener(this);
|
||||||
hideHistoryListAndDisplayMessageIfEmpty();
|
LinphoneContext.instance().addCoreStartedListener(this);
|
||||||
mHistoryAdapter =
|
LinphoneManager.getCore().addListener(mListener);
|
||||||
new HistoryAdapter((HistoryActivity) getActivity(), mLogs, this, mSelectionHelper);
|
|
||||||
mHistoryList.setAdapter(mHistoryAdapter);
|
reloadData();
|
||||||
mSelectionHelper.setAdapter(mHistoryAdapter);
|
|
||||||
mSelectionHelper.setDialogMessage(R.string.call_log_delete_dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
ContactsManager.getInstance().removeContactsListener(this);
|
ContactsManager.getInstance().removeContactsListener(this);
|
||||||
|
LinphoneContext.instance().removeCoreStartedListener(this);
|
||||||
|
LinphoneManager.getCore().removeListener(mListener);
|
||||||
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +140,11 @@ public class HistoryFragment extends Fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCoreStarted() {
|
||||||
|
reloadData();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
int id = v.getId();
|
int id = v.getId();
|
||||||
|
@ -177,6 +197,7 @@ public class HistoryFragment extends Fragment
|
||||||
if (mHistoryAdapter.isEditionEnabled()) {
|
if (mHistoryAdapter.isEditionEnabled()) {
|
||||||
mHistoryAdapter.toggleSelection(position);
|
mHistoryAdapter.toggleSelection(position);
|
||||||
} else {
|
} else {
|
||||||
|
if (position >= 0 && position < mLogs.size()) {
|
||||||
CallLog log = mLogs.get(position);
|
CallLog log = mLogs.get(position);
|
||||||
Address address;
|
Address address;
|
||||||
if (log.getDir() == Call.Dir.Incoming) {
|
if (log.getDir() == Call.Dir.Incoming) {
|
||||||
|
@ -185,7 +206,9 @@ public class HistoryFragment extends Fragment
|
||||||
address = log.getToAddress();
|
address = log.getToAddress();
|
||||||
}
|
}
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
LinphoneManager.getCallManager().newOutgoingCall(address.asStringUriOnly(), null);
|
LinphoneManager.getCallManager()
|
||||||
|
.newOutgoingCall(address.asStringUriOnly(), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,6 +241,16 @@ public class HistoryFragment extends Fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reloadData() {
|
||||||
|
mLogs = Arrays.asList(LinphoneManager.getCore().getCallLogs());
|
||||||
|
hideHistoryListAndDisplayMessageIfEmpty();
|
||||||
|
mHistoryAdapter =
|
||||||
|
new HistoryAdapter((HistoryActivity) getActivity(), mLogs, this, mSelectionHelper);
|
||||||
|
mHistoryList.setAdapter(mHistoryAdapter);
|
||||||
|
mSelectionHelper.setAdapter(mHistoryAdapter);
|
||||||
|
mSelectionHelper.setDialogMessage(R.string.call_log_delete_dialog);
|
||||||
|
}
|
||||||
|
|
||||||
private void removeNotMissedCallsFromLogs() {
|
private void removeNotMissedCallsFromLogs() {
|
||||||
if (mOnlyDisplayMissedCalls) {
|
if (mOnlyDisplayMissedCalls) {
|
||||||
List<CallLog> missedCalls = new ArrayList<>();
|
List<CallLog> missedCalls = new ArrayList<>();
|
||||||
|
|
|
@ -29,12 +29,11 @@ import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.DialerActivity;
|
|
||||||
import org.linphone.call.CallActivity;
|
import org.linphone.call.CallActivity;
|
||||||
import org.linphone.call.CallIncomingActivity;
|
import org.linphone.call.CallIncomingActivity;
|
||||||
import org.linphone.call.CallOutgoingActivity;
|
import org.linphone.call.CallOutgoingActivity;
|
||||||
|
@ -53,7 +52,9 @@ import org.linphone.core.Core;
|
||||||
import org.linphone.core.CoreListenerStub;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.Reason;
|
import org.linphone.core.Reason;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.dialer.DialerActivity;
|
||||||
import org.linphone.history.HistoryActivity;
|
import org.linphone.history.HistoryActivity;
|
||||||
|
import org.linphone.service.LinphoneService;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.DeviceUtils;
|
import org.linphone.utils.DeviceUtils;
|
||||||
import org.linphone.utils.FileUtils;
|
import org.linphone.utils.FileUtils;
|
||||||
|
@ -84,7 +85,19 @@ public class NotificationsManager {
|
||||||
mCurrentChatRoomAddress = null;
|
mCurrentChatRoomAddress = null;
|
||||||
|
|
||||||
mNM = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
|
mNM = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
if (mContext.getResources().getBoolean(R.bool.keep_missed_call_notification_upon_restart)) {
|
||||||
|
StatusBarNotification[] notifs = Compatibility.getActiveNotifications(mNM);
|
||||||
|
if (notifs != null && notifs.length > 1) {
|
||||||
|
for (StatusBarNotification notif : notifs) {
|
||||||
|
if (notif.getId() != MISSED_CALLS_NOTIF_ID) {
|
||||||
|
dismissNotification(notif.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mNM.cancelAll();
|
mNM.cancelAll();
|
||||||
|
}
|
||||||
|
|
||||||
mLastNotificationId = 5; // Do not conflict with hardcoded notifications ids !
|
mLastNotificationId = 5; // Do not conflict with hardcoded notifications ids !
|
||||||
|
|
||||||
|
@ -327,6 +340,10 @@ public class NotificationsManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dismissMissedCallNotification() {
|
||||||
|
dismissNotification(MISSED_CALLS_NOTIF_ID);
|
||||||
|
}
|
||||||
|
|
||||||
public void sendNotification(int id, Notification notif) {
|
public void sendNotification(int id, Notification notif) {
|
||||||
Log.i("[Notifications Manager] Notifying " + id);
|
Log.i("[Notifications Manager] Notifying " + id);
|
||||||
mNM.notify(id, notif);
|
mNM.notify(id, notif);
|
||||||
|
@ -521,7 +538,8 @@ public class NotificationsManager {
|
||||||
mContext,
|
mContext,
|
||||||
mContext.getString(R.string.missed_calls_notif_title),
|
mContext.getString(R.string.missed_calls_notif_title),
|
||||||
body,
|
body,
|
||||||
pendingIntent);
|
pendingIntent,
|
||||||
|
missedCallCount);
|
||||||
sendNotification(MISSED_CALLS_NOTIF_ID, notif);
|
sendNotification(MISSED_CALLS_NOTIF_ID, notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.receivers;
|
package org.linphone.receivers;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothHeadset;
|
import android.bluetooth.BluetoothHeadset;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -28,10 +29,40 @@ import org.linphone.LinphoneManager;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
|
||||||
public class BluetoothReceiver extends BroadcastReceiver {
|
public class BluetoothReceiver extends BroadcastReceiver {
|
||||||
|
public BluetoothReceiver() {
|
||||||
|
super();
|
||||||
|
Log.i("[Bluetooth] Bluetooth receiver created");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
|
Log.i("[Bluetooth] Bluetooth broadcast received");
|
||||||
|
|
||||||
|
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
|
||||||
|
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
|
||||||
|
switch (state) {
|
||||||
|
case BluetoothAdapter.STATE_OFF:
|
||||||
|
Log.w("[Bluetooth] Adapter has been turned off");
|
||||||
|
break;
|
||||||
|
case BluetoothAdapter.STATE_TURNING_OFF:
|
||||||
|
Log.w("[Bluetooth] Adapter is being turned off");
|
||||||
|
break;
|
||||||
|
case BluetoothAdapter.STATE_ON:
|
||||||
|
Log.i("[Bluetooth] Adapter has been turned on");
|
||||||
|
LinphoneManager.getAudioManager().bluetoothAdapterStateChanged();
|
||||||
|
break;
|
||||||
|
case BluetoothAdapter.STATE_TURNING_ON:
|
||||||
|
Log.i("[Bluetooth] Adapter is being turned on");
|
||||||
|
break;
|
||||||
|
case BluetoothAdapter.ERROR:
|
||||||
|
Log.e("[Bluetooth] Adapter is in error state !");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.w("[Bluetooth] Unknown adapter state: ", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
|
||||||
int state =
|
int state =
|
||||||
intent.getIntExtra(
|
intent.getIntExtra(
|
||||||
BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
|
BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
|
||||||
|
@ -55,6 +86,8 @@ public class BluetoothReceiver extends BroadcastReceiver {
|
||||||
} else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
|
} else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
|
||||||
Log.i("[Bluetooth] Bluetooth headset audio disconnected");
|
Log.i("[Bluetooth] Bluetooth headset audio disconnected");
|
||||||
LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(false);
|
LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(false);
|
||||||
|
} else if (state == BluetoothHeadset.STATE_AUDIO_CONNECTING) {
|
||||||
|
Log.i("[Bluetooth] Bluetooth headset audio connecting");
|
||||||
} else {
|
} else {
|
||||||
Log.w("[Bluetooth] Bluetooth headset unknown audio state changed: " + state);
|
Log.w("[Bluetooth] Bluetooth headset unknown audio state changed: " + state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ package org.linphone.receivers;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.compatibility.Compatibility;
|
import org.linphone.compatibility.Compatibility;
|
||||||
|
import org.linphone.service.LinphoneService;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
|
|
||||||
public class BootReceiver extends BroadcastReceiver {
|
public class BootReceiver extends BroadcastReceiver {
|
||||||
|
@ -36,17 +36,34 @@ public class BootReceiver extends BroadcastReceiver {
|
||||||
"[Boot Receiver] Device is shutting down, destroying Core to unregister");
|
"[Boot Receiver] Device is shutting down, destroying Core to unregister");
|
||||||
context.stopService(
|
context.stopService(
|
||||||
new Intent(Intent.ACTION_MAIN).setClass(context, LinphoneService.class));
|
new Intent(Intent.ACTION_MAIN).setClass(context, LinphoneService.class));
|
||||||
} else {
|
} else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
|
||||||
LinphonePreferences.instance().setContext(context);
|
LinphonePreferences.instance().setContext(context);
|
||||||
boolean autostart = LinphonePreferences.instance().isAutoStartEnabled();
|
boolean autostart = LinphonePreferences.instance().isAutoStartEnabled();
|
||||||
android.util.Log.i(
|
android.util.Log.i(
|
||||||
"Linphone", "[Boot Receiver] Device is starting, auto_start is " + autostart);
|
"Linphone", "[Boot Receiver] Device is starting, auto_start is " + autostart);
|
||||||
|
|
||||||
if (autostart && !LinphoneService.isReady()) {
|
if (autostart && !LinphoneService.isReady()) {
|
||||||
|
startService(context);
|
||||||
|
}
|
||||||
|
} else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_MY_PACKAGE_REPLACED)) {
|
||||||
|
LinphonePreferences.instance().setContext(context);
|
||||||
|
boolean foregroundService =
|
||||||
|
LinphonePreferences.instance().getServiceNotificationVisibility();
|
||||||
|
android.util.Log.i(
|
||||||
|
"Linphone",
|
||||||
|
"[Boot Receiver] App has been updated, foreground service is "
|
||||||
|
+ foregroundService);
|
||||||
|
|
||||||
|
if (foregroundService && !LinphoneService.isReady()) {
|
||||||
|
startService(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startService(Context context) {
|
||||||
Intent serviceIntent = new Intent(Intent.ACTION_MAIN);
|
Intent serviceIntent = new Intent(Intent.ACTION_MAIN);
|
||||||
serviceIntent.setClass(context, LinphoneService.class);
|
serviceIntent.setClass(context, LinphoneService.class);
|
||||||
serviceIntent.putExtra("ForceStartForeground", true);
|
serviceIntent.putExtra("ForceStartForeground", true);
|
||||||
Compatibility.startService(context, serviceIntent);
|
Compatibility.startService(context, serviceIntent);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,15 @@ import org.linphone.core.tools.Log;
|
||||||
public class HeadsetReceiver extends BroadcastReceiver {
|
public class HeadsetReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (isInitialStickyBroadcast()) {
|
||||||
|
Log.i("[Headset] Received broadcast from sticky cache, ignoring...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
|
if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
|
||||||
// This happens when the user plugs a Jack headset to the device for example
|
// This happens when the user plugs a Jack headset to the device for example
|
||||||
|
// https://developer.android.com/reference/android/media/AudioManager.html#ACTION_HEADSET_PLUG
|
||||||
int state = intent.getIntExtra("state", 0);
|
int state = intent.getIntExtra("state", 0);
|
||||||
String name = intent.getStringExtra("name");
|
String name = intent.getStringExtra("name");
|
||||||
int hasMicrophone = intent.getIntExtra("microphone", 0);
|
int hasMicrophone = intent.getIntExtra("microphone", 0);
|
||||||
|
@ -44,7 +50,7 @@ public class HeadsetReceiver extends BroadcastReceiver {
|
||||||
Log.i("[Headset] Headset " + name + " has a microphone");
|
Log.i("[Headset] Headset " + name + " has a microphone");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w("[Headset] Unknow headset plugged state: " + state);
|
Log.w("[Headset] Unknown headset plugged state: " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneManager.getAudioManager().routeAudioToEarPiece();
|
LinphoneManager.getAudioManager().routeAudioToEarPiece();
|
||||||
|
@ -55,7 +61,7 @@ public class HeadsetReceiver extends BroadcastReceiver {
|
||||||
LinphoneManager.getAudioManager().routeAudioToEarPiece();
|
LinphoneManager.getAudioManager().routeAudioToEarPiece();
|
||||||
LinphoneManager.getCallManager().refreshInCallActions();
|
LinphoneManager.getCallManager().refreshInCallActions();
|
||||||
} else {
|
} else {
|
||||||
Log.w("[Headset] Unknow action: " + action);
|
Log.w("[Headset] Unknown action: " + action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,9 @@ import java.util.List;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.activities.MainActivity;
|
import org.linphone.activities.MainActivity;
|
||||||
|
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||||
import org.linphone.utils.FileUtils;
|
import org.linphone.utils.FileUtils;
|
||||||
import org.linphone.utils.SelectableHelper;
|
import org.linphone.utils.SelectableHelper;
|
||||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
|
||||||
|
|
||||||
public class RecordingsActivity extends MainActivity
|
public class RecordingsActivity extends MainActivity
|
||||||
implements SelectableHelper.DeleteListener, RecordingViewHolder.ClickListener {
|
implements SelectableHelper.DeleteListener, RecordingViewHolder.ClickListener {
|
||||||
|
|
|
@ -17,15 +17,15 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.utils;
|
package org.linphone.service;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.LinphoneService;
|
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
|
import org.linphone.utils.LinphoneUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Believe me or not, but knowing the application visibility state on Android is a nightmare. After
|
* Believe me or not, but knowing the application visibility state on Android is a nightmare. After
|
|
@ -17,22 +17,24 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone;
|
package org.linphone.service;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import org.linphone.LinphoneContext;
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.R;
|
||||||
|
import org.linphone.call.views.LinphoneGL2JNIViewOverlay;
|
||||||
|
import org.linphone.call.views.LinphoneOverlay;
|
||||||
|
import org.linphone.call.views.LinphoneTextureViewOverlay;
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.tools.Log;
|
import org.linphone.core.tools.Log;
|
||||||
import org.linphone.mediastream.Version;
|
import org.linphone.mediastream.Version;
|
||||||
import org.linphone.settings.LinphonePreferences;
|
import org.linphone.settings.LinphonePreferences;
|
||||||
import org.linphone.utils.ActivityMonitor;
|
|
||||||
import org.linphone.views.LinphoneGL2JNIViewOverlay;
|
|
||||||
import org.linphone.views.LinphoneOverlay;
|
|
||||||
import org.linphone.views.LinphoneTextureViewOverlay;
|
|
||||||
|
|
||||||
public final class LinphoneService extends Service {
|
public final class LinphoneService extends Service {
|
||||||
private static LinphoneService sInstance;
|
private static LinphoneService sInstance;
|
||||||
|
@ -75,8 +77,12 @@ public final class LinphoneService extends Service {
|
||||||
}
|
}
|
||||||
sInstance = this;
|
sInstance = this;
|
||||||
|
|
||||||
if (LinphonePreferences.instance().getServiceNotificationVisibility()) {
|
if (LinphonePreferences.instance().getServiceNotificationVisibility()
|
||||||
|
|| (Version.sdkAboveOrEqual(Version.API26_O_80)
|
||||||
|
&& intent != null
|
||||||
|
&& intent.getBooleanExtra("ForceStartForeground", false))) {
|
||||||
Log.i("[Service] Background service mode enabled, displaying notification");
|
Log.i("[Service] Background service mode enabled, displaying notification");
|
||||||
|
// We need to call this asap after the Service can be accessed through it's singleton
|
||||||
LinphoneContext.instance().getNotificationManager().startForeground();
|
LinphoneContext.instance().getNotificationManager().startForeground();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,14 +92,7 @@ public final class LinphoneService extends Service {
|
||||||
LinphoneContext.instance().updateContext(this);
|
LinphoneContext.instance().updateContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Version.sdkAboveOrEqual(Version.API26_O_80)
|
|
||||||
&& intent != null
|
|
||||||
&& intent.getBooleanExtra("ForceStartForeground", false)) {
|
|
||||||
// We need to call this asap after the Service can be accessed through it's singleton
|
|
||||||
LinphoneContext.instance().getNotificationManager().startForeground();
|
|
||||||
}
|
|
||||||
Log.i("[Service] Started");
|
Log.i("[Service] Started");
|
||||||
|
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.utils;
|
package org.linphone.service;
|
||||||
|
|
||||||
import org.linphone.LinphoneService;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
|
|
||||||
public class ServiceWaitThread extends Thread {
|
public class ServiceWaitThread extends Thread {
|
||||||
private ServiceWaitThreadListener mListener;
|
private ServiceWaitThreadListener mListener;
|
|
@ -17,7 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.linphone.utils;
|
package org.linphone.service;
|
||||||
|
|
||||||
public interface ServiceWaitThreadListener {
|
public interface ServiceWaitThreadListener {
|
||||||
void onServiceReady();
|
void onServiceReady();
|
|
@ -240,6 +240,9 @@ public class AccountSettingsFragment extends SettingsFragment {
|
||||||
if (mAuthInfo != null) {
|
if (mAuthInfo != null) {
|
||||||
mAuthInfo.setHa1(null);
|
mAuthInfo.setHa1(null);
|
||||||
mAuthInfo.setPassword(newValue);
|
mAuthInfo.setPassword(newValue);
|
||||||
|
// Reset algorithm to generate correct hash depending on
|
||||||
|
// algorithm set in next to come 401
|
||||||
|
mAuthInfo.setAlgorithm(null);
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
if (core != null) {
|
if (core != null) {
|
||||||
core.addAuthInfo(mAuthInfo);
|
core.addAuthInfo(mAuthInfo);
|
||||||
|
|
|
@ -83,6 +83,8 @@ public class AdvancedSettingsFragment extends SettingsFragment {
|
||||||
mStartAtBoot = mRootView.findViewById(R.id.pref_autostart);
|
mStartAtBoot = mRootView.findViewById(R.id.pref_autostart);
|
||||||
|
|
||||||
mDarkMode = mRootView.findViewById(R.id.pref_dark_mode);
|
mDarkMode = mRootView.findViewById(R.id.pref_dark_mode);
|
||||||
|
mDarkMode.setVisibility(
|
||||||
|
getResources().getBoolean(R.bool.allow_dark_mode) ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
mRemoteProvisioningUrl = mRootView.findViewById(R.id.pref_remote_provisioning);
|
mRemoteProvisioningUrl = mRootView.findViewById(R.id.pref_remote_provisioning);
|
||||||
mRemoteProvisioningUrl.setInputType(
|
mRemoteProvisioningUrl.setInputType(
|
||||||
|
|
|
@ -20,9 +20,12 @@
|
||||||
package org.linphone.settings;
|
package org.linphone.settings;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -54,7 +57,7 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
mAutoAnswer;
|
mAutoAnswer;
|
||||||
private ListSetting mMediaEncryption;
|
private ListSetting mMediaEncryption;
|
||||||
private TextSetting mAutoAnswerTime, mIncomingCallTimeout, mVoiceMailUri;
|
private TextSetting mAutoAnswerTime, mIncomingCallTimeout, mVoiceMailUri;
|
||||||
private BasicSetting mDndPermissionSettings;
|
private BasicSetting mDndPermissionSettings, mAndroidNotificationSettings;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,6 +93,8 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
mMediaEncryption = mRootView.findViewById(R.id.pref_media_encryption);
|
mMediaEncryption = mRootView.findViewById(R.id.pref_media_encryption);
|
||||||
initMediaEncryptionList();
|
initMediaEncryptionList();
|
||||||
|
|
||||||
|
mAndroidNotificationSettings = mRootView.findViewById(R.id.pref_android_app_notif_settings);
|
||||||
|
|
||||||
mAutoAnswerTime = mRootView.findViewById(R.id.pref_auto_answer_time);
|
mAutoAnswerTime = mRootView.findViewById(R.id.pref_auto_answer_time);
|
||||||
mAutoAnswerTime.setInputType(InputType.TYPE_CLASS_NUMBER);
|
mAutoAnswerTime.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||||
|
|
||||||
|
@ -167,8 +172,15 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onListValueChanged(int position, String newLabel, String newValue) {
|
public void onListValueChanged(int position, String newLabel, String newValue) {
|
||||||
try {
|
try {
|
||||||
mPrefs.setMediaEncryption(
|
MediaEncryption encryption =
|
||||||
MediaEncryption.fromInt(Integer.parseInt(newValue)));
|
MediaEncryption.fromInt(Integer.parseInt(newValue));
|
||||||
|
mPrefs.setMediaEncryption(encryption);
|
||||||
|
|
||||||
|
if (encryption == MediaEncryption.None) {
|
||||||
|
mMediaEncryptionMandatory.setChecked(false);
|
||||||
|
}
|
||||||
|
mMediaEncryptionMandatory.setEnabled(
|
||||||
|
encryption != MediaEncryption.None);
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
Log.e(nfe);
|
Log.e(nfe);
|
||||||
}
|
}
|
||||||
|
@ -223,6 +235,27 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
mPrefs.setMediaEncryptionMandatory(newValue);
|
mPrefs.setMediaEncryptionMandatory(newValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mAndroidNotificationSettings.setListener(
|
||||||
|
new SettingListenerBase() {
|
||||||
|
@Override
|
||||||
|
public void onClicked() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Version.API26_O_80) {
|
||||||
|
Context context = getActivity();
|
||||||
|
Intent i = new Intent();
|
||||||
|
i.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
|
||||||
|
i.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
|
||||||
|
i.putExtra(
|
||||||
|
Settings.EXTRA_CHANNEL_ID,
|
||||||
|
context.getString(R.string.notification_service_channel_id));
|
||||||
|
i.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||||
|
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateValues() {
|
private void updateValues() {
|
||||||
|
@ -248,7 +281,12 @@ public class CallSettingsFragment extends SettingsFragment {
|
||||||
mDndPermissionSettings.setVisibility(
|
mDndPermissionSettings.setVisibility(
|
||||||
Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60) ? View.VISIBLE : View.GONE);
|
Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60) ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
mMediaEncryptionMandatory.setChecked(mPrefs.acceptMediaEncryptionMandatory());
|
mMediaEncryptionMandatory.setChecked(mPrefs.isMediaEncryptionMandatory());
|
||||||
|
mMediaEncryptionMandatory.setEnabled(mPrefs.getMediaEncryption() != MediaEncryption.None);
|
||||||
|
|
||||||
|
if (Version.sdkStrictlyBelow(Version.API26_O_80)) {
|
||||||
|
mAndroidNotificationSettings.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
setListeners();
|
setListeners();
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,10 +320,12 @@ public class LinphonePreferences {
|
||||||
|
|
||||||
// Video settings
|
// Video settings
|
||||||
public boolean useFrontCam() {
|
public boolean useFrontCam() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "front_camera_default", true);
|
return getConfig().getBool("app", "front_camera_default", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFrontCamAsDefault(boolean frontcam) {
|
public void setFrontCamAsDefault(boolean frontcam) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "front_camera_default", frontcam);
|
getConfig().setBool("app", "front_camera_default", frontcam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,6 +427,7 @@ public class LinphonePreferences {
|
||||||
|
|
||||||
// Contact settings
|
// Contact settings
|
||||||
public boolean isFriendlistsubscriptionEnabled() {
|
public boolean isFriendlistsubscriptionEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
if (getConfig().getBool("app", "friendlist_subscription_enabled", false)) {
|
if (getConfig().getBool("app", "friendlist_subscription_enabled", false)) {
|
||||||
// Old setting, do migration
|
// Old setting, do migration
|
||||||
getConfig().setBool("app", "friendlist_subscription_enabled", false);
|
getConfig().setBool("app", "friendlist_subscription_enabled", false);
|
||||||
|
@ -434,18 +437,22 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enabledFriendlistSubscription(boolean enabled) {
|
public void enabledFriendlistSubscription(boolean enabled) {
|
||||||
|
if (getLc() == null) return;
|
||||||
getLc().enableFriendListSubscription(enabled);
|
getLc().enableFriendListSubscription(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPresenceStorageInNativeAndroidContactEnabled() {
|
public boolean isPresenceStorageInNativeAndroidContactEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "store_presence_in_native_contact", false);
|
return getConfig().getBool("app", "store_presence_in_native_contact", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enabledPresenceStorageInNativeAndroidContact(boolean enabled) {
|
public void enabledPresenceStorageInNativeAndroidContact(boolean enabled) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "store_presence_in_native_contact", enabled);
|
getConfig().setBool("app", "store_presence_in_native_contact", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDisplayContactOrganization() {
|
public boolean isDisplayContactOrganization() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig()
|
return getConfig()
|
||||||
.getBool(
|
.getBool(
|
||||||
"app",
|
"app",
|
||||||
|
@ -454,24 +461,29 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enabledDisplayContactOrganization(boolean enabled) {
|
public void enabledDisplayContactOrganization(boolean enabled) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "display_contact_organization", enabled);
|
getConfig().setBool("app", "display_contact_organization", enabled);
|
||||||
}
|
}
|
||||||
// End of contact settings
|
// End of contact settings
|
||||||
|
|
||||||
// Call settings
|
// Call settings
|
||||||
public boolean acceptMediaEncryptionMandatory() {
|
public boolean isMediaEncryptionMandatory() {
|
||||||
|
if (getLc() == null) return false;
|
||||||
return getLc().isMediaEncryptionMandatory();
|
return getLc().isMediaEncryptionMandatory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMediaEncryptionMandatory(boolean accept) {
|
public void setMediaEncryptionMandatory(boolean accept) {
|
||||||
|
if (getLc() == null) return;
|
||||||
getLc().setMediaEncryptionMandatory(accept);
|
getLc().setMediaEncryptionMandatory(accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean acceptIncomingEarlyMedia() {
|
public boolean acceptIncomingEarlyMedia() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("sip", "incoming_calls_early_media", false);
|
return getConfig().getBool("sip", "incoming_calls_early_media", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAcceptIncomingEarlyMedia(boolean accept) {
|
public void setAcceptIncomingEarlyMedia(boolean accept) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("sip", "incoming_calls_early_media", accept);
|
getConfig().setBool("sip", "incoming_calls_early_media", accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,28 +518,34 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVoiceMailUri() {
|
public String getVoiceMailUri() {
|
||||||
|
if (getConfig() == null) return null;
|
||||||
return getConfig().getString("app", "voice_mail", null);
|
return getConfig().getString("app", "voice_mail", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVoiceMailUri(String uri) {
|
public void setVoiceMailUri(String uri) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setString("app", "voice_mail", uri);
|
getConfig().setString("app", "voice_mail", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getNativeDialerCall() {
|
public boolean getNativeDialerCall() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "native_dialer_call", false);
|
return getConfig().getBool("app", "native_dialer_call", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNativeDialerCall(boolean use) {
|
public void setNativeDialerCall(boolean use) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "native_dialer_call", use);
|
getConfig().setBool("app", "native_dialer_call", use);
|
||||||
}
|
}
|
||||||
// End of call settings
|
// End of call settings
|
||||||
|
|
||||||
public boolean isWifiOnlyEnabled() {
|
public boolean isWifiOnlyEnabled() {
|
||||||
|
if (getLc() == null) return false;
|
||||||
return getLc().wifiOnlyEnabled();
|
return getLc().wifiOnlyEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network settings
|
// Network settings
|
||||||
public void setWifiOnlyEnabled(Boolean enable) {
|
public void setWifiOnlyEnabled(Boolean enable) {
|
||||||
|
if (getLc() == null) return;
|
||||||
getLc().enableWifiOnly(enable);
|
getLc().enableWifiOnly(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,6 +554,7 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void useRandomPort(boolean enabled, boolean apply) {
|
private void useRandomPort(boolean enabled, boolean apply) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "random_port", enabled);
|
getConfig().setBool("app", "random_port", enabled);
|
||||||
if (apply) {
|
if (apply) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
@ -547,6 +566,7 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUsingRandomPort() {
|
public boolean isUsingRandomPort() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "random_port", true);
|
return getConfig().getBool("app", "random_port", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,10 +697,12 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPushNotificationEnabled() {
|
public boolean isPushNotificationEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "push_notification", true);
|
return getConfig().getBool("app", "push_notification", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPushNotificationEnabled(boolean enable) {
|
public void setPushNotificationEnabled(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "push_notification", enable);
|
getConfig().setBool("app", "push_notification", enable);
|
||||||
|
|
||||||
Core core = getLc();
|
Core core = getLc();
|
||||||
|
@ -748,6 +770,7 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPushNotificationRegistrationID() {
|
private String getPushNotificationRegistrationID() {
|
||||||
|
if (getConfig() == null) return null;
|
||||||
return getConfig().getString("app", "push_notification_regid", null);
|
return getConfig().getString("app", "push_notification_regid", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,30 +793,36 @@ public class LinphonePreferences {
|
||||||
// End of network settings
|
// End of network settings
|
||||||
|
|
||||||
public boolean isDebugEnabled() {
|
public boolean isDebugEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "debug", false);
|
return getConfig().getBool("app", "debug", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advanced settings
|
// Advanced settings
|
||||||
public void setDebugEnabled(boolean enabled) {
|
public void setDebugEnabled(boolean enabled) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "debug", enabled);
|
getConfig().setBool("app", "debug", enabled);
|
||||||
LinphoneUtils.configureLoggingService(enabled, mContext.getString(R.string.app_name));
|
LinphoneUtils.configureLoggingService(enabled, mContext.getString(R.string.app_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJavaLogger(boolean enabled) {
|
public void setJavaLogger(boolean enabled) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "java_logger", enabled);
|
getConfig().setBool("app", "java_logger", enabled);
|
||||||
LinphoneUtils.configureLoggingService(
|
LinphoneUtils.configureLoggingService(
|
||||||
isDebugEnabled(), mContext.getString(R.string.app_name));
|
isDebugEnabled(), mContext.getString(R.string.app_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean useJavaLogger() {
|
public boolean useJavaLogger() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "java_logger", false);
|
return getConfig().getBool("app", "java_logger", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAutoStartEnabled() {
|
public boolean isAutoStartEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "auto_start", false);
|
return getConfig().getBool("app", "auto_start", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutoStart(boolean autoStartEnabled) {
|
public void setAutoStart(boolean autoStartEnabled) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "auto_start", autoStartEnabled);
|
getConfig().setBool("app", "auto_start", autoStartEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,80 +1004,99 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCodecBitrateLimit() {
|
public int getCodecBitrateLimit() {
|
||||||
|
if (getConfig() == null) return 36;
|
||||||
return getConfig().getInt("audio", "codec_bitrate_limit", 36);
|
return getConfig().getInt("audio", "codec_bitrate_limit", 36);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodecBitrateLimit(int bitrate) {
|
public void setCodecBitrateLimit(int bitrate) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setInt("audio", "codec_bitrate_limit", bitrate);
|
getConfig().setInt("audio", "codec_bitrate_limit", bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getXmlrpcUrl() {
|
public String getXmlrpcUrl() {
|
||||||
|
if (getConfig() == null) return null;
|
||||||
return getConfig().getString("assistant", "xmlrpc_url", null);
|
return getConfig().getString("assistant", "xmlrpc_url", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLinkPopupTime() {
|
public String getLinkPopupTime() {
|
||||||
|
if (getConfig() == null) return null;
|
||||||
return getConfig().getString("app", "link_popup_time", null);
|
return getConfig().getString("app", "link_popup_time", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLinkPopupTime(String date) {
|
public void setLinkPopupTime(String date) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setString("app", "link_popup_time", date);
|
getConfig().setString("app", "link_popup_time", date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLinkPopupEnabled() {
|
public boolean isLinkPopupEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "link_popup_enabled", true);
|
return getConfig().getBool("app", "link_popup_enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableLinkPopup(boolean enable) {
|
public void enableLinkPopup(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "link_popup_enabled", enable);
|
getConfig().setBool("app", "link_popup_enabled", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDNDSettingsPopupEnabled() {
|
public boolean isDNDSettingsPopupEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "dnd_settings_popup_enabled", true);
|
return getConfig().getBool("app", "dnd_settings_popup_enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableDNDSettingsPopup(boolean enable) {
|
public void enableDNDSettingsPopup(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "dnd_settings_popup_enabled", enable);
|
getConfig().setBool("app", "dnd_settings_popup_enabled", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLimeSecurityPopupEnabled() {
|
public boolean isLimeSecurityPopupEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "lime_security_popup_enabled", true);
|
return getConfig().getBool("app", "lime_security_popup_enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableLimeSecurityPopup(boolean enable) {
|
public void enableLimeSecurityPopup(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "lime_security_popup_enabled", enable);
|
getConfig().setBool("app", "lime_security_popup_enabled", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDebugPopupAddress() {
|
public String getDebugPopupAddress() {
|
||||||
|
if (getConfig() == null) return null;
|
||||||
return getConfig().getString("app", "debug_popup_magic", null);
|
return getConfig().getString("app", "debug_popup_magic", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getActivityToLaunchOnIncomingReceived() {
|
public String getActivityToLaunchOnIncomingReceived() {
|
||||||
|
if (getConfig() == null) return "org.linphone.call.CallIncomingActivity";
|
||||||
return getConfig()
|
return getConfig()
|
||||||
.getString(
|
.getString(
|
||||||
"app", "incoming_call_activity", "org.linphone.call.CallIncomingActivity");
|
"app", "incoming_call_activity", "org.linphone.call.CallIncomingActivity");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActivityToLaunchOnIncomingReceived(String name) {
|
public void setActivityToLaunchOnIncomingReceived(String name) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setString("app", "incoming_call_activity", name);
|
getConfig().setString("app", "incoming_call_activity", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getServiceNotificationVisibility() {
|
public boolean getServiceNotificationVisibility() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "show_service_notification", false);
|
return getConfig().getBool("app", "show_service_notification", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServiceNotificationVisibility(boolean enable) {
|
public void setServiceNotificationVisibility(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "show_service_notification", enable);
|
getConfig().setBool("app", "show_service_notification", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCheckReleaseUrl() {
|
public String getCheckReleaseUrl() {
|
||||||
|
if (getConfig() == null) return null;
|
||||||
return getConfig().getString("misc", "version_check_url_root", null);
|
return getConfig().getString("misc", "version_check_url_root", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLastCheckReleaseTimestamp() {
|
public int getLastCheckReleaseTimestamp() {
|
||||||
|
if (getConfig() == null) return 0;
|
||||||
return getConfig().getInt("app", "version_check_url_last_timestamp", 0);
|
return getConfig().getInt("app", "version_check_url_last_timestamp", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastCheckReleaseTimestamp(int timestamp) {
|
public void setLastCheckReleaseTimestamp(int timestamp) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setInt("app", "version_check_url_last_timestamp", timestamp);
|
getConfig().setInt("app", "version_check_url_last_timestamp", timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1058,10 +1106,12 @@ public class LinphonePreferences {
|
||||||
// Disable overlay and use PIP feature
|
// Disable overlay and use PIP feature
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "display_overlay", false);
|
return getConfig().getBool("app", "display_overlay", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableOverlay(boolean enable) {
|
public void enableOverlay(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "display_overlay", enable);
|
getConfig().setBool("app", "display_overlay", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,71 +1121,87 @@ public class LinphonePreferences {
|
||||||
.checkPermission(
|
.checkPermission(
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
mContext.getPackageName());
|
mContext.getPackageName());
|
||||||
|
if (getConfig() == null) return readExternalStorage == PackageManager.PERMISSION_GRANTED;
|
||||||
return getConfig().getBool("app", "device_ringtone", true)
|
return getConfig().getBool("app", "device_ringtone", true)
|
||||||
&& readExternalStorage == PackageManager.PERMISSION_GRANTED;
|
&& readExternalStorage == PackageManager.PERMISSION_GRANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableDeviceRingtone(boolean enable) {
|
public void enableDeviceRingtone(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "device_ringtone", enable);
|
getConfig().setBool("app", "device_ringtone", enable);
|
||||||
LinphoneManager.getInstance().enableDeviceRingtone(enable);
|
LinphoneManager.getInstance().enableDeviceRingtone(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIncomingCallVibrationEnabled() {
|
public boolean isIncomingCallVibrationEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "incoming_call_vibration", true);
|
return getConfig().getBool("app", "incoming_call_vibration", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableIncomingCallVibration(boolean enable) {
|
public void enableIncomingCallVibration(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "incoming_call_vibration", enable);
|
getConfig().setBool("app", "incoming_call_vibration", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBisFeatureEnabled() {
|
public boolean isBisFeatureEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "bis_feature", true);
|
return getConfig().getBool("app", "bis_feature", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAutoAnswerEnabled() {
|
public boolean isAutoAnswerEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "auto_answer", false);
|
return getConfig().getBool("app", "auto_answer", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableAutoAnswer(boolean enable) {
|
public void enableAutoAnswer(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "auto_answer", enable);
|
getConfig().setBool("app", "auto_answer", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAutoAnswerTime() {
|
public int getAutoAnswerTime() {
|
||||||
|
if (getConfig() == null) return 0;
|
||||||
return getConfig().getInt("app", "auto_answer_delay", 0);
|
return getConfig().getInt("app", "auto_answer_delay", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutoAnswerTime(int time) {
|
public void setAutoAnswerTime(int time) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setInt("app", "auto_answer_delay", time);
|
getConfig().setInt("app", "auto_answer_delay", time);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableFriendsStorage() {
|
public void disableFriendsStorage() {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("misc", "store_friends", false);
|
getConfig().setBool("misc", "store_friends", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean useBasicChatRoomFor1To1() {
|
public boolean useBasicChatRoomFor1To1() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "prefer_basic_chat_room", false);
|
return getConfig().getBool("app", "prefer_basic_chat_room", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 is download all, -1 is disable feature, else size is bytes
|
// 0 is download all, -1 is disable feature, else size is bytes
|
||||||
public int getAutoDownloadFileMaxSize() {
|
public int getAutoDownloadFileMaxSize() {
|
||||||
|
if (getLc() == null) return -1;
|
||||||
return getLc().getMaxSizeForAutoDownloadIncomingFiles();
|
return getLc().getMaxSizeForAutoDownloadIncomingFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 is download all, -1 is disable feature, else size is bytes
|
// 0 is download all, -1 is disable feature, else size is bytes
|
||||||
public void setAutoDownloadFileMaxSize(int size) {
|
public void setAutoDownloadFileMaxSize(int size) {
|
||||||
|
if (getLc() == null) return;
|
||||||
getLc().setMaxSizeForAutoDownloadIncomingFiles(size);
|
getLc().setMaxSizeForAutoDownloadIncomingFiles(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPowerSaverDialogBeenPrompted() {
|
public boolean hasPowerSaverDialogBeenPrompted() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "android_power_saver_dialog", false);
|
return getConfig().getBool("app", "android_power_saver_dialog", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void powerSaverDialogPrompted(boolean b) {
|
public void powerSaverDialogPrompted(boolean b) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "android_power_saver_dialog", b);
|
getConfig().setBool("app", "android_power_saver_dialog", b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDarkModeEnabled() {
|
public boolean isDarkModeEnabled() {
|
||||||
if (getConfig() == null) return false;
|
if (getConfig() == null) return false;
|
||||||
|
if (!mContext.getResources().getBoolean(R.bool.allow_dark_mode)) return false;
|
||||||
|
|
||||||
boolean useNightModeDefault =
|
boolean useNightModeDefault =
|
||||||
AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES;
|
AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES;
|
||||||
|
@ -1152,63 +1218,78 @@ public class LinphonePreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableDarkMode(boolean enable) {
|
public void enableDarkMode(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "dark_mode", enable);
|
getConfig().setBool("app", "dark_mode", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDeviceName(Context context) {
|
public String getDeviceName(Context context) {
|
||||||
String defaultValue = Compatibility.getDeviceName(context);
|
String defaultValue = Compatibility.getDeviceName(context);
|
||||||
|
if (getConfig() == null) return defaultValue;
|
||||||
return getConfig().getString("app", "device_name", defaultValue);
|
return getConfig().getString("app", "device_name", defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeviceName(String name) {
|
public void setDeviceName(String name) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setString("app", "device_name", name);
|
getConfig().setString("app", "device_name", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEchoCancellationCalibrationDone() {
|
public boolean isEchoCancellationCalibrationDone() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "echo_cancellation_calibration_done", false);
|
return getConfig().getBool("app", "echo_cancellation_calibration_done", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEchoCancellationCalibrationDone(boolean done) {
|
public void setEchoCancellationCalibrationDone(boolean done) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "echo_cancellation_calibration_done", done);
|
getConfig().setBool("app", "echo_cancellation_calibration_done", done);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOpenH264CodecDownloadEnabled() {
|
public boolean isOpenH264CodecDownloadEnabled() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("app", "open_h264_download_enabled", true);
|
return getConfig().getBool("app", "open_h264_download_enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOpenH264CodecDownloadEnabled(boolean enable) {
|
public void setOpenH264CodecDownloadEnabled(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "open_h264_download_enabled", enable);
|
getConfig().setBool("app", "open_h264_download_enabled", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVideoPreviewEnabled() {
|
public boolean isVideoPreviewEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return isVideoEnabled() && getConfig().getBool("app", "video_preview", false);
|
return isVideoEnabled() && getConfig().getBool("app", "video_preview", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVideoPreviewEnabled(boolean enabled) {
|
public void setVideoPreviewEnabled(boolean enabled) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "video_preview", enabled);
|
getConfig().setBool("app", "video_preview", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shortcutsCreationEnabled() {
|
public boolean shortcutsCreationEnabled() {
|
||||||
|
if (getConfig() == null) return false;
|
||||||
return getConfig().getBool("app", "shortcuts", false);
|
return getConfig().getBool("app", "shortcuts", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableChatRoomsShortcuts(boolean enable) {
|
public void enableChatRoomsShortcuts(boolean enable) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("app", "shortcuts", enable);
|
getConfig().setBool("app", "shortcuts", enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hideEmptyChatRooms() {
|
public boolean hideEmptyChatRooms() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("misc", "hide_empty_chat_rooms", true);
|
return getConfig().getBool("misc", "hide_empty_chat_rooms", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHideEmptyChatRooms(boolean hide) {
|
public void setHideEmptyChatRooms(boolean hide) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("misc", "hide_empty_chat_rooms", hide);
|
getConfig().setBool("misc", "hide_empty_chat_rooms", hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hideRemovedProxiesChatRooms() {
|
public boolean hideRemovedProxiesChatRooms() {
|
||||||
|
if (getConfig() == null) return true;
|
||||||
return getConfig().getBool("misc", "hide_chat_rooms_from_removed_proxies", true);
|
return getConfig().getBool("misc", "hide_chat_rooms_from_removed_proxies", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHideRemovedProxiesChatRooms(boolean hide) {
|
public void setHideRemovedProxiesChatRooms(boolean hide) {
|
||||||
|
if (getConfig() == null) return;
|
||||||
getConfig().setBool("misc", "hide_chat_rooms_from_removed_proxies", hide);
|
getConfig().setBool("misc", "hide_chat_rooms_from_removed_proxies", hide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,6 +312,7 @@ public class VideoSettingsFragment extends SettingsFragment {
|
||||||
: View.GONE);
|
: View.GONE);
|
||||||
mAutoInitiate.setVisibility(show ? View.VISIBLE : View.GONE);
|
mAutoInitiate.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
mAutoAccept.setVisibility(show ? View.VISIBLE : View.GONE);
|
mAutoAccept.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
|
mCameraDevices.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
mOverlay.setVisibility(show ? View.VISIBLE : View.GONE);
|
mOverlay.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
mBandwidth.setVisibility(show ? View.VISIBLE : View.GONE);
|
mBandwidth.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
mPreset.setVisibility(show ? View.VISIBLE : View.GONE);
|
mPreset.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
|
@ -319,6 +320,17 @@ public class VideoSettingsFragment extends SettingsFragment {
|
||||||
mFps.setVisibility(show ? View.VISIBLE : View.GONE);
|
mFps.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
mVideoCodecs.setVisibility(show ? View.VISIBLE : View.GONE);
|
mVideoCodecs.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
mVideoCodecsHeader.setVisibility(show ? View.VISIBLE : View.GONE);
|
mVideoCodecsHeader.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
if (show) {
|
||||||
|
if (Version.sdkAboveOrEqual(Version.API26_O_80)
|
||||||
|
&& getResources().getBoolean(R.bool.allow_pip_while_video_call)) {
|
||||||
|
// Disable overlay and use PIP feature
|
||||||
|
mOverlay.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
mBandwidth.setVisibility(
|
||||||
|
mPrefs.getVideoPreset().equals("custom") ? View.VISIBLE : View.GONE);
|
||||||
|
mFps.setVisibility(mPrefs.getVideoPreset().equals("custom") ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCameraDevicesList() {
|
private void initCameraDevicesList() {
|
||||||
|
|
|
@ -151,9 +151,10 @@ public class DeviceUtils {
|
||||||
for (final Intent intent : POWERMANAGER_INTENTS) {
|
for (final Intent intent : POWERMANAGER_INTENTS) {
|
||||||
if (DeviceUtils.isIntentCallable(context, intent)) {
|
if (DeviceUtils.isIntentCallable(context, intent)) {
|
||||||
Log.w(
|
Log.w(
|
||||||
"[Hacks] "
|
"[Hacks] ",
|
||||||
+ android.os.Build.MANUFACTURER
|
android.os.Build.MANUFACTURER,
|
||||||
+ " device with power saver detected !");
|
" device with power saver detected: ",
|
||||||
|
intent.getComponent().getClassName());
|
||||||
if (!LinphonePreferences.instance().hasPowerSaverDialogBeenPrompted()) {
|
if (!LinphonePreferences.instance().hasPowerSaverDialogBeenPrompted()) {
|
||||||
Log.w("[Hacks] Asking power saver for whitelist !");
|
Log.w("[Hacks] Asking power saver for whitelist !");
|
||||||
|
|
||||||
|
@ -197,12 +198,19 @@ public class DeviceUtils {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Log.w(
|
Log.w(
|
||||||
"[Hacks] Power saver detected, user is going to settings :)");
|
"[Hacks] Power saver detected, user is going to settings :)");
|
||||||
if (doNotAskAgain.isChecked()) {
|
// If user is going into the settings,
|
||||||
LinphonePreferences.instance()
|
// assume it will make the change so don't prompt again
|
||||||
.powerSaverDialogPrompted(true);
|
LinphonePreferences.instance().powerSaverDialogPrompted(true);
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
|
} catch (SecurityException se) {
|
||||||
|
Log.e(
|
||||||
|
"[Hacks] Couldn't start intent [",
|
||||||
|
intent.getComponent().getClassName(),
|
||||||
|
"], security exception was thrown: ",
|
||||||
|
se);
|
||||||
|
}
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.linphone.utils;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffXfermode;
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
@ -55,7 +56,7 @@ public class ImageUtils {
|
||||||
return bm;
|
return bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bitmap getRoundBitmap(Bitmap bitmap) {
|
public static Bitmap getRoundBitmap(Bitmap bitmap) {
|
||||||
Bitmap output =
|
Bitmap output =
|
||||||
Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(output);
|
Canvas canvas = new Canvas(output);
|
||||||
|
@ -85,4 +86,14 @@ public class ImageUtils {
|
||||||
/ ((float) context.getResources().getDisplayMetrics().densityDpi
|
/ ((float) context.getResources().getDisplayMetrics().densityDpi
|
||||||
/ DisplayMetrics.DENSITY_DEFAULT);
|
/ DisplayMetrics.DENSITY_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Bitmap rotateImage(Bitmap source, float angle) {
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postRotate(angle);
|
||||||
|
Bitmap rotatedBitmap =
|
||||||
|
Bitmap.createBitmap(
|
||||||
|
source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
|
||||||
|
source.recycle();
|
||||||
|
return rotatedBitmap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2019 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-android
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.linphone.views;
|
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
class AsyncBitmap extends BitmapDrawable {
|
|
||||||
private final WeakReference<BitmapWorkerTask> mBitmapWorkerTaskReference;
|
|
||||||
|
|
||||||
public AsyncBitmap(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
|
|
||||||
super(res, bitmap);
|
|
||||||
mBitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitmapWorkerTask getBitmapWorkerTask() {
|
|
||||||
return mBitmapWorkerTaskReference.get();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,166 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2019 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-android
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.linphone.views;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.media.ExifInterface;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.provider.MediaStore;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import org.linphone.LinphoneContext;
|
|
||||||
import org.linphone.core.tools.Log;
|
|
||||||
import org.linphone.utils.FileUtils;
|
|
||||||
import org.linphone.utils.ImageUtils;
|
|
||||||
|
|
||||||
public class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
|
|
||||||
private String path;
|
|
||||||
|
|
||||||
private final WeakReference<ImageView> mImageViewReference;
|
|
||||||
private final Bitmap mDefaultBitmap;
|
|
||||||
private final int mImageViewHeight;
|
|
||||||
|
|
||||||
public BitmapWorkerTask(ImageView imageView, Bitmap defaultBitmap) {
|
|
||||||
mDefaultBitmap = defaultBitmap;
|
|
||||||
path = null;
|
|
||||||
// Use a WeakReference to ensure the ImageView can be garbage collected
|
|
||||||
mImageViewReference = new WeakReference<>(imageView);
|
|
||||||
mImageViewHeight = imageView.getMeasuredHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
|
|
||||||
if (imageView != null) {
|
|
||||||
final Drawable drawable = imageView.getDrawable();
|
|
||||||
if (drawable instanceof AsyncBitmap) {
|
|
||||||
final AsyncBitmap asyncDrawable = (AsyncBitmap) drawable;
|
|
||||||
return asyncDrawable.getBitmapWorkerTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap scaleToFitHeight(Bitmap b, int height) {
|
|
||||||
float factor = height / (float) b.getHeight();
|
|
||||||
int dstWidth = (int) (b.getWidth() * factor);
|
|
||||||
if (dstWidth > 0 && height > 0) {
|
|
||||||
return Bitmap.createScaledBitmap(b, dstWidth, height, true);
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode image in background.
|
|
||||||
@Override
|
|
||||||
protected Bitmap doInBackground(String... params) {
|
|
||||||
Context context = LinphoneContext.instance().getApplicationContext();
|
|
||||||
path = params[0];
|
|
||||||
Bitmap bm = null;
|
|
||||||
Bitmap thumbnail = null;
|
|
||||||
if (FileUtils.isExtensionImage(path)) {
|
|
||||||
if (path.startsWith("content")) {
|
|
||||||
try {
|
|
||||||
bm =
|
|
||||||
MediaStore.Images.Media.getBitmap(
|
|
||||||
context.getContentResolver(), Uri.parse(path));
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bm = BitmapFactory.decodeFile(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageView imageView = mImageViewReference.get();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Rotate the bitmap if possible/needed, using EXIF data
|
|
||||||
Matrix matrix = new Matrix();
|
|
||||||
ExifInterface exif = new ExifInterface(path);
|
|
||||||
int width = bm.getWidth();
|
|
||||||
int height = bm.getHeight();
|
|
||||||
|
|
||||||
int pictureOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
|
|
||||||
if (pictureOrientation == 6 || pictureOrientation == 3 || pictureOrientation == 8) {
|
|
||||||
if (imageView != null) {
|
|
||||||
float factor = (float) mImageViewHeight / height;
|
|
||||||
matrix.postScale(factor, factor);
|
|
||||||
}
|
|
||||||
if (pictureOrientation == 6) {
|
|
||||||
matrix.preRotate(90);
|
|
||||||
} else if (pictureOrientation == 3) {
|
|
||||||
matrix.preRotate(180);
|
|
||||||
} else {
|
|
||||||
matrix.preRotate(270);
|
|
||||||
}
|
|
||||||
thumbnail = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
|
|
||||||
if (thumbnail != bm) {
|
|
||||||
bm.recycle();
|
|
||||||
bm = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thumbnail == null && bm != null) {
|
|
||||||
if (imageView == null) return bm;
|
|
||||||
thumbnail = scaleToFitHeight(bm, mImageViewHeight);
|
|
||||||
if (thumbnail != bm) {
|
|
||||||
bm.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return thumbnail;
|
|
||||||
} else {
|
|
||||||
return mDefaultBitmap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once complete, see if ImageView is still around and set bitmap.
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Bitmap bitmap) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
bitmap.recycle();
|
|
||||||
bitmap = null;
|
|
||||||
}
|
|
||||||
if (mImageViewReference != null && bitmap != null) {
|
|
||||||
Context context = LinphoneContext.instance().getApplicationContext();
|
|
||||||
final ImageView imageView = mImageViewReference.get();
|
|
||||||
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
|
||||||
if (this == bitmapWorkerTask && imageView != null) {
|
|
||||||
imageView.setImageBitmap(bitmap);
|
|
||||||
if (bitmap.getWidth() > ImageUtils.dpToPixels(context, 300)) {
|
|
||||||
RelativeLayout.LayoutParams params =
|
|
||||||
new RelativeLayout.LayoutParams(
|
|
||||||
bitmap.getWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
int margin = (int) ImageUtils.dpToPixels(context, 5);
|
|
||||||
params.setMargins(margin, margin, margin, margin);
|
|
||||||
imageView.setLayoutParams(params);
|
|
||||||
imageView.invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
10
app/src/main/res/drawable/call_numpad.xml
Normal file
10
app/src/main/res/drawable/call_numpad.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_selected="true">
|
||||||
|
<bitmap android:src="@drawable/dialer_alt_back" />
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<bitmap android:src="@drawable/footer_dialer" />
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
|
|
|
@ -109,6 +109,7 @@
|
||||||
android:id="@+id/buttons"
|
android:id="@+id/buttons"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
android:gravity="bottom">
|
android:gravity="bottom">
|
||||||
|
|
||||||
<!-- This is a better way of splitting screen 50/50 than using weights -->
|
<!-- This is a better way of splitting screen 50/50 than using weights -->
|
||||||
|
@ -119,29 +120,30 @@
|
||||||
android:layout_centerHorizontal="true" />
|
android:layout_centerHorizontal="true" />
|
||||||
|
|
||||||
<include layout="@layout/call_primary_buttons"
|
<include layout="@layout/call_primary_buttons"
|
||||||
|
android:id="@+id/call_primary_buttons"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_toLeftOf="@id/vertical_divider" />
|
android:layout_toLeftOf="@id/vertical_divider" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/numpad"
|
||||||
|
android:inflatedId="@+id/numpad"
|
||||||
|
android:layout="@layout/numpad"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_above="@id/call_primary_buttons"
|
||||||
|
android:background="@color/toolbar_color" />
|
||||||
|
|
||||||
<include layout="@layout/call_secondary_buttons"
|
<include layout="@layout/call_secondary_buttons"
|
||||||
|
android:id="@+id/call_secondary_buttons"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_toRightOf="@id/vertical_divider" />
|
android:layout_toRightOf="@id/vertical_divider" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<ViewStub
|
|
||||||
android:id="@+id/numpad"
|
|
||||||
android:inflatedId="@+id/numpad"
|
|
||||||
android:layout="@layout/numpad"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:background="@color/toolbar_color" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:background="?attr/lighToolbarBackgroundColor">
|
android:background="?attr/lighToolbarBackgroundColor">
|
||||||
|
|
||||||
<org.linphone.views.EraseButton
|
<org.linphone.dialer.views.EraseButton
|
||||||
android:id="@+id/erase"
|
android:id="@+id/erase"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
android:contentDescription="@string/content_description_backspace"
|
android:contentDescription="@string/content_description_backspace"
|
||||||
android:src="@drawable/backspace" />
|
android:src="@drawable/backspace" />
|
||||||
|
|
||||||
<org.linphone.views.AddressText
|
<org.linphone.dialer.views.AddressText
|
||||||
android:id="@+id/address"
|
android:id="@+id/address"
|
||||||
style="@style/numpad_composed_number_font"
|
style="@style/numpad_composed_number_font"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<org.linphone.views.CallButton
|
<org.linphone.call.views.CallButton
|
||||||
android:id="@+id/start_call"
|
android:id="@+id/start_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:src="@drawable/call_audio_start" />
|
android:src="@drawable/call_audio_start" />
|
||||||
|
|
||||||
<org.linphone.views.CallButton
|
<org.linphone.call.views.CallButton
|
||||||
android:id="@+id/add_call"
|
android:id="@+id/add_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:src="@drawable/call_add" />
|
android:src="@drawable/call_add" />
|
||||||
|
|
||||||
<org.linphone.views.CallButton
|
<org.linphone.call.views.CallButton
|
||||||
android:id="@+id/transfer_call"
|
android:id="@+id/transfer_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:background="?attr/lighToolbarBackgroundColor">
|
android:background="?attr/lighToolbarBackgroundColor">
|
||||||
|
|
||||||
<org.linphone.views.EraseButton
|
<org.linphone.dialer.views.EraseButton
|
||||||
android:id="@+id/erase"
|
android:id="@+id/erase"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
android:contentDescription="@string/content_description_backspace"
|
android:contentDescription="@string/content_description_backspace"
|
||||||
android:src="@drawable/backspace" />
|
android:src="@drawable/backspace" />
|
||||||
|
|
||||||
<org.linphone.views.AddressText
|
<org.linphone.dialer.views.AddressText
|
||||||
android:id="@+id/address"
|
android:id="@+id/address"
|
||||||
style="@style/numpad_composed_number_font"
|
style="@style/numpad_composed_number_font"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<org.linphone.views.CallButton
|
<org.linphone.call.views.CallButton
|
||||||
android:id="@+id/start_call"
|
android:id="@+id/start_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:src="@drawable/call_audio_start" />
|
android:src="@drawable/call_audio_start" />
|
||||||
|
|
||||||
<org.linphone.views.CallButton
|
<org.linphone.call.views.CallButton
|
||||||
android:id="@+id/add_call"
|
android:id="@+id/add_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -136,7 +136,7 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:src="@drawable/call_add" />
|
android:src="@drawable/call_add" />
|
||||||
|
|
||||||
<org.linphone.views.CallButton
|
<org.linphone.call.views.CallButton
|
||||||
android:id="@+id/transfer_call"
|
android:id="@+id/transfer_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue