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
|
||||
source_file = app/src/main/res/values/strings.xml
|
||||
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]
|
||||
|
||||
### Added
|
||||
-
|
||||
|
||||
### Changed
|
||||
-
|
||||
|
||||
## [4.2.0] - 2019-12-09
|
||||
|
||||
### Added
|
||||
- Added shortcuts to contacts' latest chat rooms
|
||||
- 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)
|
||||
- Android 10 compatibility
|
||||
- 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
|
||||
- Call statistics are now available for each call & conference
|
||||
- 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)
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -73,8 +73,7 @@ excludePackage.add('**/LICENSE.txt')
|
|||
|
||||
repositories {
|
||||
maven {
|
||||
// Replace snapshots by releases for releases !
|
||||
url "https://linphone.org/snapshots/maven_repository"
|
||||
url "https://linphone.org/maven_repository"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +88,7 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 4129
|
||||
versionCode 4213
|
||||
versionName "${project.version}"
|
||||
applicationId getPackageName()
|
||||
multiDexEnabled true
|
||||
|
|
|
@ -64,7 +64,8 @@
|
|||
android:largeHeap="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:resizeableActivity="true"
|
||||
android:theme="@style/LinphoneStyle">
|
||||
android:theme="@style/LinphoneStyle"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
|
||||
<!-- Starting activities -->
|
||||
|
||||
|
@ -81,7 +82,7 @@
|
|||
<!-- Main activities -->
|
||||
|
||||
<activity
|
||||
android:name=".activities.DialerActivity"
|
||||
android:name=".dialer.DialerActivity"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DIAL" />
|
||||
|
@ -211,7 +212,7 @@
|
|||
<!-- Services -->
|
||||
|
||||
<service
|
||||
android:name=".LinphoneService"
|
||||
android:name=".service.LinphoneService"
|
||||
android:label="@string/service_name" />
|
||||
|
||||
<service
|
||||
|
@ -252,9 +253,8 @@
|
|||
<receiver android:name=".receivers.BootReceiver">
|
||||
<intent-filter>
|
||||
<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.MY_PACKAGE_REPLACED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
|
|
|
@ -21,28 +21,33 @@ package org.linphone;
|
|||
|
||||
import static android.content.Intent.ACTION_MAIN;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.provider.ContactsContract;
|
||||
import java.util.ArrayList;
|
||||
import org.linphone.call.CallActivity;
|
||||
import org.linphone.call.CallIncomingActivity;
|
||||
import org.linphone.call.CallOutgoingActivity;
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.ConfiguringState;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.core.Factory;
|
||||
import org.linphone.core.GlobalState;
|
||||
import org.linphone.core.LogLevel;
|
||||
import org.linphone.core.LoggingService;
|
||||
import org.linphone.core.LoggingServiceListener;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.notifications.NotificationsManager;
|
||||
import org.linphone.service.LinphoneService;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.DeviceUtils;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.utils.PushNotificationUtils;
|
||||
|
||||
public class LinphoneContext {
|
||||
private static LinphoneContext sInstance = null;
|
||||
|
@ -78,7 +83,7 @@ public class LinphoneContext {
|
|||
private NotificationsManager mNotificationManager;
|
||||
private LinphoneManager mLinphoneManager;
|
||||
private ContactsManager mContactsManager;
|
||||
private Class<? extends Activity> mIncomingReceivedActivity = CallIncomingActivity.class;
|
||||
private final ArrayList<CoreStartedListener> mCoreStartedListeners;
|
||||
|
||||
public static boolean isReady() {
|
||||
return sInstance != null;
|
||||
|
@ -90,6 +95,7 @@ public class LinphoneContext {
|
|||
|
||||
public LinphoneContext(Context context) {
|
||||
mContext = context;
|
||||
mCoreStartedListeners = new ArrayList<>();
|
||||
|
||||
LinphonePreferences.instance().setContext(context);
|
||||
Factory.instance().setLogCollectionPath(context.getFilesDir().getAbsolutePath());
|
||||
|
@ -100,23 +106,40 @@ public class LinphoneContext {
|
|||
dumpDeviceInformation();
|
||||
dumpLinphoneInformation();
|
||||
|
||||
String incomingReceivedActivityName =
|
||||
LinphonePreferences.instance().getActivityToLaunchOnIncomingReceived();
|
||||
try {
|
||||
mIncomingReceivedActivity =
|
||||
(Class<? extends Activity>) Class.forName(incomingReceivedActivityName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
sInstance = this;
|
||||
Log.i("[Context] Ready");
|
||||
|
||||
mListener =
|
||||
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
|
||||
public void onCallStateChanged(
|
||||
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)) {
|
||||
mNotificationManager.displayCallNotification(call);
|
||||
}
|
||||
|
@ -157,12 +180,28 @@ public class LinphoneContext {
|
|||
|
||||
mLinphoneManager = new LinphoneManager(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) {
|
||||
Log.i("[Context] Starting");
|
||||
mLinphoneManager.startLibLinphone(isPush);
|
||||
LinphoneManager.getCore().addListener(mListener);
|
||||
Log.i("[Context] Starting, push status is ", isPush);
|
||||
mLinphoneManager.startLibLinphone(isPush, mListener);
|
||||
|
||||
mNotificationManager.onCoreReady();
|
||||
|
||||
|
@ -236,6 +275,14 @@ public class LinphoneContext {
|
|||
return mContactsManager;
|
||||
}
|
||||
|
||||
public void addCoreStartedListener(CoreStartedListener listener) {
|
||||
mCoreStartedListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeCoreStartedListener(CoreStartedListener listener) {
|
||||
mCoreStartedListeners.remove(listener);
|
||||
}
|
||||
|
||||
/* Log device related information */
|
||||
|
||||
private void dumpDeviceInformation() {
|
||||
|
@ -266,7 +313,7 @@ public class LinphoneContext {
|
|||
/* Call activities */
|
||||
|
||||
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
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
|
@ -285,4 +332,8 @@ public class LinphoneContext {
|
|||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
public interface CoreStartedListener {
|
||||
void onCoreStarted();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,18 +45,18 @@ import java.util.Date;
|
|||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import org.linphone.assistant.PhoneAccountLinkingAssistantActivity;
|
||||
import org.linphone.call.AndroidAudioManager;
|
||||
import org.linphone.call.CallManager;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.core.AccountCreator;
|
||||
import org.linphone.core.AccountCreatorListenerStub;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.Call.State;
|
||||
import org.linphone.core.ConfiguringState;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.CoreListener;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.core.Factory;
|
||||
import org.linphone.core.FriendList;
|
||||
import org.linphone.core.GlobalState;
|
||||
import org.linphone.core.PresenceActivity;
|
||||
import org.linphone.core.PresenceBasicStatus;
|
||||
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.Log;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.AndroidAudioManager;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.utils.MediaScanner;
|
||||
import org.linphone.utils.PushNotificationUtils;
|
||||
|
@ -160,37 +159,6 @@ public class LinphoneManager implements SensorEventListener {
|
|||
|
||||
mCoreListener =
|
||||
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")
|
||||
@Override
|
||||
public void onCallStateChanged(
|
||||
|
@ -198,7 +166,7 @@ public class LinphoneManager implements SensorEventListener {
|
|||
final Call call,
|
||||
final State state,
|
||||
final String message) {
|
||||
Log.i("[Manager] New call state [", state, "]");
|
||||
Log.i("[Manager] Call state is [", state, "]");
|
||||
if (state == State.IncomingReceived
|
||||
&& !call.equals(core.getCurrentCall())) {
|
||||
if (call.getReplacedCall() != null) {
|
||||
|
@ -388,6 +356,7 @@ public class LinphoneManager implements SensorEventListener {
|
|||
}
|
||||
|
||||
public void restartCore() {
|
||||
Log.w("[Manager] Restarting Core");
|
||||
mCore.stop();
|
||||
mCore.start();
|
||||
}
|
||||
|
@ -395,8 +364,8 @@ public class LinphoneManager implements SensorEventListener {
|
|||
private void destroyCore() {
|
||||
Log.w("[Manager] Destroying Core");
|
||||
if (LinphonePreferences.instance() != null) {
|
||||
// We set network reachable at false before destroy LC to not send register with expires
|
||||
// at 0
|
||||
// We set network reachable at false before destroying the Core
|
||||
// to not send a register with expires at 0
|
||||
if (LinphonePreferences.instance().isPushNotificationEnabled()) {
|
||||
Log.w(
|
||||
"[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 {
|
||||
mCore =
|
||||
Factory.instance()
|
||||
|
@ -437,6 +406,7 @@ public class LinphoneManager implements SensorEventListener {
|
|||
mPrefs.getLinphoneDefaultConfig(),
|
||||
mPrefs.getLinphoneFactoryConfig(),
|
||||
mContext);
|
||||
mCore.addListener(listener);
|
||||
mCore.addListener(mCoreListener);
|
||||
|
||||
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*/
|
||||
mTimer = new Timer("Linphone scheduler");
|
||||
mTimer.schedule(lTask, 0, 20);
|
||||
|
||||
configureCore();
|
||||
} catch (Exception e) {
|
||||
Log.e(e, "[Manager] Cannot start linphone");
|
||||
}
|
||||
|
@ -474,8 +446,8 @@ public class LinphoneManager implements SensorEventListener {
|
|||
H264Helper.setH264Mode(H264Helper.MODE_AUTO, mCore);
|
||||
}
|
||||
|
||||
private synchronized void initLiblinphone(Core core) {
|
||||
mCore = core;
|
||||
private synchronized void configureCore() {
|
||||
Log.i("[Manager] Configuring Core");
|
||||
mAudioManager = new AndroidAudioManager(mContext);
|
||||
|
||||
mCore.setZrtpSecretsFile(mBasePath + "/zrtp_secrets");
|
||||
|
@ -544,6 +516,8 @@ public class LinphoneManager implements SensorEventListener {
|
|||
mAccountCreator = mCore.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
|
||||
mAccountCreator.setListener(mAccountCreatorListener);
|
||||
mCallGsmON = false;
|
||||
|
||||
Log.i("[Manager] Core configured");
|
||||
}
|
||||
|
||||
public void resetCameraFromPreferences() {
|
||||
|
@ -572,16 +546,28 @@ public class LinphoneManager implements SensorEventListener {
|
|||
|
||||
/* 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() {
|
||||
if (mCore.getDefaultProxyConfig() != null) {
|
||||
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) {
|
||||
mAccountCreator.setUsername(
|
||||
accountCreator.reset();
|
||||
accountCreator.setUsername(
|
||||
LinphonePreferences.instance()
|
||||
.getAccountUsername(
|
||||
LinphonePreferences.instance().getDefaultAccountIndex()));
|
||||
mAccountCreator.isAccountExist();
|
||||
accountCreator.isAccountExist();
|
||||
}
|
||||
} else {
|
||||
LinphonePreferences.instance().setLinkPopupTime(null);
|
||||
|
@ -839,7 +825,7 @@ public class LinphoneManager implements SensorEventListener {
|
|||
|
||||
public void setCallGsmON(boolean on) {
|
||||
mCallGsmON = on;
|
||||
if (on) {
|
||||
if (on && mCore != null) {
|
||||
mCore.pauseAllCalls();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import android.os.Bundle;
|
|||
import android.view.Surface;
|
||||
import org.linphone.LinphoneContext;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.service.LinphoneService;
|
||||
|
||||
public abstract class LinphoneGenericActivity extends ThemeableActivity {
|
||||
@Override
|
||||
|
@ -80,8 +80,15 @@ public abstract class LinphoneGenericActivity extends ThemeableActivity {
|
|||
if (!LinphoneContext.isReady()) {
|
||||
new LinphoneContext(getApplicationContext());
|
||||
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));
|
||||
} 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.os.Bundle;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.R;
|
||||
import org.linphone.assistant.MenuAssistantActivity;
|
||||
import org.linphone.chat.ChatActivity;
|
||||
import org.linphone.contacts.ContactsActivity;
|
||||
import org.linphone.dialer.DialerActivity;
|
||||
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.utils.ServiceWaitThread;
|
||||
import org.linphone.utils.ServiceWaitThreadListener;
|
||||
|
||||
/** Creates LinphoneService and wait until Core is ready to start main Activity */
|
||||
public class LinphoneLauncherActivity extends Activity implements ServiceWaitThreadListener {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.linphone.activities;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Dialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
|
@ -46,7 +45,6 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
|||
import java.util.ArrayList;
|
||||
import org.linphone.LinphoneContext;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.R;
|
||||
import org.linphone.call.CallActivity;
|
||||
import org.linphone.call.CallIncomingActivity;
|
||||
|
@ -66,6 +64,7 @@ import org.linphone.core.CoreListenerStub;
|
|||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.core.RegistrationState;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.dialer.DialerActivity;
|
||||
import org.linphone.fragments.EmptyFragment;
|
||||
import org.linphone.fragments.StatusBarFragment;
|
||||
import org.linphone.history.HistoryActivity;
|
||||
|
@ -74,7 +73,6 @@ import org.linphone.settings.LinphonePreferences;
|
|||
import org.linphone.settings.SettingsActivity;
|
||||
import org.linphone.utils.DeviceUtils;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.utils.PushNotificationUtils;
|
||||
|
||||
public abstract class MainActivity extends LinphoneGenericActivity
|
||||
implements StatusBarFragment.MenuClikedListener, SideMenuFragment.QuitClikedListener {
|
||||
|
@ -276,23 +274,6 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
|||
super.onStart();
|
||||
|
||||
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
|
||||
|
@ -443,10 +424,6 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
|||
|
||||
private void quit() {
|
||||
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
|
||||
|
@ -495,6 +472,14 @@ public abstract class MainActivity extends LinphoneGenericActivity
|
|||
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) {
|
||||
if (!checkPermission(permission)) {
|
||||
Log.i("[Permission] Requesting " + permission + " permission");
|
||||
|
|
|
@ -31,9 +31,11 @@ import android.widget.RelativeLayout;
|
|||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.core.AccountCreator;
|
||||
import org.linphone.core.AccountCreatorListenerStub;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.DialPlan;
|
||||
import org.linphone.core.tools.Log;
|
||||
|
||||
|
@ -70,20 +72,26 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
||||
AccountCreator accountCreator = getAccountCreator();
|
||||
accountCreator.reset();
|
||||
mConnect.setEnabled(false);
|
||||
|
||||
if (mUsernameConnectionSwitch.isChecked()) {
|
||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
||||
mAccountCreator.setPassword(mPassword.getText().toString());
|
||||
accountCreator.setUsername(mUsername.getText().toString());
|
||||
accountCreator.setPassword(mPassword.getText().toString());
|
||||
|
||||
createProxyConfigAndLeaveAssistant();
|
||||
} 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) {
|
||||
Log.e("[Account Connection] recoverAccount returned " + status);
|
||||
Log.e(
|
||||
"[Account Connection Assistant] recoverAccount returned "
|
||||
+ status);
|
||||
mConnect.setEnabled(true);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -202,7 +210,9 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void onRecoverAccount(
|
||||
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)) {
|
||||
Intent intent =
|
||||
new Intent(
|
||||
|
@ -222,7 +232,12 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mAccountCreator.addListener(mListener);
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core != null) {
|
||||
reloadLinphoneAccountCreatorConfig();
|
||||
}
|
||||
|
||||
getAccountCreator().addListener(mListener);
|
||||
|
||||
DialPlan dp = getDialPlanForCurrentCountry();
|
||||
displayDialPlan(dp);
|
||||
|
@ -236,7 +251,7 @@ public class AccountConnectionAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mAccountCreator.removeListener(mListener);
|
||||
getAccountCreator().removeListener(mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,16 +21,16 @@ package org.linphone.assistant;
|
|||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import java.util.Locale;
|
||||
import org.linphone.LinphoneContext;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.DialerActivity;
|
||||
import org.linphone.activities.LinphoneGenericActivity;
|
||||
import org.linphone.core.AccountCreator;
|
||||
import org.linphone.core.Core;
|
||||
|
@ -38,29 +38,16 @@ import org.linphone.core.DialPlan;
|
|||
import org.linphone.core.Factory;
|
||||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.dialer.DialerActivity;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
|
||||
public abstract class AssistantActivity extends LinphoneGenericActivity
|
||||
implements CountryPicker.CountryPickedListener {
|
||||
static AccountCreator mAccountCreator;
|
||||
|
||||
protected ImageView mBack;
|
||||
private AlertDialog mCountryPickerDialog;
|
||||
|
||||
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
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
@ -104,25 +91,78 @@ public abstract class AssistantActivity extends LinphoneGenericActivity
|
|||
}
|
||||
}
|
||||
|
||||
void createProxyConfigAndLeaveAssistant() {
|
||||
Core core = LinphoneManager.getCore();
|
||||
boolean useLinphoneDefaultValues =
|
||||
getString(R.string.default_domain).equals(mAccountCreator.getDomain());
|
||||
if (useLinphoneDefaultValues) {
|
||||
core.loadConfigFromXml(LinphonePreferences.instance().getLinphoneDynamicConfigFile());
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (!mBack.isEnabled()) return true;
|
||||
}
|
||||
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) {
|
||||
// Restore default values
|
||||
core.loadConfigFromXml(LinphonePreferences.instance().getDefaultDynamicConfigFile());
|
||||
Log.i("[Assistant] Restoring default assistant configuration");
|
||||
core.loadConfigFromXml(
|
||||
LinphonePreferences.instance().getDefaultDynamicConfigFile());
|
||||
} else {
|
||||
// If this isn't a sip.linphone.org account, disable push notifications and enable
|
||||
// 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);
|
||||
LinphoneContext.instance().getNotificationManager().startForeground();
|
||||
}
|
||||
}
|
||||
|
||||
if (proxyConfig == null) {
|
||||
Log.e("[Assistant] Account creator couldn't create proxy config");
|
||||
|
@ -206,6 +246,9 @@ public abstract class AssistantActivity extends LinphoneGenericActivity
|
|||
case PhoneNumberOverused:
|
||||
message = getString(R.string.phone_number_overuse);
|
||||
break;
|
||||
case AccountNotExist:
|
||||
message = getString(R.string.account_doesnt_exist);
|
||||
break;
|
||||
default:
|
||||
message = getString(R.string.error_unknown);
|
||||
break;
|
||||
|
@ -271,7 +314,7 @@ public abstract class AssistantActivity extends LinphoneGenericActivity
|
|||
}
|
||||
|
||||
String phoneNumber = phoneNumberEditText.getText().toString();
|
||||
return mAccountCreator.setPhoneNumber(phoneNumber, prefix);
|
||||
return getAccountCreator().setPhoneNumber(phoneNumber, prefix);
|
||||
}
|
||||
|
||||
String getErrorFromPhoneNumberStatus(int status) {
|
||||
|
|
|
@ -30,9 +30,11 @@ import android.view.View;
|
|||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.core.AccountCreator;
|
||||
import org.linphone.core.AccountCreatorListenerStub;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.tools.Log;
|
||||
|
||||
public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
||||
|
@ -65,7 +67,7 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
AccountCreator.UsernameStatus status =
|
||||
mAccountCreator.setUsername(s.toString());
|
||||
getAccountCreator().setUsername(s.toString());
|
||||
mUsernameError.setVisibility(
|
||||
status == AccountCreator.UsernameStatus.Ok
|
||||
? View.INVISIBLE
|
||||
|
@ -88,7 +90,7 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
AccountCreator.PasswordStatus status =
|
||||
mAccountCreator.setPassword(s.toString());
|
||||
getAccountCreator().setPassword(s.toString());
|
||||
mPasswordError.setVisibility(
|
||||
status == AccountCreator.PasswordStatus.Ok
|
||||
? View.INVISIBLE
|
||||
|
@ -146,7 +148,8 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
AccountCreator.EmailStatus status = mAccountCreator.setEmail(s.toString());
|
||||
AccountCreator.EmailStatus status =
|
||||
getAccountCreator().setEmail(s.toString());
|
||||
mEmailError.setVisibility(
|
||||
status == AccountCreator.EmailStatus.Ok
|
||||
? View.INVISIBLE
|
||||
|
@ -161,12 +164,13 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
enableButtonsAndFields(false);
|
||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
||||
|
||||
AccountCreator.Status status = mAccountCreator.isAccountExist();
|
||||
AccountCreator.Status status = getAccountCreator().isAccountExist();
|
||||
if (status != AccountCreator.Status.RequestOk) {
|
||||
enableButtonsAndFields(true);
|
||||
Log.e("[Email Account Creation] isAccountExists returned " + status);
|
||||
Log.e(
|
||||
"[Email Account Creation Assistant] isAccountExists returned "
|
||||
+ status);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
}
|
||||
|
@ -177,15 +181,19 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
new AccountCreatorListenerStub() {
|
||||
public void onIsAccountExist(
|
||||
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)
|
||||
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
|
||||
showAccountAlreadyExistsDialog();
|
||||
enableButtonsAndFields(true);
|
||||
} else if (status.equals(AccountCreator.Status.AccountNotExist)) {
|
||||
status = mAccountCreator.createAccount();
|
||||
status = getAccountCreator().createAccount();
|
||||
if (status != AccountCreator.Status.RequestOk) {
|
||||
Log.e("[Email Account Creation] createAccount returned " + status);
|
||||
Log.e(
|
||||
"[Email Account Creation Assistant] createAccount returned "
|
||||
+ status);
|
||||
enableButtonsAndFields(true);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -198,7 +206,9 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void onCreateAccount(
|
||||
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)) {
|
||||
startActivity(
|
||||
new Intent(
|
||||
|
@ -235,7 +245,12 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
protected void 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)) {
|
||||
Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
|
||||
|
@ -252,6 +267,6 @@ public class EmailAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void 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);
|
||||
|
||||
TextView email = findViewById(R.id.send_email);
|
||||
email.setText(mAccountCreator.getEmail());
|
||||
email.setText(getAccountCreator().getEmail());
|
||||
|
||||
mFinishCreation = findViewById(R.id.assistant_check);
|
||||
mFinishCreation.setOnClickListener(
|
||||
|
@ -50,9 +50,11 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
|||
public void onClick(View v) {
|
||||
mFinishCreation.setEnabled(false);
|
||||
|
||||
AccountCreator.Status status = mAccountCreator.isAccountActivated();
|
||||
AccountCreator.Status status = getAccountCreator().isAccountActivated();
|
||||
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);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -65,7 +67,7 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
|||
public void onIsAccountActivated(
|
||||
AccountCreator creator, AccountCreator.Status status, String resp) {
|
||||
Log.i(
|
||||
"[Email Account Validation] onIsAccountActivated status is "
|
||||
"[Email Account Validation Assistant] onIsAccountActivated status is "
|
||||
+ status);
|
||||
if (status.equals(AccountCreator.Status.AccountActivated)) {
|
||||
createProxyConfigAndLeaveAssistant();
|
||||
|
@ -87,7 +89,7 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mAccountCreator.addListener(mListener);
|
||||
getAccountCreator().addListener(mListener);
|
||||
|
||||
// Prevent user to go back, it won't be able to come back here after...
|
||||
mBack.setEnabled(false);
|
||||
|
@ -96,6 +98,6 @@ public class EmailAccountValidationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mAccountCreator.removeListener(mListener);
|
||||
getAccountCreator().removeListener(mListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,12 @@ import android.widget.EditText;
|
|||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.core.AccountCreator;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.TransportType;
|
||||
import org.linphone.core.tools.Log;
|
||||
|
||||
public class GenericConnectionAssistantActivity extends AssistantActivity implements TextWatcher {
|
||||
private TextView mLogin;
|
||||
|
@ -63,24 +67,31 @@ public class GenericConnectionAssistantActivity extends AssistantActivity implem
|
|||
}
|
||||
|
||||
private void configureAccount() {
|
||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
||||
mAccountCreator.setDomain(mDomain.getText().toString());
|
||||
mAccountCreator.setPassword(mPassword.getText().toString());
|
||||
mAccountCreator.setDisplayName(mDisplayName.getText().toString());
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core != null) {
|
||||
Log.i("[Generic Connection Assistant] Reloading configuration with default");
|
||||
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()) {
|
||||
case R.id.transport_udp:
|
||||
mAccountCreator.setTransport(TransportType.Udp);
|
||||
accountCreator.setTransport(TransportType.Udp);
|
||||
break;
|
||||
case R.id.transport_tcp:
|
||||
mAccountCreator.setTransport(TransportType.Tcp);
|
||||
accountCreator.setTransport(TransportType.Tcp);
|
||||
break;
|
||||
case R.id.transport_tls:
|
||||
mAccountCreator.setTransport(TransportType.Tls);
|
||||
accountCreator.setTransport(TransportType.Tls);
|
||||
break;
|
||||
}
|
||||
|
||||
createProxyConfigAndLeaveAssistant();
|
||||
createProxyConfigAndLeaveAssistant(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -58,7 +58,7 @@ public class OpenH264DownloadAssistantActivity extends AssistantActivity {
|
|||
public void onClick(View v) {
|
||||
mYes.setEnabled(false);
|
||||
mNo.setEnabled(false);
|
||||
Log.e("[OpenH264 Downloader] Start download");
|
||||
Log.e("[OpenH264 Downloader Assistant] Start download");
|
||||
mProgress.setVisibility(View.VISIBLE);
|
||||
mHelper.downloadCodec();
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class OpenH264DownloadAssistantActivity extends AssistantActivity {
|
|||
public void onClick(View v) {
|
||||
mYes.setEnabled(false);
|
||||
mNo.setEnabled(false);
|
||||
Log.e("[OpenH264 Downloader] Download refused");
|
||||
Log.e("[OpenH264 Downloader Assistant] Download refused");
|
||||
goToLinphoneActivity();
|
||||
}
|
||||
});
|
||||
|
@ -96,7 +96,7 @@ public class OpenH264DownloadAssistantActivity extends AssistantActivity {
|
|||
|
||||
@Override
|
||||
public void OnError(String s) {
|
||||
Log.e("[OpenH264 Downloader] " + s);
|
||||
Log.e("[OpenH264 Downloader Assistant] " + s);
|
||||
mYes.setEnabled(true);
|
||||
mNo.setEnabled(true);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,11 @@ import android.widget.EditText;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.core.AccountCreator;
|
||||
import org.linphone.core.AccountCreatorListenerStub;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.DialPlan;
|
||||
import org.linphone.core.tools.Log;
|
||||
|
||||
|
@ -67,18 +69,20 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AccountCreator accountCreator = getAccountCreator();
|
||||
enableButtonsAndFields(false);
|
||||
|
||||
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
||||
accountCreator.setUsername(mUsername.getText().toString());
|
||||
} 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) {
|
||||
Log.e("[Phone Account Creation] isAccountExists returned " + status);
|
||||
Log.e(
|
||||
"[Phone Account Creation Assistant] isAccountExists returned "
|
||||
+ status);
|
||||
enableButtonsAndFields(true);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -167,15 +171,19 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
new AccountCreatorListenerStub() {
|
||||
public void onIsAccountExist(
|
||||
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)
|
||||
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
|
||||
showAccountAlreadyExistsDialog();
|
||||
enableButtonsAndFields(true);
|
||||
} else if (status.equals(AccountCreator.Status.AccountNotExist)) {
|
||||
status = mAccountCreator.createAccount();
|
||||
status = getAccountCreator().createAccount();
|
||||
if (status != AccountCreator.Status.RequestOk) {
|
||||
Log.e("[Phone Account Creation] createAccount returned " + status);
|
||||
Log.e(
|
||||
"[Phone Account Creation Assistant] createAccount returned "
|
||||
+ status);
|
||||
enableButtonsAndFields(true);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -188,7 +196,9 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void onCreateAccount(
|
||||
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)) {
|
||||
startActivity(
|
||||
new Intent(
|
||||
|
@ -206,7 +216,12 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mAccountCreator.addListener(mListener);
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core != null) {
|
||||
reloadLinphoneAccountCreatorConfig();
|
||||
}
|
||||
|
||||
getAccountCreator().addListener(mListener);
|
||||
|
||||
DialPlan dp = getDialPlanForCurrentCountry();
|
||||
displayDialPlan(dp);
|
||||
|
@ -220,7 +235,7 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mAccountCreator.removeListener(mListener);
|
||||
getAccountCreator().removeListener(mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,7 +262,7 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) {
|
||||
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
||||
AccountCreator.UsernameStatus usernameStatus =
|
||||
mAccountCreator.setUsername(mUsername.getText().toString());
|
||||
getAccountCreator().setUsername(mUsername.getText().toString());
|
||||
if (usernameStatus != AccountCreator.UsernameStatus.Ok) {
|
||||
mCreate.setEnabled(false);
|
||||
mError.setText(getErrorFromUsernameStatus(usernameStatus));
|
||||
|
@ -264,7 +279,7 @@ public class PhoneAccountCreationAssistantActivity extends AssistantActivity {
|
|||
if (mUseUsernameInsteadOfPhoneNumber.isChecked()) {
|
||||
username = mUsername.getText().toString();
|
||||
} else {
|
||||
username = mAccountCreator.getPhoneNumber();
|
||||
username = getAccountCreator().getPhoneNumber();
|
||||
}
|
||||
|
||||
if (username != null) {
|
||||
|
|
|
@ -56,42 +56,50 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
|||
int proxyConfigIndex = getIntent().getExtras().getInt("AccountNumber");
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core == null) {
|
||||
Log.e("[Account Linking] Core not available");
|
||||
Log.e("[Account Linking Assistant] Core not available");
|
||||
unexpectedError();
|
||||
return;
|
||||
}
|
||||
|
||||
ProxyConfig[] proxyConfigs = core.getProxyConfigList();
|
||||
if (proxyConfigIndex >= 0 && proxyConfigIndex < proxyConfigs.length) {
|
||||
ProxyConfig mProxyConfig = proxyConfigs[proxyConfigIndex];
|
||||
AccountCreator accountCreator = getAccountCreator();
|
||||
|
||||
Address identity = mProxyConfig.getIdentityAddress();
|
||||
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();
|
||||
return;
|
||||
}
|
||||
if (!mProxyConfig.getDomain().equals(getString(R.string.default_domain))) {
|
||||
Log.e(
|
||||
"[Account Linking] Can't link account on domain "
|
||||
"[Account Linking Assistant] Can't link account on domain "
|
||||
+ mProxyConfig.getDomain());
|
||||
unexpectedError();
|
||||
return;
|
||||
}
|
||||
mAccountCreator.setUsername(identity.getUsername());
|
||||
accountCreator.setUsername(identity.getUsername());
|
||||
|
||||
AuthInfo authInfo = mProxyConfig.findAuthInfo();
|
||||
if (authInfo == null) {
|
||||
Log.e("[Account Linking] Auth info not found");
|
||||
Log.e("[Account Linking Assistant] Auth info not found");
|
||||
unexpectedError();
|
||||
return;
|
||||
}
|
||||
mAccountCreator.setHa1(authInfo.getHa1());
|
||||
|
||||
mAccountCreator.setDomain(getString(R.string.default_domain));
|
||||
accountCreator.setHa1(authInfo.getHa1());
|
||||
accountCreator.setAlgorithm((authInfo.getAlgorithm()));
|
||||
} 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();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Log.e("[Account Linking] Proxy config index not found");
|
||||
Log.e("[Account Linking Assistant] Proxy config index not found");
|
||||
unexpectedError();
|
||||
return;
|
||||
}
|
||||
|
||||
mCountryPicker = findViewById(R.id.select_country);
|
||||
|
@ -112,9 +120,11 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
|||
public void onClick(View v) {
|
||||
enableButtonsAndFields(false);
|
||||
|
||||
AccountCreator.Status status = mAccountCreator.isAliasUsed();
|
||||
AccountCreator.Status status = getAccountCreator().isAliasUsed();
|
||||
if (status != AccountCreator.Status.RequestOk) {
|
||||
Log.e("[Phone Account Linking] isAliasUsed returned " + status);
|
||||
Log.e(
|
||||
"[Phone Account Linking Assistant] isAliasUsed returned "
|
||||
+ status);
|
||||
enableButtonsAndFields(true);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -178,11 +188,15 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void onIsAliasUsed(
|
||||
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)) {
|
||||
status = mAccountCreator.linkAccount();
|
||||
status = getAccountCreator().linkAccount();
|
||||
if (status != AccountCreator.Status.RequestOk) {
|
||||
Log.e("[Phone Account Linking] linkAccount returned " + status);
|
||||
Log.e(
|
||||
"[Phone Account Linking Assistant] linkAccount returned "
|
||||
+ status);
|
||||
enableButtonsAndFields(true);
|
||||
showGenericErrorDialog(status);
|
||||
}
|
||||
|
@ -200,7 +214,9 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
public void onLinkAccount(
|
||||
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)) {
|
||||
Intent intent =
|
||||
new Intent(
|
||||
|
@ -220,7 +236,12 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mAccountCreator.addListener(mListener);
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core != null) {
|
||||
reloadLinphoneAccountCreatorConfig();
|
||||
}
|
||||
|
||||
getAccountCreator().addListener(mListener);
|
||||
|
||||
DialPlan dp = getDialPlanForCurrentCountry();
|
||||
displayDialPlan(dp);
|
||||
|
@ -234,7 +255,7 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mAccountCreator.removeListener(mListener);
|
||||
getAccountCreator().removeListener(mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,7 +40,7 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
|||
private ClipboardManager mClipboard;
|
||||
|
||||
private int mActivationCodeLength;
|
||||
private boolean mIsLinking;
|
||||
private boolean mIsLinking = false, mIsLogin = false;
|
||||
private AccountCreatorListenerStub mListener;
|
||||
|
||||
@Override
|
||||
|
@ -50,20 +50,21 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
|||
setContentView(R.layout.assistant_phone_account_validation);
|
||||
|
||||
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
|
||||
&& getIntent().getBooleanExtra("isLinkingVerification", false)) {
|
||||
mIsLinking = true;
|
||||
findViewById(R.id.title_account_linking).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.title_account_activation).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.title_account_creation).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
mActivationCodeLength =
|
||||
getResources().getInteger(R.integer.phone_number_validation_code_length);
|
||||
|
||||
TextView phoneNumber = findViewById(R.id.phone_number);
|
||||
phoneNumber.setText(mAccountCreator.getPhoneNumber());
|
||||
phoneNumber.setText(getAccountCreator().getPhoneNumber());
|
||||
|
||||
mSmsCode = findViewById(R.id.sms_code);
|
||||
mSmsCode.addTextChangedListener(
|
||||
|
@ -87,21 +88,27 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AccountCreator accountCreator = getAccountCreator();
|
||||
mFinishCreation.setEnabled(false);
|
||||
mAccountCreator.setActivationCode(mSmsCode.getText().toString());
|
||||
accountCreator.setActivationCode(mSmsCode.getText().toString());
|
||||
|
||||
AccountCreator.Status status;
|
||||
if (mIsLinking) {
|
||||
status = mAccountCreator.activateAlias();
|
||||
status = accountCreator.activateAlias();
|
||||
} else if (mIsLogin) {
|
||||
status = accountCreator.loginLinphoneAccount();
|
||||
} else {
|
||||
status = mAccountCreator.activateAccount();
|
||||
status = accountCreator.activateAccount();
|
||||
}
|
||||
if (status != AccountCreator.Status.RequestOk) {
|
||||
Log.e(
|
||||
"[Phone Account Validation] "
|
||||
+ (mIsLinking
|
||||
? "linkAccount"
|
||||
: "activateAccount" + " returned ")
|
||||
: (mIsLogin
|
||||
? "loginLinphoneAccount"
|
||||
: "activateAccount")
|
||||
+ " returned ")
|
||||
+ status);
|
||||
mFinishCreation.setEnabled(true);
|
||||
showGenericErrorDialog(status);
|
||||
|
@ -118,12 +125,7 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
|||
if (status.equals(AccountCreator.Status.AccountActivated)) {
|
||||
createProxyConfigAndLeaveAssistant();
|
||||
} else {
|
||||
mFinishCreation.setEnabled(true);
|
||||
showGenericErrorDialog(status);
|
||||
|
||||
if (status.equals(AccountCreator.Status.WrongActivationCode)) {
|
||||
// TODO do something so the server re-send a SMS
|
||||
}
|
||||
onError(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,13 +137,21 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
|||
LinphonePreferences.instance().setLinkPopupTime("");
|
||||
goToLinphoneActivity();
|
||||
} else {
|
||||
mFinishCreation.setEnabled(true);
|
||||
showGenericErrorDialog(status);
|
||||
|
||||
if (status.equals(AccountCreator.Status.WrongActivationCode)) {
|
||||
// TODO do something so the server re-send a SMS
|
||||
onError(status);
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mAccountCreator.addListener(mListener);
|
||||
getAccountCreator().addListener(mListener);
|
||||
|
||||
// Prevent user to go back, it won't be able to come back here after...
|
||||
mBack.setEnabled(false);
|
||||
|
@ -173,6 +183,15 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
|
|||
@Override
|
||||
protected void 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
|
||||
* 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.STREAM_RING;
|
||||
|
@ -54,8 +54,6 @@ import org.linphone.receivers.HeadsetReceiver;
|
|||
import org.linphone.settings.LinphonePreferences;
|
||||
|
||||
public class AndroidAudioManager {
|
||||
private static final int LINPHONE_VOLUME_STREAM = STREAM_VOICE_CALL;
|
||||
|
||||
private Context mContext;
|
||||
private AudioManager mAudioManager;
|
||||
private Call mRingingCall;
|
||||
|
@ -415,10 +413,22 @@ public class AndroidAudioManager {
|
|||
}
|
||||
|
||||
private void adjustVolume(int i) {
|
||||
// starting from ICS, volume must be adjusted by the application, at least for
|
||||
// STREAM_VOICE_CALL volume stream
|
||||
if (mAudioManager.isVolumeFixed()) {
|
||||
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(
|
||||
LINPHONE_VOLUME_STREAM,
|
||||
stream,
|
||||
i < 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_RAISE,
|
||||
AudioManager.FLAG_SHOW_UI);
|
||||
}
|
||||
|
@ -428,6 +438,7 @@ public class AndroidAudioManager {
|
|||
public synchronized void bluetoothHeadetConnectionChanged(boolean connected) {
|
||||
mIsBluetoothHeadsetConnected = connected;
|
||||
mAudioManager.setBluetoothScoOn(connected);
|
||||
LinphoneManager.getCallManager().refreshInCallActions();
|
||||
}
|
||||
|
||||
public synchronized void bluetoothHeadetAudioConnectionChanged(boolean connected) {
|
||||
|
@ -475,8 +486,10 @@ public class AndroidAudioManager {
|
|||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean resultAcknoledged;
|
||||
Log.i("[Audio Manager] [Bluetooth] SCO start/stop thread started");
|
||||
boolean resultAcknowledged;
|
||||
int retries = 0;
|
||||
|
||||
do {
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
|
@ -496,26 +509,17 @@ public class AndroidAudioManager {
|
|||
+ retries);
|
||||
mAudioManager.stopBluetoothSco();
|
||||
}
|
||||
resultAcknoledged = isUsingBluetoothAudioRoute() == enable;
|
||||
resultAcknowledged = isUsingBluetoothAudioRoute() == enable;
|
||||
retries++;
|
||||
}
|
||||
} while (!resultAcknoledged && retries < 10);
|
||||
} while (!resultAcknowledged && retries < 10);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
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 !");
|
||||
}
|
||||
public void bluetoothAdapterStateChanged() {
|
||||
if (mBluetoothAdapter.isEnabled()) {
|
||||
Log.i("[Audio Manager] [Bluetooth] Adapter enabled");
|
||||
mBluetoothReceiver = new BluetoothReceiver();
|
||||
mIsBluetoothHeadsetConnected = false;
|
||||
mIsBluetoothHeadsetScoConnected = false;
|
||||
|
||||
|
@ -534,19 +538,18 @@ public class AndroidAudioManager {
|
|||
bluetoothHeadetConnectionChanged(true);
|
||||
}
|
||||
|
||||
Log.i(
|
||||
"[Audio Manager] [Bluetooth] Registering bluetooth receiver");
|
||||
Log.i("[Audio Manager] [Bluetooth] Registering bluetooth receiver");
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
|
||||
filter.addAction(
|
||||
BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
|
||||
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
|
||||
filter.addAction(
|
||||
BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
|
||||
|
||||
Intent sticky =
|
||||
mContext.registerReceiver(mBluetoothReceiver, filter);
|
||||
Log.i("[Audio Manager] [Bluetooth] Bluetooth receiver registered");
|
||||
int state =
|
||||
sticky.getIntExtra(
|
||||
AudioManager.EXTRA_SCO_AUDIO_STATE,
|
||||
|
@ -575,18 +578,37 @@ public class AndroidAudioManager {
|
|||
|
||||
public void onServiceDisconnected(int profile) {
|
||||
if (profile == BluetoothProfile.HEADSET) {
|
||||
Log.i(
|
||||
"[Audio Manager] [Bluetooth] HEADSET profile disconnected");
|
||||
Log.i("[Audio Manager] [Bluetooth] HEADSET profile disconnected");
|
||||
mBluetoothHeadset = null;
|
||||
mIsBluetoothHeadsetConnected = false;
|
||||
mIsBluetoothHeadsetScoConnected = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mBluetoothAdapter.getProfileProxy(
|
||||
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
|
|
@ -48,16 +48,16 @@ import androidx.core.app.ActivityCompat;
|
|||
import androidx.core.content.ContextCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.DialerActivity;
|
||||
import org.linphone.activities.LinphoneGenericActivity;
|
||||
import org.linphone.chat.ChatActivity;
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.ContactsUpdatedListener;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.ChatMessage;
|
||||
|
@ -66,10 +66,10 @@ import org.linphone.core.Core;
|
|||
import org.linphone.core.CoreListener;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.dialer.DialerActivity;
|
||||
import org.linphone.service.LinphoneService;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.AndroidAudioManager;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class CallActivity extends LinphoneGenericActivity
|
||||
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 WRITE_EXTERNAL_STORAGE_FOR_RECORDING = 2;
|
||||
private static final int CAMERA_TO_ACCEPT_UPDATE = 3;
|
||||
private static final int ALL_PERMISSIONS = 4;
|
||||
|
||||
private static class HideControlsRunnable implements Runnable {
|
||||
private WeakReference<CallActivity> mWeakCallActivity;
|
||||
|
@ -306,13 +307,13 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
findViewById(R.id.numpad)
|
||||
.setVisibility(
|
||||
findViewById(R.id.numpad).getVisibility() == View.VISIBLE
|
||||
? View.GONE
|
||||
: View.VISIBLE);
|
||||
View numpad = findViewById(R.id.numpad);
|
||||
boolean isNumpadVisible = numpad.getVisibility() == View.VISIBLE;
|
||||
numpad.setVisibility(isNumpadVisible ? View.GONE : View.VISIBLE);
|
||||
v.setSelected(!isNumpadVisible);
|
||||
}
|
||||
});
|
||||
numpadButton.setSelected(false);
|
||||
|
||||
ImageView hangUp = findViewById(R.id.hang_up);
|
||||
hangUp.setOnClickListener(
|
||||
|
@ -387,6 +388,8 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
if (state == Call.State.End || state == Call.State.Released) {
|
||||
if (core.getCallsNb() == 0) {
|
||||
finish();
|
||||
} else {
|
||||
showVideoControls(false);
|
||||
}
|
||||
} else if (state == Call.State.PausedByRemote) {
|
||||
if (core.getCurrentCall() != null) {
|
||||
|
@ -437,6 +440,7 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
Call call = mCore.getCurrentCall();
|
||||
boolean videoEnabled =
|
||||
LinphonePreferences.instance().isVideoEnabled()
|
||||
&& call != null
|
||||
&& call.getCurrentParams().videoEnabled();
|
||||
|
||||
if (videoEnabled) {
|
||||
|
@ -451,6 +455,11 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
protected void 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();
|
||||
if (mCore != null) {
|
||||
mCore.setNativeVideoWindowId(mRemoteVideo);
|
||||
|
@ -557,11 +566,6 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (mAudioManager.onKeyVolumeAdjust(keyCode)) return true;
|
||||
|
@ -581,8 +585,21 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
public void onRequestPermissionsResult(
|
||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
// 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) {
|
||||
case CAMERA_TO_TOGGLE_VIDEO:
|
||||
LinphoneUtils.reloadVideoDevices();
|
||||
|
@ -600,6 +617,7 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPermission(String permission) {
|
||||
int granted = getPackageManager().checkPermission(permission, getPackageName());
|
||||
|
@ -620,6 +638,57 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
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
|
||||
public void onContactsUpdated() {
|
||||
setCurrentCallContactInformation();
|
||||
|
@ -825,6 +894,7 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
|
||||
boolean videoEnabled =
|
||||
LinphonePreferences.instance().isVideoEnabled()
|
||||
&& call != null
|
||||
&& call.getCurrentParams().videoEnabled();
|
||||
showVideoControls(videoEnabled);
|
||||
}
|
||||
|
@ -1024,7 +1094,7 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
mConferenceList.removeAllViews();
|
||||
|
||||
for (Call call : mCore.getCalls()) {
|
||||
if (call.getConference() != null) {
|
||||
if (call != null && call.getConference() != null) {
|
||||
if (mCore.isInConference()) {
|
||||
displayConferenceCall(call);
|
||||
conferenceDisplayed = true;
|
||||
|
@ -1032,11 +1102,16 @@ public class CallActivity extends LinphoneGenericActivity
|
|||
displayPausedConference();
|
||||
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);
|
||||
callThatIsNotCurrentFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCallsList.setVisibility(
|
||||
pausedConferenceDisplayed || callThatIsNotCurrentFound ? View.VISIBLE : View.GONE);
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.os.Bundle;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -36,9 +37,13 @@ import org.linphone.LinphoneContext;
|
|||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
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.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.Call.State;
|
||||
|
@ -47,10 +52,6 @@ import org.linphone.core.CoreListenerStub;
|
|||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
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 {
|
||||
private TextView mName, mNumber;
|
||||
|
@ -63,6 +64,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
Compatibility.setShowWhenLocked(this, true);
|
||||
Compatibility.setTurnScreenOn(this, true);
|
||||
|
||||
|
@ -122,13 +124,13 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
|||
Core core, Call call, State state, String message) {
|
||||
if (call == mCall) {
|
||||
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,
|
||||
// CallActivity.class));
|
||||
}
|
||||
}
|
||||
|
||||
if (LinphoneManager.getCore().getCallsNb() == 0) {
|
||||
if (state == State.End || state == State.Released) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -230,6 +232,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
|||
mAlreadyAcceptedOrDeniedCall = true;
|
||||
|
||||
mCall.terminate();
|
||||
finish();
|
||||
}
|
||||
|
||||
private void answer() {
|
||||
|
@ -276,8 +279,9 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
|
|||
Log.i("[Permission] Asking for read phone state");
|
||||
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
||||
}
|
||||
if (LinphonePreferences.instance().shouldInitiateVideoCall()
|
||||
|| LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
|
||||
if (LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()
|
||||
&& mCall != null
|
||||
&& mCall.getRemoteParams().videoEnabled()) {
|
||||
if (camera != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.i("[Permission] Asking for camera");
|
||||
permissionsList.add(Manifest.permission.CAMERA);
|
||||
|
|
|
@ -35,11 +35,11 @@ import org.linphone.core.Core;
|
|||
import org.linphone.core.MediaEncryption;
|
||||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.dialer.views.AddressType;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.FileUtils;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.AddressType;
|
||||
|
||||
/** Handle call updating, reinvites. */
|
||||
public class CallManager {
|
||||
|
@ -87,32 +87,26 @@ public class CallManager {
|
|||
|
||||
public void switchCamera() {
|
||||
Core core = LinphoneManager.getCore();
|
||||
try {
|
||||
if (core == null) return;
|
||||
|
||||
String currentDevice = core.getVideoDevice();
|
||||
Log.i("[Call Manager] Current camera device is " + currentDevice);
|
||||
|
||||
String[] devices = core.getVideoDevicesList();
|
||||
int index = 0;
|
||||
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;
|
||||
}
|
||||
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();
|
||||
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;
|
||||
}
|
||||
call.update(null);
|
||||
} catch (ArithmeticException ae) {
|
||||
Log.e("[Call Manager] [Video] Cannot switch camera: no camera");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean acceptCall(Call call) {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.linphone.R;
|
|||
import org.linphone.activities.LinphoneGenericActivity;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.Call.State;
|
||||
|
@ -46,7 +47,6 @@ import org.linphone.core.Reason;
|
|||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class CallOutgoingActivity extends LinphoneGenericActivity implements OnClickListener {
|
||||
private TextView mName, mNumber;
|
||||
|
@ -125,12 +125,12 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
|
|||
.show();
|
||||
}
|
||||
} 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,
|
||||
// CallActivity.class));
|
||||
}
|
||||
|
||||
if (LinphoneManager.getCore().getCallsNb() == 0) {
|
||||
if (state == State.End || state == State.Released) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -283,8 +283,7 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
|
|||
Log.i("[Permission] Asking for read phone state");
|
||||
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
|
||||
}
|
||||
if (LinphonePreferences.instance().shouldInitiateVideoCall()
|
||||
|| LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
|
||||
if (LinphonePreferences.instance().shouldInitiateVideoCall()) {
|
||||
if (camera != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.i("[Permission] Asking for camera");
|
||||
permissionsList.add(Manifest.permission.CAMERA);
|
||||
|
|
|
@ -29,9 +29,9 @@ import java.util.List;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class CallStatsAdapter extends BaseExpandableListAdapter {
|
||||
private final Context mContext;
|
||||
|
|
|
@ -55,8 +55,8 @@ public class CallStatsFragment extends Fragment {
|
|||
new CoreListenerStub() {
|
||||
@Override
|
||||
public void onCallStateChanged(
|
||||
Core lc, Call call, Call.State cstate, String message) {
|
||||
if (cstate == Call.State.End || cstate == Call.State.Error) {
|
||||
Core core, Call call, Call.State state, String message) {
|
||||
if (state == Call.State.End || state == Call.State.Error) {
|
||||
mAdapter.updateListItems(
|
||||
Arrays.asList(LinphoneManager.getCore().getCalls()));
|
||||
}
|
||||
|
|
|
@ -288,9 +288,19 @@ public class CallStatusBarFragment extends Fragment {
|
|||
|
||||
public void refreshStatusItems(final Call call) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
MediaEncryption mediaEncryption = call.getCurrentParams().getMediaEncryption();
|
||||
mEncryption.setVisibility(View.VISIBLE);
|
||||
|
||||
if (mediaEncryption == MediaEncryption.SRTP
|
||||
|| (mediaEncryption == MediaEncryption.ZRTP
|
||||
&& call.getAuthenticationTokenVerified())
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
|
@ -30,6 +30,8 @@ import org.linphone.core.Call;
|
|||
import org.linphone.core.CallLog;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.dialer.views.AddressAware;
|
||||
import org.linphone.dialer.views.AddressText;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
|
||||
@SuppressLint("AppCompatCustomView")
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
public interface CallIncomingButtonListener {
|
||||
void onAction();
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.view.WindowManager;
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.call.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
|
@ -20,6 +20,7 @@
|
|||
package org.linphone.chat;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
@ -258,7 +259,18 @@ public class ChatActivity extends MainActivity {
|
|||
ArrayList<ContactAddress> participants,
|
||||
String subject,
|
||||
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();
|
||||
if (peerAddress != null) {
|
||||
extras.putSerializable("RemoteSipUri", peerAddress.asStringUriOnly());
|
||||
|
|
|
@ -50,6 +50,7 @@ import java.util.List;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatMessage;
|
||||
import org.linphone.core.Content;
|
||||
|
@ -57,7 +58,6 @@ import org.linphone.core.tools.Log;
|
|||
import org.linphone.utils.FileUtils;
|
||||
import org.linphone.utils.ImageUtils;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
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;
|
||||
|
||||
public final CheckBox delete;
|
||||
public boolean isEditionEnabled;
|
||||
|
||||
private Context mContext;
|
||||
private ChatMessageViewHolderClickListener mListener;
|
||||
|
@ -275,8 +276,12 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isEditionEnabled) {
|
||||
ChatMessageViewHolder.this.onClick(v);
|
||||
} else {
|
||||
openFile(filePath);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
downloadOrCancel.setVisibility(View.VISIBLE);
|
||||
|
@ -315,6 +320,9 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isEditionEnabled) {
|
||||
ChatMessageViewHolder.this.onClick(v);
|
||||
} else {
|
||||
Content c = (Content) v.getTag();
|
||||
if (!message.isFileTransferInProgress()) {
|
||||
message.downloadContent(c);
|
||||
|
@ -322,6 +330,7 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
|||
message.cancelFileTransfer();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.w(
|
||||
|
|
|
@ -119,6 +119,7 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
|
|||
holder.bubbleLayout.setVisibility(View.GONE);
|
||||
holder.sendInProgress.setVisibility(View.GONE);
|
||||
|
||||
holder.isEditionEnabled = isEditionEnabled();
|
||||
if (isEditionEnabled()) {
|
||||
holder.delete.setVisibility(View.VISIBLE);
|
||||
holder.delete.setChecked(isSelected(position));
|
||||
|
|
|
@ -349,7 +349,7 @@ public class ChatMessagesFragment extends Fragment
|
|||
new CoreListenerStub() {
|
||||
@Override
|
||||
public void onCallStateChanged(
|
||||
Core lc, Call call, Call.State state, String message) {
|
||||
Core core, Call call, Call.State state, String message) {
|
||||
displayChatRoomHeader();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,12 +43,14 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||
import org.linphone.contacts.ContactAddress;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.ContactsUpdatedListener;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.SearchContactViewHolder;
|
||||
import org.linphone.contacts.SearchContactsAdapter;
|
||||
import org.linphone.contacts.views.ContactSelectView;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatRoom;
|
||||
import org.linphone.core.ChatRoomBackend;
|
||||
|
@ -61,8 +63,6 @@ import org.linphone.core.ProxyConfig;
|
|||
import org.linphone.core.SearchResult;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.views.ContactSelectView;
|
||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
||||
|
||||
public class ChatRoomCreationFragment extends Fragment
|
||||
implements View.OnClickListener,
|
||||
|
@ -143,8 +143,8 @@ public class ChatRoomCreationFragment extends Fragment
|
|||
if (mChatRoomAddress == null && mChatRoomSubject == null) {
|
||||
mContactsSelectedLayout.removeAllViews();
|
||||
} else {
|
||||
// Pop the back stack twice so we don't have in stack Group -> Creation
|
||||
// -> Group
|
||||
// Pop the back stack twice so we don't have in stack
|
||||
// Group -> Creation -> Group
|
||||
getFragmentManager().popBackStack();
|
||||
getFragmentManager().popBackStack();
|
||||
}
|
||||
|
@ -448,7 +448,10 @@ public class ChatRoomCreationFragment extends Fragment
|
|||
mChatRoom.getLocalAddress(), mChatRoom.getPeerAddress());
|
||||
}
|
||||
} 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) {
|
||||
// Pop back stack so back button takes to the chat rooms list
|
||||
getFragmentManager().popBackStack();
|
||||
|
|
|
@ -28,6 +28,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatMessage;
|
||||
import org.linphone.core.ChatRoom;
|
||||
|
@ -35,7 +36,6 @@ import org.linphone.core.ChatRoomCapabilities;
|
|||
import org.linphone.core.Content;
|
||||
import org.linphone.core.Participant;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class ChatRoomViewHolder extends RecyclerView.ViewHolder
|
||||
implements View.OnClickListener, View.OnLongClickListener {
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.util.List;
|
|||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.MainActivity;
|
||||
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.ContactsUpdatedListener;
|
||||
import org.linphone.core.ChatMessage;
|
||||
|
@ -44,7 +45,6 @@ import org.linphone.core.Core;
|
|||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.utils.SelectableHelper;
|
||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
||||
|
||||
public class ChatRoomsFragment extends Fragment
|
||||
implements ContactsUpdatedListener,
|
||||
|
@ -108,7 +108,7 @@ public class ChatRoomsFragment extends Fragment
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
((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
|
||||
public void onClick(View v) {
|
||||
((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
|
||||
public void onMessageReceived(Core core, ChatRoom cr, ChatMessage message) {
|
||||
refreshChatRoom(cr);
|
||||
public void onMessageReceived(Core core, ChatRoom room, ChatMessage message) {
|
||||
refreshChatRoom(room);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChatRoomSubjectChanged(Core core, ChatRoom room) {
|
||||
refreshChatRoom(room);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -154,9 +159,10 @@ public class ChatRoomsFragment extends Fragment
|
|||
|
||||
@Override
|
||||
public void onChatRoomStateChanged(
|
||||
Core core, ChatRoom cr, ChatRoom.State state) {
|
||||
Core core, ChatRoom room, ChatRoom.State state) {
|
||||
if (state == ChatRoom.State.Created) {
|
||||
refreshChatRoom(cr);
|
||||
refreshChatRoom(room);
|
||||
scrollToTop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -253,6 +259,9 @@ public class ChatRoomsFragment extends Fragment
|
|||
mWaitLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
((ChatActivity) getActivity()).displayMissedChats();
|
||||
|
||||
if (getResources().getBoolean(R.bool.isTablet))
|
||||
((ChatActivity) getActivity()).showEmptyChildFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -263,6 +272,10 @@ public class ChatRoomsFragment extends Fragment
|
|||
}
|
||||
}
|
||||
|
||||
private void scrollToTop() {
|
||||
mChatRoomsList.getLayoutManager().scrollToPosition(0);
|
||||
}
|
||||
|
||||
private void refreshChatRoom(ChatRoom cr) {
|
||||
ChatRoomViewHolder holder = (ChatRoomViewHolder) cr.getUserData();
|
||||
if (holder != null) {
|
||||
|
|
|
@ -29,12 +29,12 @@ import java.util.List;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatRoomSecurityLevel;
|
||||
import org.linphone.core.Participant;
|
||||
import org.linphone.core.ParticipantDevice;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
class DevicesAdapter extends BaseExpandableListAdapter {
|
||||
private final Context mContext;
|
||||
|
|
|
@ -26,16 +26,12 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatRoom;
|
||||
import org.linphone.core.ChatRoomCapabilities;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.Factory;
|
||||
import org.linphone.core.Participant;
|
||||
|
@ -43,7 +39,6 @@ import org.linphone.core.ParticipantDevice;
|
|||
import org.linphone.utils.LinphoneUtils;
|
||||
|
||||
public class DevicesFragment extends Fragment {
|
||||
private TextView mTitle;
|
||||
private ExpandableListView mExpandableList;
|
||||
private DevicesAdapter mAdapter;
|
||||
|
||||
|
@ -114,9 +109,6 @@ public class DevicesFragment extends Fragment {
|
|||
|
||||
initChatRoom();
|
||||
|
||||
mTitle = view.findViewById(R.id.title);
|
||||
initHeader();
|
||||
|
||||
ImageView backButton = view.findViewById(R.id.back);
|
||||
backButton.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
|
@ -146,24 +138,6 @@ public class DevicesFragment extends Fragment {
|
|||
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() {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = new DevicesAdapter(getActivity());
|
||||
|
|
|
@ -30,9 +30,9 @@ import org.linphone.LinphoneContext;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactAddress;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.ChatRoom;
|
||||
import org.linphone.core.Participant;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoViewHolder> {
|
||||
private List<ContactAddress> mItems;
|
||||
|
|
|
@ -23,7 +23,6 @@ import static android.content.Context.INPUT_METHOD_SERVICE;
|
|||
|
||||
import android.app.Dialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
@ -42,6 +41,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import java.util.ArrayList;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||
import org.linphone.contacts.ContactAddress;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
|
@ -56,7 +56,6 @@ import org.linphone.core.Factory;
|
|||
import org.linphone.core.Participant;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
||||
|
||||
public class GroupInfoFragment extends Fragment {
|
||||
private ImageView mConfirmButton;
|
||||
|
@ -146,7 +145,11 @@ public class GroupInfoFragment extends Fragment {
|
|||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (mIsAlreadyCreatedGroup) {
|
||||
((ChatActivity) getActivity()).goBack();
|
||||
} else {
|
||||
goBackToChatCreationFragment();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -262,6 +265,16 @@ public class GroupInfoFragment extends Fragment {
|
|||
public void onSubjectChanged(ChatRoom cr, EventLog event_log) {
|
||||
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) {
|
||||
|
@ -300,26 +313,14 @@ public class GroupInfoFragment extends Fragment {
|
|||
}
|
||||
|
||||
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())
|
||||
.showChatRoomCreation(
|
||||
mGroupChatRoomAddress,
|
||||
mParticipants,
|
||||
mSubject,
|
||||
mIsEncryptionEnabled,
|
||||
true);
|
||||
}
|
||||
true,
|
||||
!mIsAlreadyCreatedGroup);
|
||||
}
|
||||
|
||||
private void refreshParticipantsList() {
|
||||
|
@ -485,7 +486,9 @@ public class GroupInfoFragment extends Fragment {
|
|||
}
|
||||
Address[] participantsToAdd = new Address[toAdd.size()];
|
||||
toAdd.toArray(participantsToAdd);
|
||||
mChatRoom.addParticipants(participantsToAdd);
|
||||
if (!mChatRoom.addParticipants(participantsToAdd)) {
|
||||
// TODO error
|
||||
}
|
||||
// Pop back stack to go back to the Messages fragment
|
||||
getFragmentManager().popBackStack();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.linphone.LinphoneManager;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatMessage;
|
||||
import org.linphone.core.ChatMessageListenerStub;
|
||||
|
@ -40,7 +41,6 @@ import org.linphone.core.Core;
|
|||
import org.linphone.core.Factory;
|
||||
import org.linphone.core.ParticipantImdnState;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class ImdnFragment extends Fragment {
|
||||
private LayoutInflater mInflater;
|
||||
|
|
|
@ -140,7 +140,6 @@ class ApiTwentyFourPlus {
|
|||
return new Notification.Builder(context)
|
||||
.setStyle(new Notification.DecoratedCustomViewStyle())
|
||||
.setSmallIcon(R.drawable.topbar_call_notification)
|
||||
.setLargeIcon(contactIcon)
|
||||
.setContentTitle(contactName)
|
||||
.setContentText(context.getString(R.string.incall_notif_incoming))
|
||||
.setContentIntent(intent)
|
||||
|
|
|
@ -183,7 +183,7 @@ class ApiTwentyOnePlus {
|
|||
}
|
||||
|
||||
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)
|
||||
.setContentTitle(title)
|
||||
|
@ -201,6 +201,7 @@ class ApiTwentyOnePlus {
|
|||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setShowWhen(true)
|
||||
.setNumber(count)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ class ApiTwentySixPlus {
|
|||
CharSequence name = context.getString(R.string.content_title_notification_service);
|
||||
String description = context.getString(R.string.content_title_notification_service);
|
||||
NotificationChannel channel =
|
||||
new NotificationChannel(id, name, NotificationManager.IMPORTANCE_NONE);
|
||||
new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
|
||||
channel.setDescription(description);
|
||||
channel.enableVibration(false);
|
||||
channel.enableLights(false);
|
||||
|
@ -191,7 +191,6 @@ class ApiTwentySixPlus {
|
|||
context, context.getString(R.string.notification_channel_id))
|
||||
.setStyle(new Notification.DecoratedCustomViewStyle())
|
||||
.setSmallIcon(R.drawable.topbar_call_notification)
|
||||
.setLargeIcon(contactIcon)
|
||||
.setContentTitle(contactName)
|
||||
.setContentText(context.getString(R.string.incall_notif_incoming))
|
||||
.setContentIntent(intent)
|
||||
|
@ -255,7 +254,7 @@ class ApiTwentySixPlus {
|
|||
}
|
||||
|
||||
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, context.getString(R.string.notification_channel_id))
|
||||
.setContentTitle(title)
|
||||
|
@ -269,6 +268,7 @@ class ApiTwentySixPlus {
|
|||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setShowWhen(true)
|
||||
.setNumber(count)
|
||||
.setColor(context.getColor(R.color.notification_led_color))
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.annotation.TargetApi;
|
|||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.core.Address;
|
||||
|
@ -111,4 +112,8 @@ class ApiTwentyThreePlus {
|
|||
|
||||
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.FragmentTransaction;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.ContentProviderClient;
|
||||
|
@ -30,6 +31,7 @@ import android.content.Intent;
|
|||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.notifications.Notifiable;
|
||||
|
@ -103,11 +105,12 @@ public class Compatibility {
|
|||
}
|
||||
|
||||
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)) {
|
||||
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(
|
||||
|
@ -308,4 +311,12 @@ public class Compatibility {
|
|||
}
|
||||
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.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract;
|
||||
|
@ -30,6 +31,8 @@ import android.provider.ContactsContract.CommonDataKinds;
|
|||
import android.provider.ContactsContract.Contacts;
|
||||
import android.provider.ContactsContract.Data;
|
||||
import android.provider.ContactsContract.RawContacts;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import org.linphone.LinphoneContext;
|
||||
|
@ -41,10 +44,12 @@ class AndroidContact implements Serializable {
|
|||
private String mAndroidRawId;
|
||||
private boolean isAndroidRawIdLinphone;
|
||||
private final transient ArrayList<ContentProviderOperation> mChangesToCommit;
|
||||
private byte[] mTempPicture;
|
||||
|
||||
AndroidContact() {
|
||||
mChangesToCommit = new ArrayList<>();
|
||||
isAndroidRawIdLinphone = false;
|
||||
mTempPicture = null;
|
||||
}
|
||||
|
||||
String getAndroidId() {
|
||||
|
@ -78,6 +83,12 @@ class AndroidContact implements Serializable {
|
|||
String rawId = String.valueOf(ContentUris.parseId(results[0].uri));
|
||||
if (mAndroidId == null) {
|
||||
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 =
|
||||
new String[] {ContactsContract.RawContacts.CONTACT_ID};
|
||||
|
@ -146,6 +157,7 @@ class AndroidContact implements Serializable {
|
|||
}
|
||||
|
||||
void deleteAndroidContact() {
|
||||
Log.i("[Contact] Deleting Android contact ", this);
|
||||
ContactsManager.getInstance().delete(mAndroidId);
|
||||
}
|
||||
|
||||
|
@ -550,33 +562,44 @@ class AndroidContact implements Serializable {
|
|||
return;
|
||||
}
|
||||
|
||||
if (mAndroidId == null) {
|
||||
Log.i("[Contact] Setting picture to new contact.");
|
||||
addChangesToCommit(
|
||||
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());
|
||||
if (mAndroidRawId == null) {
|
||||
Log.w("[Contact] Can't set picture for not already created contact, will do it later");
|
||||
mTempPicture = photo;
|
||||
} else {
|
||||
Log.i(
|
||||
"[Contact] Setting picture to existing contact "
|
||||
+ mAndroidId
|
||||
+ " ("
|
||||
+ mAndroidRawId
|
||||
+ ")");
|
||||
addChangesToCommit(
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
||||
.withValue(ContactsContract.Data.RAW_CONTACT_ID, mAndroidRawId)
|
||||
.withValue(
|
||||
ContactsContract.Data.MIMETYPE,
|
||||
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
|
||||
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
|
||||
.withValue(ContactsContract.Data.IS_PRIMARY, 1)
|
||||
.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
|
||||
.build());
|
||||
"[Contact] Setting picture to an already created raw contact [",
|
||||
mAndroidRawId,
|
||||
"]");
|
||||
try {
|
||||
long rawId = Long.parseLong(mAndroidRawId);
|
||||
|
||||
Uri rawContactPhotoUri =
|
||||
Uri.withAppendedPath(
|
||||
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawId),
|
||||
RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
|
||||
|
||||
if (rawContactPhotoUri != null) {
|
||||
ContentResolver resolver =
|
||||
LinphoneContext.instance().getApplicationContext().getContentResolver();
|
||||
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) {
|
||||
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<>();
|
||||
AsyncContactsData data = new AsyncContactsData();
|
||||
List<String> nativeIds = new ArrayList<>();
|
||||
|
@ -111,10 +96,12 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
|||
|
||||
LinphoneContact contact = (LinphoneContact) friend.getUserData();
|
||||
if (contact != null) {
|
||||
contact.clearAddresses();
|
||||
if (contact.getAndroidId() != null) {
|
||||
contact.clearAddresses();
|
||||
androidContactsCache.put(contact.getAndroidId(), contact);
|
||||
nativeIds.add(contact.getAndroidId());
|
||||
} else {
|
||||
data.contacts.add(contact);
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
Log.i("[Contacts Manager] Found " + c.getCount() + " entries in cursor");
|
||||
while (c.moveToNext()) {
|
||||
|
@ -142,6 +144,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
|||
return data;
|
||||
}
|
||||
|
||||
try {
|
||||
String id = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
|
||||
boolean starred =
|
||||
c.getInt(c.getColumnIndex(ContactsContract.Contacts.STARRED)) == 1;
|
||||
|
@ -161,8 +164,14 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
|||
}
|
||||
|
||||
contact.syncValuesFromAndroidCusor(c);
|
||||
} catch (IllegalStateException ise) {
|
||||
Log.e(
|
||||
"[Contacts Manager] Couldn't get values from cursor, exception: ",
|
||||
ise);
|
||||
}
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
FriendList[] friendLists = core.getFriendsLists();
|
||||
for (FriendList list : friendLists) {
|
||||
|
@ -188,7 +197,13 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
|
|||
}
|
||||
|
||||
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) {
|
||||
if (isCancelled()) {
|
||||
Log.w("[Contacts Manager] Task cancelled");
|
||||
|
|
|
@ -36,6 +36,7 @@ import android.widget.TableLayout;
|
|||
import android.widget.TextView;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.ChatRoom;
|
||||
import org.linphone.core.ChatRoomBackend;
|
||||
|
@ -50,7 +51,6 @@ import org.linphone.core.ProxyConfig;
|
|||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class ContactDetailsFragment extends Fragment implements ContactsUpdatedListener {
|
||||
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);
|
||||
deleteContact.setOnClickListener(
|
||||
new OnClickListener() {
|
||||
|
@ -359,6 +364,8 @@ public class ContactDetailsFragment extends Fragment implements ContactsUpdatedL
|
|||
|
||||
private void goToChat(String tag, boolean isSecured) {
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core == null) return;
|
||||
|
||||
Address participant = Factory.instance().createAddress(tag);
|
||||
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.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.ExifInterface;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.ContactsContract.DisplayPhoto;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
|
@ -53,12 +52,13 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.linphone.R;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.mediastream.Version;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.FileUtils;
|
||||
import org.linphone.utils.ImageUtils;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class ContactEditorFragment extends Fragment {
|
||||
private static final int ADD_PHOTO = 1337;
|
||||
|
@ -136,12 +136,15 @@ public class ContactEditorFragment extends Fragment {
|
|||
if (mIsNewContact) {
|
||||
boolean areAllFielsEmpty = true;
|
||||
for (LinphoneNumberOrAddress nounoa : mNumbersAndAddresses) {
|
||||
if (nounoa.getValue() != null && !nounoa.getValue().equals("")) {
|
||||
String value = nounoa.getValue();
|
||||
if (value != null && !value.trim().isEmpty()) {
|
||||
areAllFielsEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (areAllFielsEmpty) {
|
||||
Log.i(
|
||||
"[Contact Editor] All SIP and phone fields are empty, aborting");
|
||||
getFragmentManager().popBackStackImmediate();
|
||||
return;
|
||||
}
|
||||
|
@ -154,37 +157,36 @@ public class ContactEditorFragment extends Fragment {
|
|||
true);
|
||||
|
||||
if (mPhotoToAdd != null) {
|
||||
Log.i("[Contact Editor] Found picture to set to contact");
|
||||
mContact.setPhoto(mPhotoToAdd);
|
||||
}
|
||||
|
||||
for (LinphoneNumberOrAddress noa : mNumbersAndAddresses) {
|
||||
if (noa.getValue() == null || noa.getValue().isEmpty()) {
|
||||
if (noa.getOldValue() != null && !noa.getOldValue().isEmpty()) {
|
||||
Log.i("[Contact Editor] Removing number " + noa.getOldValue());
|
||||
String value = noa.getValue();
|
||||
String oldValue = noa.getOldValue();
|
||||
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
if (oldValue != null && !oldValue.isEmpty()) {
|
||||
Log.i("[Contact Editor] Removing number: ", oldValue);
|
||||
mContact.removeNumberOrAddress(noa);
|
||||
}
|
||||
} else {
|
||||
if (noa.getOldValue() != null
|
||||
&& noa.getOldValue().equals(noa.getValue())) {
|
||||
Log.i(
|
||||
"[Contact Editor] Keeping existing number "
|
||||
+ noa.getValue());
|
||||
if (oldValue != null && oldValue.equals(value)) {
|
||||
Log.i("[Contact Editor] Keeping existing number: ", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (noa.isSIPAddress()) {
|
||||
|
||||
noa.setValue(
|
||||
LinphoneUtils.getFullAddressFromUsername(
|
||||
noa.getValue()));
|
||||
noa.setValue(LinphoneUtils.getFullAddressFromUsername(value));
|
||||
}
|
||||
Log.i("[Contact Editor] Adding new number " + noa.getValue());
|
||||
Log.i("[Contact Editor] Adding new number: ", value);
|
||||
|
||||
mContact.addOrUpdateNumberOrAddress(noa);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mOrganization.getText().toString().isEmpty() || !mIsNewContact) {
|
||||
Log.i("[Contact Editor] Setting organization field: ", mOrganization);
|
||||
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
|
||||
// list: contacts content observer may not be notified if contacts sync
|
||||
// is disabled at system level
|
||||
Log.i(
|
||||
"[Contact Editor] New contact created, starting fetch contacts task");
|
||||
ContactsManager.getInstance().fetchContactsAsync();
|
||||
}
|
||||
|
||||
|
@ -306,9 +310,18 @@ public class ContactEditorFragment extends Fragment {
|
|||
new OnClickListener() {
|
||||
@Override
|
||||
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();
|
||||
((ContactsActivity) getActivity())
|
||||
.requestPermissionIfNotGranted(Manifest.permission.CAMERA);
|
||||
} else {
|
||||
contactsActivity.requestPermissionsIfNotGranted(permissions);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -386,15 +399,18 @@ public class ContactEditorFragment extends Fragment {
|
|||
editContactPicture(null, bm);
|
||||
} else if (data != null && data.getData() != null) {
|
||||
Uri selectedImageUri = data.getData();
|
||||
String filePath = FileUtils.getRealPathFromURI(getActivity(), selectedImageUri);
|
||||
if (filePath != null) {
|
||||
editContactPicture(filePath, null);
|
||||
} else {
|
||||
try {
|
||||
Bitmap selectedImage =
|
||||
MediaStore.Images.Media.getBitmap(
|
||||
getActivity().getContentResolver(), selectedImageUri);
|
||||
selectedImage =
|
||||
Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false);
|
||||
editContactPicture(null, selectedImage);
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
Log.e("[Contact Editor] IO error: ", e);
|
||||
}
|
||||
}
|
||||
} else if (mPickedPhotoForContactUri != null) {
|
||||
String filePath = mPickedPhotoForContactUri.getPath();
|
||||
|
@ -426,11 +442,13 @@ public class ContactEditorFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
if (mPhotoToAdd == null) {
|
||||
if (mContact != null) {
|
||||
ContactAvatar.displayAvatar(mContact, mView.findViewById(R.id.avatar_layout));
|
||||
} else {
|
||||
ContactAvatar.displayAvatar("", mView.findViewById(R.id.avatar_layout));
|
||||
}
|
||||
}
|
||||
|
||||
mSipAddresses = initSipAddressFields(mContact);
|
||||
mNumbers = initNumbersFields(mContact);
|
||||
|
@ -438,27 +456,24 @@ public class ContactEditorFragment extends Fragment {
|
|||
|
||||
private void pickImage() {
|
||||
mPickedPhotoForContactUri = null;
|
||||
final List<Intent> cameraIntents = new ArrayList<>();
|
||||
final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
List<Intent> cameraIntents = new ArrayList<>();
|
||||
|
||||
// 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 =
|
||||
new File(
|
||||
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);
|
||||
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);
|
||||
cameraIntents.add(captureIntent);
|
||||
|
||||
final Intent galleryIntent = new Intent();
|
||||
galleryIntent.setType("image/*");
|
||||
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
|
||||
final Intent chooserIntent =
|
||||
Intent chooserIntent =
|
||||
Intent.createChooser(galleryIntent, getString(R.string.image_picker_title));
|
||||
chooserIntent.putExtra(
|
||||
Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {}));
|
||||
|
@ -467,44 +482,59 @@ public class ContactEditorFragment extends Fragment {
|
|||
}
|
||||
|
||||
private void editContactPicture(String filePath, Bitmap image) {
|
||||
int orientation = ExifInterface.ORIENTATION_NORMAL;
|
||||
|
||||
if (image == null) {
|
||||
Log.i(
|
||||
"[Contact Editor] Bitmap is null, trying to decode image from file [",
|
||||
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;
|
||||
int size = getThumbnailSize();
|
||||
if (size > 0) {
|
||||
scaledPhoto = Bitmap.createScaledBitmap(image, size, size, false);
|
||||
} else {
|
||||
scaledPhoto = Bitmap.createBitmap(image);
|
||||
switch (orientation) {
|
||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||
image = ImageUtils.rotateImage(image, 90);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||
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();
|
||||
scaledPhoto.compress(Bitmap.CompressFormat.PNG, 0, stream);
|
||||
mContactPicture.setImageBitmap(scaledPhoto);
|
||||
image.compress(Bitmap.CompressFormat.JPEG, 100, stream);
|
||||
mPhotoToAdd = stream.toByteArray();
|
||||
}
|
||||
|
||||
private int getThumbnailSize() {
|
||||
int value = -1;
|
||||
Cursor c =
|
||||
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;
|
||||
Bitmap roundPicture = ImageUtils.getRoundBitmap(image);
|
||||
ContactAvatar.displayAvatar(roundPicture, mView.findViewById(R.id.avatar_layout));
|
||||
image.recycle();
|
||||
}
|
||||
|
||||
private LinearLayout initNumbersFields(final LinphoneContact contact) {
|
||||
|
|
|
@ -102,6 +102,15 @@ public class ContactsActivity extends MainActivity {
|
|||
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
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
|
|
@ -31,10 +31,10 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.linphone.R;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.SelectableAdapter;
|
||||
import org.linphone.utils.SelectableHelper;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class ContactsAdapter extends SelectableAdapter<ContactViewHolder>
|
||||
implements SectionIndexer {
|
||||
|
|
|
@ -39,8 +39,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||
import org.linphone.utils.SelectableHelper;
|
||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
||||
|
||||
public class ContactsFragment extends Fragment
|
||||
implements OnItemClickListener,
|
||||
|
|
|
@ -55,7 +55,8 @@ import org.linphone.core.ProxyConfig;
|
|||
import org.linphone.core.tools.Log;
|
||||
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 final ArrayList<ContactsUpdatedListener> mContactsUpdatedListeners;
|
||||
private MagicSearch mMagicSearch;
|
||||
|
@ -79,6 +80,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
mMagicSearch = LinphoneManager.getCore().createMagicSearch();
|
||||
mMagicSearch.setLimitedSearch(false); // Do not limit the number of results
|
||||
}
|
||||
|
||||
LinphoneContext.instance().addCoreStartedListener(this);
|
||||
}
|
||||
|
||||
public void addContactsListener(ContactsUpdatedListener listener) {
|
||||
|
@ -104,6 +107,13 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
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() {
|
||||
return mContacts;
|
||||
}
|
||||
|
@ -122,6 +132,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
|
||||
public void destroy() {
|
||||
mContext.getContentResolver().unregisterContentObserver(this);
|
||||
LinphoneContext.instance().removeCoreStartedListener(this);
|
||||
|
||||
if (mLoadContactTask != null) {
|
||||
mLoadContactTask.cancel(true);
|
||||
|
@ -149,10 +160,12 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
if (mLoadContactTask != null) {
|
||||
mLoadContactTask.cancel(true);
|
||||
}
|
||||
|
||||
if (!hasReadContactsAccess()) {
|
||||
Log.w("[Contacts Manager] Can't fetch contact without READ permission");
|
||||
return;
|
||||
Log.w(
|
||||
"[Contacts Manager] Can't fetch native contacts without READ_CONTACTS permission");
|
||||
}
|
||||
|
||||
mLoadContactTask = new AsyncContactsLoader(mContext);
|
||||
mContactsFetchedOnce = true;
|
||||
mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
|
@ -212,6 +225,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
if (mContext == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean contactsR =
|
||||
(PackageManager.PERMISSION_GRANTED
|
||||
== mContext.getPackageManager()
|
||||
|
@ -226,6 +240,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
if (mContext == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (PackageManager.PERMISSION_GRANTED
|
||||
== mContext.getPackageManager()
|
||||
.checkPermission(
|
||||
|
@ -236,6 +251,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
if (mContext == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (PackageManager.PERMISSION_GRANTED
|
||||
== mContext.getPackageManager()
|
||||
.checkPermission(
|
||||
|
@ -264,10 +280,6 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mContext != null && getContacts().isEmpty() && hasReadContactsAccess()) {
|
||||
fetchContactsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void makeContactAccountVisible() {
|
||||
|
@ -366,6 +378,11 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
}
|
||||
|
||||
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()) {
|
||||
return findContactFromPhoneNumber(username);
|
||||
}
|
||||
|
@ -421,6 +438,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
}
|
||||
|
||||
public String getAddressOrNumberForAndroidContact(ContentResolver resolver, Uri contactUri) {
|
||||
if (resolver == null || contactUri == null) return null;
|
||||
|
||||
// Phone Numbers
|
||||
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
|
||||
Cursor c = resolver.query(contactUri, projection, null, null, null);
|
||||
|
@ -431,8 +450,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
c.close();
|
||||
return number;
|
||||
}
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
|
||||
c = resolver.query(contactUri, projection, null, null, null);
|
||||
|
@ -444,12 +463,14 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
c.close();
|
||||
return address;
|
||||
}
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private synchronized boolean refreshSipContact(Friend lf) {
|
||||
if (lf == null) return false;
|
||||
LinphoneContact contact = (LinphoneContact) lf.getUserData();
|
||||
|
||||
if (contact != null) {
|
||||
|
@ -486,6 +507,7 @@ public class ContactsManager extends ContentObserver implements FriendListListen
|
|||
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
|
||||
|
||||
for (String id : ids) {
|
||||
Log.i("[Contacts Manager] Adding Android contact id ", id, " to batch removal");
|
||||
String[] args = new String[] {id};
|
||||
ops.add(
|
||||
ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.linphone.core.Address;
|
|||
import org.linphone.core.Core;
|
||||
import org.linphone.core.Friend;
|
||||
import org.linphone.core.FriendCapability;
|
||||
import org.linphone.core.FriendList;
|
||||
import org.linphone.core.PresenceBasicStatus;
|
||||
import org.linphone.core.PresenceModel;
|
||||
import org.linphone.core.SubscribePolicy;
|
||||
|
@ -195,7 +194,7 @@ public class LinphoneContact extends AndroidContact
|
|||
}
|
||||
|
||||
private void setPhotoUri(Uri uri) {
|
||||
if (uri.equals(mPhotoUri)) return;
|
||||
if (uri != null && uri.equals(mPhotoUri)) return;
|
||||
mPhotoUri = uri;
|
||||
}
|
||||
|
||||
|
@ -204,7 +203,7 @@ public class LinphoneContact extends AndroidContact
|
|||
}
|
||||
|
||||
private void setThumbnailUri(Uri uri) {
|
||||
if (uri.equals(mThumbnailUri)) return;
|
||||
if (uri != null && uri.equals(mThumbnailUri)) return;
|
||||
mThumbnailUri = uri;
|
||||
}
|
||||
|
||||
|
@ -216,14 +215,16 @@ public class LinphoneContact extends AndroidContact
|
|||
if (noa == null) return;
|
||||
|
||||
boolean found = false;
|
||||
String normalizedPhone = noa.getNormalizedPhone();
|
||||
// Check for duplicated phone numbers but with different formats
|
||||
for (LinphoneNumberOrAddress number : mAddresses) {
|
||||
if (!number.isSIPAddress()) {
|
||||
if ((!noa.isSIPAddress()
|
||||
&& noa.getNormalizedPhone().equals(number.getNormalizedPhone()))
|
||||
&& normalizedPhone != null
|
||||
&& normalizedPhone.equals(number.getNormalizedPhone()))
|
||||
|| (noa.isSIPAddress()
|
||||
&& noa.getValue().equals(number.getNormalizedPhone()))
|
||||
|| (noa.getNormalizedPhone().equals(number.getValue()))) {
|
||||
|| (normalizedPhone != null && normalizedPhone.equals(number.getValue()))) {
|
||||
Log.d("[Linphone Contact] Duplicated entry detected: " + noa);
|
||||
found = true;
|
||||
break;
|
||||
|
@ -247,7 +248,8 @@ public class LinphoneContact extends AndroidContact
|
|||
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
||||
if (noa.isSIPAddress()) {
|
||||
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
|
||||
// address may have a ;gruu= at the end...
|
||||
return true;
|
||||
|
@ -274,7 +276,8 @@ public class LinphoneContact extends AndroidContact
|
|||
}
|
||||
LinphoneNumberOrAddress toRemove = null;
|
||||
for (LinphoneNumberOrAddress address : mAddresses) {
|
||||
if (noa.getOldValue().equals(address.getValue())
|
||||
if (noa.getOldValue() != null
|
||||
&& noa.getOldValue().equals(address.getValue())
|
||||
&& noa.isSIPAddress() == address.isSIPAddress()) {
|
||||
toRemove = address;
|
||||
break;
|
||||
|
@ -305,7 +308,8 @@ public class LinphoneContact extends AndroidContact
|
|||
}
|
||||
}
|
||||
for (LinphoneNumberOrAddress address : mAddresses) {
|
||||
if (noa.getOldValue().equals(address.getValue())
|
||||
if (noa.getOldValue() != null
|
||||
&& noa.getOldValue().equals(address.getValue())
|
||||
&& noa.isSIPAddress() == address.isSIPAddress()) {
|
||||
address.setValue(noa.getValue());
|
||||
break;
|
||||
|
@ -352,10 +356,11 @@ public class LinphoneContact extends AndroidContact
|
|||
if (mFriend.getVcard() != null) {
|
||||
mFriend.getVcard().setFamilyName(mLastName);
|
||||
mFriend.getVcard().setGivenName(mFirstName);
|
||||
}
|
||||
|
||||
if (mOrganization != null) {
|
||||
mFriend.getVcard().setOrganization(mOrganization);
|
||||
}
|
||||
}
|
||||
|
||||
if (!created) {
|
||||
for (Address address : mFriend.getAddresses()) {
|
||||
|
@ -395,12 +400,12 @@ public class LinphoneContact extends AndroidContact
|
|||
}
|
||||
|
||||
public void deleteFriend() {
|
||||
if (mFriend == null) return;
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (mFriend != null && core != null) {
|
||||
for (FriendList list : core.getFriendsLists()) {
|
||||
list.removeFriend(mFriend);
|
||||
}
|
||||
}
|
||||
if (core == null) return;
|
||||
|
||||
Log.i("[Contact] Deleting friend ", mFriend.getName(), " for contact ", this);
|
||||
mFriend.remove();
|
||||
}
|
||||
|
||||
public void createOrUpdateFriendFromNativeContact() {
|
||||
|
@ -427,7 +432,9 @@ public class LinphoneContact extends AndroidContact
|
|||
if (mFriend == null) return false;
|
||||
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -449,14 +456,22 @@ public class LinphoneContact extends AndroidContact
|
|||
}
|
||||
|
||||
public boolean hasPresenceModelForUriOrTelCapability(String uri, FriendCapability capability) {
|
||||
if (mFriend == null) return false;
|
||||
if (mFriend.getPresenceModelForUriOrTel(uri) != null) {
|
||||
return mFriend.getPresenceModelForUriOrTel(uri).hasCapability(capability);
|
||||
if (mFriend == null || uri == null) return false;
|
||||
|
||||
PresenceModel presence = mFriend.getPresenceModelForUriOrTel(uri);
|
||||
if (presence != null) {
|
||||
return presence.hasCapability(capability);
|
||||
} else {
|
||||
for (LinphoneNumberOrAddress noa : getNumbersOrAddresses()) {
|
||||
if (getContactFromPresenceModelForUriOrTel(noa.getValue()).equals(uri)) {
|
||||
return mFriend.getPresenceModelForUriOrTel(noa.getValue())
|
||||
.hasCapability(capability);
|
||||
String value = noa.getValue();
|
||||
if (value != null) {
|
||||
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 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);
|
||||
setFullName(displayName);
|
||||
}
|
||||
|
||||
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 + ")");
|
||||
addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
|
||||
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime)
|
||||
|
@ -560,12 +581,27 @@ public class LinphoneContact extends AndroidContact
|
|||
.getApplicationContext()
|
||||
.getString(R.string.linphone_address_mime_type)
|
||||
.equals(mime)) {
|
||||
if (data1 == null) {
|
||||
Log.e("[Linphone Contact] SIP address is null !");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("[Linphone Contact] Found SIP address " + data1);
|
||||
addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
|
||||
} 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);
|
||||
setOrganization(data1, false);
|
||||
} 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);
|
||||
setFirstNameAndLastName(data2, data3, false);
|
||||
} else {
|
||||
|
@ -592,7 +628,9 @@ public class LinphoneContact extends AndroidContact
|
|||
// Test presence of the value
|
||||
PresenceModel pm = getFriend().getPresenceModelForUriOrTel(value);
|
||||
// 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);
|
||||
if (!isLinphoneAddressMimeEntryAlreadyExisting(value)) {
|
||||
// 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() {
|
||||
saveChangesCommited();
|
||||
if (getAndroidId() != null) {
|
||||
setThumbnailUri(getContactThumbnailPictureUri());
|
||||
setPhotoUri(getContactPictureUri());
|
||||
}
|
||||
syncValuesFromAndroidContact(LinphoneContext.instance().getApplicationContext());
|
||||
createOrUpdateFriend();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
Log.i("[Contact] Deleting contact ", this);
|
||||
if (isAndroidContact()) {
|
||||
deleteAndroidContact();
|
||||
}
|
||||
if (isFriend()) {
|
||||
deleteFriend();
|
||||
}
|
||||
|
|
|
@ -54,9 +54,11 @@ public class SearchContactViewHolder extends RecyclerView.ViewHolder
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
if (mListener != null) {
|
||||
if (disabled.getVisibility() == View.GONE) {
|
||||
mListener.onItemClicked(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ClickListener {
|
||||
void onItemClicked(int position);
|
||||
|
|
|
@ -30,13 +30,14 @@ import java.util.Objects;
|
|||
import org.linphone.LinphoneContext;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.FriendCapability;
|
||||
import org.linphone.core.PresenceBasicStatus;
|
||||
import org.linphone.core.PresenceModel;
|
||||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.core.SearchResult;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactViewHolder> {
|
||||
private List<SearchResult> mContacts;
|
||||
|
@ -118,8 +119,20 @@ public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactVie
|
|||
holder.name.setText(searchResult.getAddress().getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
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.getFullName() == null
|
||||
&& contact.getFirstName() == null
|
||||
|
@ -137,15 +150,6 @@ public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactVie
|
|||
&& !searchResult.hasCapability(FriendCapability.LimeX3Dh))) {
|
||||
// Disable row, contact doesn't have the required capabilities
|
||||
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 {
|
||||
ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout);
|
||||
|
|
|
@ -17,49 +17,25 @@
|
|||
* 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;
|
||||
package org.linphone.contacts.views;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import org.linphone.R;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.core.ChatRoomSecurityLevel;
|
||||
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 {
|
||||
|
||||
private static String generateAvatar(String displayName) {
|
||||
String[] names = displayName.split(" ");
|
||||
StringBuilder generatedAvatarText = new StringBuilder();
|
||||
int count = 0;
|
||||
for (String name : names) {
|
||||
if (name != null && name.length() > 0) {
|
||||
if (name != null && name.length() > 0 && count < 2) {
|
||||
generatedAvatarText.append(name.charAt(0));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return generatedAvatarText.toString().toUpperCase();
|
||||
|
@ -161,10 +137,7 @@ public class ContactAvatar {
|
|||
|
||||
Bitmap bm = ImageUtils.getRoundBitmapFromUri(v.getContext(), contact.getThumbnailUri());
|
||||
if (bm != null) {
|
||||
holder.contactPicture.setImageBitmap(bm);
|
||||
holder.contactPicture.setVisibility(View.VISIBLE);
|
||||
holder.generatedAvatar.setVisibility(View.GONE);
|
||||
holder.generatedAvatarBackground.setVisibility(View.GONE);
|
||||
displayAvatar(bm, holder);
|
||||
} else if (generated_avatars) {
|
||||
holder.generatedAvatar.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) {
|
||||
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
|
||||
* 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.view.LayoutInflater;
|
|
@ -17,7 +17,7 @@
|
|||
* 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.activities;
|
||||
package org.linphone.dialer;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
|
@ -37,17 +37,18 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.MainActivity;
|
||||
import org.linphone.call.views.CallButton;
|
||||
import org.linphone.contacts.ContactsActivity;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
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.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 {
|
||||
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) {
|
||||
Core core = LinphoneManager.getCore();
|
||||
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()) {
|
||||
preview.setVisibility(View.VISIBLE);
|
||||
core.setNativePreviewWindowId(preview);
|
||||
core.enableVideoPreview(true);
|
||||
|
||||
ImageView changeCamera = findViewById(R.id.video_preview_change_camera);
|
||||
if (changeCamera != null && core.getVideoDevicesList().length > 1) {
|
||||
if (core.getVideoDevicesList().length > 1) {
|
||||
changeCamera.setVisibility(View.VISIBLE);
|
||||
changeCamera.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
|
@ -239,6 +241,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
|||
}
|
||||
} else {
|
||||
preview.setVisibility(View.GONE);
|
||||
changeCamera.setVisibility(View.GONE);
|
||||
core.setNativePreviewWindowId(null);
|
||||
core.enableVideoPreview(false);
|
||||
}
|
||||
|
@ -259,9 +262,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
|||
|
||||
@Override
|
||||
public void onAddressChanged() {
|
||||
Core core = LinphoneManager.getCore();
|
||||
mAddContact.setEnabled(
|
||||
core != null && core.getCallsNb() > 0 || !mAddress.getText().toString().equals(""));
|
||||
mAddContact.setEnabled(!mAddress.getText().toString().isEmpty());
|
||||
}
|
||||
|
||||
private void updateLayout() {
|
||||
|
@ -273,6 +274,8 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
|
|||
boolean atLeastOneCall = core.getCallsNb() > 0;
|
||||
mStartCall.setVisibility(atLeastOneCall ? View.GONE : View.VISIBLE);
|
||||
mAddContact.setVisibility(atLeastOneCall ? View.GONE : View.VISIBLE);
|
||||
mAddContact.setEnabled(!mAddress.getText().toString().isEmpty());
|
||||
|
||||
if (!atLeastOneCall) {
|
||||
if (core.getVideoActivationPolicy().getAutomaticallyInitiate()) {
|
||||
mStartCall.setImageResource(R.drawable.call_video_start);
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.dialer.views;
|
||||
|
||||
public interface AddressAware {
|
||||
void setAddressWidget(AddressText address);
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.dialer.views;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.dialer.views;
|
||||
|
||||
public interface AddressType {
|
||||
CharSequence getText();
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.dialer.views;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
|
@ -17,7 +17,7 @@
|
|||
* 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;
|
||||
package org.linphone.dialer.views;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
|
@ -37,7 +37,7 @@ public class FirebaseMessaging extends FirebaseMessagingService {
|
|||
android.util.Log.i(
|
||||
"FirebaseMessaging", "[Push Notification] Starting context");
|
||||
new LinphoneContext(getApplicationContext());
|
||||
LinphoneContext.instance().start(false);
|
||||
LinphoneContext.instance().start(true);
|
||||
} else {
|
||||
Log.i("[Push Notification] Notifying Core");
|
||||
if (LinphoneManager.getInstance() != null) {
|
||||
|
|
|
@ -79,10 +79,8 @@ public class StatusBarFragment extends Fragment {
|
|||
final RegistrationState state,
|
||||
String smessage) {
|
||||
if (core.getProxyConfigList() == null) {
|
||||
mStatusLed.setImageResource(R.drawable.led_disconnected);
|
||||
mStatusText.setText(getString(R.string.no_account));
|
||||
} else {
|
||||
mStatusLed.setVisibility(View.VISIBLE);
|
||||
showNoAccountConfigured();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((core.getDefaultProxyConfig() != null
|
||||
|
@ -152,6 +150,8 @@ public class StatusBarFragment extends Fragment {
|
|||
ProxyConfig lpc = core.getDefaultProxyConfig();
|
||||
if (lpc != null) {
|
||||
mListener.onRegistrationStateChanged(core, lpc, lpc.getState(), null);
|
||||
} else {
|
||||
showNoAccountConfigured();
|
||||
}
|
||||
} else {
|
||||
mStatusText.setVisibility(View.VISIBLE);
|
||||
|
@ -178,11 +178,15 @@ public class StatusBarFragment extends Fragment {
|
|||
mVoicemailCount.setVisibility(View.VISIBLE);
|
||||
|
||||
if (core.getProxyConfigList().length == 0) {
|
||||
showNoAccountConfigured();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showNoAccountConfigured() {
|
||||
mStatusLed.setImageResource(R.drawable.led_disconnected);
|
||||
mStatusText.setText(getString(R.string.no_account));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getStatusIconResource(RegistrationState state) {
|
||||
try {
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.app.Fragment;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import org.linphone.LinphoneContext;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.MainActivity;
|
||||
|
@ -71,6 +72,7 @@ public class HistoryActivity extends MainActivity {
|
|||
mHistorySelected.setVisibility(View.VISIBLE);
|
||||
LinphoneManager.getCore().resetMissedCallsCount();
|
||||
displayMissedCalls();
|
||||
LinphoneContext.instance().getNotificationManager().dismissMissedCallNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,13 +30,13 @@ import java.util.List;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.CallLog;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.utils.SelectableAdapter;
|
||||
import org.linphone.utils.SelectableHelper;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
|
||||
private final List<CallLog> mLogs;
|
||||
|
|
|
@ -35,20 +35,22 @@ import org.linphone.LinphoneManager;
|
|||
import org.linphone.R;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.LinphoneContact;
|
||||
import org.linphone.contacts.views.ContactAvatar;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.CallLog;
|
||||
import org.linphone.core.ChatRoom;
|
||||
import org.linphone.core.ChatRoomBackend;
|
||||
import org.linphone.core.ChatRoomListenerStub;
|
||||
import org.linphone.core.ChatRoomParams;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.core.Factory;
|
||||
import org.linphone.core.FriendCapability;
|
||||
import org.linphone.core.ProxyConfig;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
import org.linphone.views.ContactAvatar;
|
||||
|
||||
public class HistoryDetailFragment extends Fragment {
|
||||
private ImageView mAddToContacts;
|
||||
|
@ -60,6 +62,7 @@ public class HistoryDetailFragment extends Fragment {
|
|||
private ChatRoom mChatRoom;
|
||||
private ChatRoomListenerStub mChatRoomCreationListener;
|
||||
private ListView mLogsList;
|
||||
private CoreListenerStub mListener;
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
|
@ -157,7 +160,7 @@ public class HistoryDetailFragment extends Fragment {
|
|||
mWaitLayout.setVisibility(View.GONE);
|
||||
((HistoryActivity) getActivity()).displayChatRoomError();
|
||||
Log.e(
|
||||
"Group mChat room for address "
|
||||
"[History Detail Fragment] Group mChat room for address "
|
||||
+ cr.getPeerAddress()
|
||||
+ " has failed !");
|
||||
}
|
||||
|
@ -165,16 +168,36 @@ public class HistoryDetailFragment extends Fragment {
|
|||
};
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
LinphoneManager.getCore().addListener(mListener);
|
||||
displayHistory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mChatRoom != null) {
|
||||
mChatRoom.removeListener(mChatRoomCreationListener);
|
||||
}
|
||||
LinphoneManager.getCore().removeListener(mListener);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
@ -234,24 +257,29 @@ public class HistoryDetailFragment extends Fragment {
|
|||
|
||||
private void goToChat(boolean isSecured) {
|
||||
Core core = LinphoneManager.getCore();
|
||||
if (core == null) return;
|
||||
|
||||
Address participant = Factory.instance().createAddress(mSipUri);
|
||||
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
|
||||
|
||||
if (defaultProxyConfig != null) {
|
||||
ChatRoom room =
|
||||
core.findOneToOneChatRoom(
|
||||
core.getDefaultProxyConfig().getContact(), participant, isSecured);
|
||||
defaultProxyConfig.getContact(), participant, isSecured);
|
||||
if (room != null) {
|
||||
((HistoryActivity) getActivity())
|
||||
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
|
||||
} else {
|
||||
ProxyConfig lpc = core.getDefaultProxyConfig();
|
||||
if (lpc != null
|
||||
&& lpc.getConferenceFactoryUri() != null
|
||||
&& (isSecured || !LinphonePreferences.instance().useBasicChatRoomFor1To1())) {
|
||||
if (defaultProxyConfig.getConferenceFactoryUri() != null
|
||||
&& (isSecured
|
||||
|| !LinphonePreferences.instance().useBasicChatRoomFor1To1())) {
|
||||
mWaitLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
ChatRoomParams params = core.createDefaultChatRoomParams();
|
||||
params.enableEncryption(isSecured);
|
||||
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);
|
||||
|
||||
Address[] participants = new Address[1];
|
||||
|
@ -259,7 +287,9 @@ public class HistoryDetailFragment extends Fragment {
|
|||
|
||||
mChatRoom =
|
||||
core.createChatRoom(
|
||||
params, getString(R.string.dummy_group_chat_subject), participants);
|
||||
params,
|
||||
getString(R.string.dummy_group_chat_subject),
|
||||
participants);
|
||||
if (mChatRoom != null) {
|
||||
mChatRoom.addListener(mChatRoomCreationListener);
|
||||
} 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.Arrays;
|
||||
import java.util.List;
|
||||
import org.linphone.LinphoneContext;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.R;
|
||||
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||
import org.linphone.contacts.ContactsManager;
|
||||
import org.linphone.contacts.ContactsUpdatedListener;
|
||||
import org.linphone.core.Address;
|
||||
import org.linphone.core.Call;
|
||||
import org.linphone.core.CallLog;
|
||||
import org.linphone.core.Core;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.utils.SelectableHelper;
|
||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
||||
|
||||
public class HistoryFragment extends Fragment
|
||||
implements OnClickListener,
|
||||
OnItemClickListener,
|
||||
HistoryViewHolder.ClickListener,
|
||||
ContactsUpdatedListener,
|
||||
SelectableHelper.DeleteListener {
|
||||
SelectableHelper.DeleteListener,
|
||||
LinphoneContext.CoreStartedListener {
|
||||
private RecyclerView mHistoryList;
|
||||
private TextView mNoCallHistory, mNoMissedCallHistory;
|
||||
private ImageView mMissedCalls, mAllCalls;
|
||||
|
@ -60,6 +63,7 @@ public class HistoryFragment extends Fragment
|
|||
private List<CallLog> mLogs;
|
||||
private HistoryAdapter mHistoryAdapter;
|
||||
private SelectableHelper mSelectionHelper;
|
||||
private CoreListenerStub mListener;
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
|
@ -94,26 +98,37 @@ public class HistoryFragment extends Fragment
|
|||
mAllCalls.setEnabled(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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
ContactsManager.getInstance().addContactsListener(this);
|
||||
|
||||
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);
|
||||
ContactsManager.getInstance().addContactsListener(this);
|
||||
LinphoneContext.instance().addCoreStartedListener(this);
|
||||
LinphoneManager.getCore().addListener(mListener);
|
||||
|
||||
reloadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
ContactsManager.getInstance().removeContactsListener(this);
|
||||
LinphoneContext.instance().removeCoreStartedListener(this);
|
||||
LinphoneManager.getCore().removeListener(mListener);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
@ -125,6 +140,11 @@ public class HistoryFragment extends Fragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCoreStarted() {
|
||||
reloadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int id = v.getId();
|
||||
|
@ -177,6 +197,7 @@ public class HistoryFragment extends Fragment
|
|||
if (mHistoryAdapter.isEditionEnabled()) {
|
||||
mHistoryAdapter.toggleSelection(position);
|
||||
} else {
|
||||
if (position >= 0 && position < mLogs.size()) {
|
||||
CallLog log = mLogs.get(position);
|
||||
Address address;
|
||||
if (log.getDir() == Call.Dir.Incoming) {
|
||||
|
@ -185,7 +206,9 @@ public class HistoryFragment extends Fragment
|
|||
address = log.getToAddress();
|
||||
}
|
||||
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() {
|
||||
if (mOnlyDisplayMissedCalls) {
|
||||
List<CallLog> missedCalls = new ArrayList<>();
|
||||
|
|
|
@ -29,12 +29,11 @@ import android.content.Intent;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.R;
|
||||
import org.linphone.activities.DialerActivity;
|
||||
import org.linphone.call.CallActivity;
|
||||
import org.linphone.call.CallIncomingActivity;
|
||||
import org.linphone.call.CallOutgoingActivity;
|
||||
|
@ -53,7 +52,9 @@ import org.linphone.core.Core;
|
|||
import org.linphone.core.CoreListenerStub;
|
||||
import org.linphone.core.Reason;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.dialer.DialerActivity;
|
||||
import org.linphone.history.HistoryActivity;
|
||||
import org.linphone.service.LinphoneService;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
import org.linphone.utils.DeviceUtils;
|
||||
import org.linphone.utils.FileUtils;
|
||||
|
@ -84,7 +85,19 @@ public class NotificationsManager {
|
|||
mCurrentChatRoomAddress = null;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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) {
|
||||
Log.i("[Notifications Manager] Notifying " + id);
|
||||
mNM.notify(id, notif);
|
||||
|
@ -521,7 +538,8 @@ public class NotificationsManager {
|
|||
mContext,
|
||||
mContext.getString(R.string.missed_calls_notif_title),
|
||||
body,
|
||||
pendingIntent);
|
||||
pendingIntent,
|
||||
missedCallCount);
|
||||
sendNotification(MISSED_CALLS_NOTIF_ID, notif);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.receivers;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
|
@ -28,10 +29,40 @@ import org.linphone.LinphoneManager;
|
|||
import org.linphone.core.tools.Log;
|
||||
|
||||
public class BluetoothReceiver extends BroadcastReceiver {
|
||||
public BluetoothReceiver() {
|
||||
super();
|
||||
Log.i("[Bluetooth] Bluetooth receiver created");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
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 =
|
||||
intent.getIntExtra(
|
||||
BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
|
||||
|
@ -55,6 +86,8 @@ public class BluetoothReceiver extends BroadcastReceiver {
|
|||
} else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
|
||||
Log.i("[Bluetooth] Bluetooth headset audio disconnected");
|
||||
LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(false);
|
||||
} else if (state == BluetoothHeadset.STATE_AUDIO_CONNECTING) {
|
||||
Log.i("[Bluetooth] Bluetooth headset audio connecting");
|
||||
} else {
|
||||
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.Context;
|
||||
import android.content.Intent;
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
import org.linphone.service.LinphoneService;
|
||||
import org.linphone.settings.LinphonePreferences;
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
@ -36,17 +36,34 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
"[Boot Receiver] Device is shutting down, destroying Core to unregister");
|
||||
context.stopService(
|
||||
new Intent(Intent.ACTION_MAIN).setClass(context, LinphoneService.class));
|
||||
} else {
|
||||
} else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
|
||||
LinphonePreferences.instance().setContext(context);
|
||||
boolean autostart = LinphonePreferences.instance().isAutoStartEnabled();
|
||||
android.util.Log.i(
|
||||
"Linphone", "[Boot Receiver] Device is starting, auto_start is " + autostart);
|
||||
|
||||
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);
|
||||
serviceIntent.setClass(context, LinphoneService.class);
|
||||
serviceIntent.putExtra("ForceStartForeground", true);
|
||||
Compatibility.startService(context, serviceIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,15 @@ import org.linphone.core.tools.Log;
|
|||
public class HeadsetReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (isInitialStickyBroadcast()) {
|
||||
Log.i("[Headset] Received broadcast from sticky cache, ignoring...");
|
||||
return;
|
||||
}
|
||||
|
||||
String action = intent.getAction();
|
||||
if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
|
||||
// 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);
|
||||
String name = intent.getStringExtra("name");
|
||||
int hasMicrophone = intent.getIntExtra("microphone", 0);
|
||||
|
@ -44,7 +50,7 @@ public class HeadsetReceiver extends BroadcastReceiver {
|
|||
Log.i("[Headset] Headset " + name + " has a microphone");
|
||||
}
|
||||
} else {
|
||||
Log.w("[Headset] Unknow headset plugged state: " + state);
|
||||
Log.w("[Headset] Unknown headset plugged state: " + state);
|
||||
}
|
||||
|
||||
LinphoneManager.getAudioManager().routeAudioToEarPiece();
|
||||
|
@ -55,7 +61,7 @@ public class HeadsetReceiver extends BroadcastReceiver {
|
|||
LinphoneManager.getAudioManager().routeAudioToEarPiece();
|
||||
LinphoneManager.getCallManager().refreshInCallActions();
|
||||
} 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.R;
|
||||
import org.linphone.activities.MainActivity;
|
||||
import org.linphone.call.views.LinphoneLinearLayoutManager;
|
||||
import org.linphone.utils.FileUtils;
|
||||
import org.linphone.utils.SelectableHelper;
|
||||
import org.linphone.views.LinphoneLinearLayoutManager;
|
||||
|
||||
public class RecordingsActivity extends MainActivity
|
||||
implements SelectableHelper.DeleteListener, RecordingViewHolder.ClickListener {
|
||||
|
|
|
@ -17,15 +17,15 @@
|
|||
* 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.utils;
|
||||
package org.linphone.service;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
import java.util.ArrayList;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.LinphoneService;
|
||||
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
|
|
@ -17,22 +17,24 @@
|
|||
* 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;
|
||||
package org.linphone.service;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
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.Core;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.mediastream.Version;
|
||||
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 {
|
||||
private static LinphoneService sInstance;
|
||||
|
@ -75,8 +77,12 @@ public final class LinphoneService extends Service {
|
|||
}
|
||||
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");
|
||||
// We need to call this asap after the Service can be accessed through it's singleton
|
||||
LinphoneContext.instance().getNotificationManager().startForeground();
|
||||
}
|
||||
|
||||
|
@ -86,14 +92,7 @@ public final class LinphoneService extends Service {
|
|||
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");
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
|
@ -17,9 +17,9 @@
|
|||
* 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.utils;
|
||||
package org.linphone.service;
|
||||
|
||||
import org.linphone.LinphoneService;
|
||||
import org.linphone.utils.LinphoneUtils;
|
||||
|
||||
public class ServiceWaitThread extends Thread {
|
||||
private ServiceWaitThreadListener mListener;
|
|
@ -17,7 +17,7 @@
|
|||
* 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.utils;
|
||||
package org.linphone.service;
|
||||
|
||||
public interface ServiceWaitThreadListener {
|
||||
void onServiceReady();
|
|
@ -240,6 +240,9 @@ public class AccountSettingsFragment extends SettingsFragment {
|
|||
if (mAuthInfo != null) {
|
||||
mAuthInfo.setHa1(null);
|
||||
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();
|
||||
if (core != null) {
|
||||
core.addAuthInfo(mAuthInfo);
|
||||
|
|
|
@ -83,6 +83,8 @@ public class AdvancedSettingsFragment extends SettingsFragment {
|
|||
mStartAtBoot = mRootView.findViewById(R.id.pref_autostart);
|
||||
|
||||
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.setInputType(
|
||||
|
|
|
@ -20,9 +20,12 @@
|
|||
package org.linphone.settings;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.text.InputType;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -54,7 +57,7 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
mAutoAnswer;
|
||||
private ListSetting mMediaEncryption;
|
||||
private TextSetting mAutoAnswerTime, mIncomingCallTimeout, mVoiceMailUri;
|
||||
private BasicSetting mDndPermissionSettings;
|
||||
private BasicSetting mDndPermissionSettings, mAndroidNotificationSettings;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -90,6 +93,8 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
mMediaEncryption = mRootView.findViewById(R.id.pref_media_encryption);
|
||||
initMediaEncryptionList();
|
||||
|
||||
mAndroidNotificationSettings = mRootView.findViewById(R.id.pref_android_app_notif_settings);
|
||||
|
||||
mAutoAnswerTime = mRootView.findViewById(R.id.pref_auto_answer_time);
|
||||
mAutoAnswerTime.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
|
||||
|
@ -167,8 +172,15 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
@Override
|
||||
public void onListValueChanged(int position, String newLabel, String newValue) {
|
||||
try {
|
||||
mPrefs.setMediaEncryption(
|
||||
MediaEncryption.fromInt(Integer.parseInt(newValue)));
|
||||
MediaEncryption encryption =
|
||||
MediaEncryption.fromInt(Integer.parseInt(newValue));
|
||||
mPrefs.setMediaEncryption(encryption);
|
||||
|
||||
if (encryption == MediaEncryption.None) {
|
||||
mMediaEncryptionMandatory.setChecked(false);
|
||||
}
|
||||
mMediaEncryptionMandatory.setEnabled(
|
||||
encryption != MediaEncryption.None);
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.e(nfe);
|
||||
}
|
||||
|
@ -223,6 +235,27 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
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() {
|
||||
|
@ -248,7 +281,12 @@ public class CallSettingsFragment extends SettingsFragment {
|
|||
mDndPermissionSettings.setVisibility(
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -320,10 +320,12 @@ public class LinphonePreferences {
|
|||
|
||||
// Video settings
|
||||
public boolean useFrontCam() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "front_camera_default", true);
|
||||
}
|
||||
|
||||
public void setFrontCamAsDefault(boolean frontcam) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "front_camera_default", frontcam);
|
||||
}
|
||||
|
||||
|
@ -425,6 +427,7 @@ public class LinphonePreferences {
|
|||
|
||||
// Contact settings
|
||||
public boolean isFriendlistsubscriptionEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
if (getConfig().getBool("app", "friendlist_subscription_enabled", false)) {
|
||||
// Old setting, do migration
|
||||
getConfig().setBool("app", "friendlist_subscription_enabled", false);
|
||||
|
@ -434,18 +437,22 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public void enabledFriendlistSubscription(boolean enabled) {
|
||||
if (getLc() == null) return;
|
||||
getLc().enableFriendListSubscription(enabled);
|
||||
}
|
||||
|
||||
public boolean isPresenceStorageInNativeAndroidContactEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "store_presence_in_native_contact", false);
|
||||
}
|
||||
|
||||
public void enabledPresenceStorageInNativeAndroidContact(boolean enabled) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "store_presence_in_native_contact", enabled);
|
||||
}
|
||||
|
||||
public boolean isDisplayContactOrganization() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig()
|
||||
.getBool(
|
||||
"app",
|
||||
|
@ -454,24 +461,29 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public void enabledDisplayContactOrganization(boolean enabled) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "display_contact_organization", enabled);
|
||||
}
|
||||
// End of contact settings
|
||||
|
||||
// Call settings
|
||||
public boolean acceptMediaEncryptionMandatory() {
|
||||
public boolean isMediaEncryptionMandatory() {
|
||||
if (getLc() == null) return false;
|
||||
return getLc().isMediaEncryptionMandatory();
|
||||
}
|
||||
|
||||
public void setMediaEncryptionMandatory(boolean accept) {
|
||||
if (getLc() == null) return;
|
||||
getLc().setMediaEncryptionMandatory(accept);
|
||||
}
|
||||
|
||||
public boolean acceptIncomingEarlyMedia() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("sip", "incoming_calls_early_media", false);
|
||||
}
|
||||
|
||||
public void setAcceptIncomingEarlyMedia(boolean accept) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("sip", "incoming_calls_early_media", accept);
|
||||
}
|
||||
|
||||
|
@ -506,28 +518,34 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public String getVoiceMailUri() {
|
||||
if (getConfig() == null) return null;
|
||||
return getConfig().getString("app", "voice_mail", null);
|
||||
}
|
||||
|
||||
public void setVoiceMailUri(String uri) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setString("app", "voice_mail", uri);
|
||||
}
|
||||
|
||||
public boolean getNativeDialerCall() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "native_dialer_call", false);
|
||||
}
|
||||
|
||||
public void setNativeDialerCall(boolean use) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "native_dialer_call", use);
|
||||
}
|
||||
// End of call settings
|
||||
|
||||
public boolean isWifiOnlyEnabled() {
|
||||
if (getLc() == null) return false;
|
||||
return getLc().wifiOnlyEnabled();
|
||||
}
|
||||
|
||||
// Network settings
|
||||
public void setWifiOnlyEnabled(Boolean enable) {
|
||||
if (getLc() == null) return;
|
||||
getLc().enableWifiOnly(enable);
|
||||
}
|
||||
|
||||
|
@ -536,6 +554,7 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
private void useRandomPort(boolean enabled, boolean apply) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "random_port", enabled);
|
||||
if (apply) {
|
||||
if (enabled) {
|
||||
|
@ -547,6 +566,7 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public boolean isUsingRandomPort() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "random_port", true);
|
||||
}
|
||||
|
||||
|
@ -677,10 +697,12 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public boolean isPushNotificationEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "push_notification", true);
|
||||
}
|
||||
|
||||
public void setPushNotificationEnabled(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "push_notification", enable);
|
||||
|
||||
Core core = getLc();
|
||||
|
@ -748,6 +770,7 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
private String getPushNotificationRegistrationID() {
|
||||
if (getConfig() == null) return null;
|
||||
return getConfig().getString("app", "push_notification_regid", null);
|
||||
}
|
||||
|
||||
|
@ -770,30 +793,36 @@ public class LinphonePreferences {
|
|||
// End of network settings
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "debug", false);
|
||||
}
|
||||
|
||||
// Advanced settings
|
||||
public void setDebugEnabled(boolean enabled) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "debug", enabled);
|
||||
LinphoneUtils.configureLoggingService(enabled, mContext.getString(R.string.app_name));
|
||||
}
|
||||
|
||||
public void setJavaLogger(boolean enabled) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "java_logger", enabled);
|
||||
LinphoneUtils.configureLoggingService(
|
||||
isDebugEnabled(), mContext.getString(R.string.app_name));
|
||||
}
|
||||
|
||||
public boolean useJavaLogger() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "java_logger", false);
|
||||
}
|
||||
|
||||
public boolean isAutoStartEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "auto_start", false);
|
||||
}
|
||||
|
||||
public void setAutoStart(boolean autoStartEnabled) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "auto_start", autoStartEnabled);
|
||||
}
|
||||
|
||||
|
@ -975,80 +1004,99 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public int getCodecBitrateLimit() {
|
||||
if (getConfig() == null) return 36;
|
||||
return getConfig().getInt("audio", "codec_bitrate_limit", 36);
|
||||
}
|
||||
|
||||
public void setCodecBitrateLimit(int bitrate) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setInt("audio", "codec_bitrate_limit", bitrate);
|
||||
}
|
||||
|
||||
public String getXmlrpcUrl() {
|
||||
if (getConfig() == null) return null;
|
||||
return getConfig().getString("assistant", "xmlrpc_url", null);
|
||||
}
|
||||
|
||||
public String getLinkPopupTime() {
|
||||
if (getConfig() == null) return null;
|
||||
return getConfig().getString("app", "link_popup_time", null);
|
||||
}
|
||||
|
||||
public void setLinkPopupTime(String date) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setString("app", "link_popup_time", date);
|
||||
}
|
||||
|
||||
public boolean isLinkPopupEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "link_popup_enabled", true);
|
||||
}
|
||||
|
||||
public void enableLinkPopup(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "link_popup_enabled", enable);
|
||||
}
|
||||
|
||||
public boolean isDNDSettingsPopupEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "dnd_settings_popup_enabled", true);
|
||||
}
|
||||
|
||||
public void enableDNDSettingsPopup(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "dnd_settings_popup_enabled", enable);
|
||||
}
|
||||
|
||||
public boolean isLimeSecurityPopupEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "lime_security_popup_enabled", true);
|
||||
}
|
||||
|
||||
public void enableLimeSecurityPopup(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "lime_security_popup_enabled", enable);
|
||||
}
|
||||
|
||||
public String getDebugPopupAddress() {
|
||||
if (getConfig() == null) return null;
|
||||
return getConfig().getString("app", "debug_popup_magic", null);
|
||||
}
|
||||
|
||||
public String getActivityToLaunchOnIncomingReceived() {
|
||||
if (getConfig() == null) return "org.linphone.call.CallIncomingActivity";
|
||||
return getConfig()
|
||||
.getString(
|
||||
"app", "incoming_call_activity", "org.linphone.call.CallIncomingActivity");
|
||||
}
|
||||
|
||||
public void setActivityToLaunchOnIncomingReceived(String name) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setString("app", "incoming_call_activity", name);
|
||||
}
|
||||
|
||||
public boolean getServiceNotificationVisibility() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "show_service_notification", false);
|
||||
}
|
||||
|
||||
public void setServiceNotificationVisibility(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "show_service_notification", enable);
|
||||
}
|
||||
|
||||
public String getCheckReleaseUrl() {
|
||||
if (getConfig() == null) return null;
|
||||
return getConfig().getString("misc", "version_check_url_root", null);
|
||||
}
|
||||
|
||||
public int getLastCheckReleaseTimestamp() {
|
||||
if (getConfig() == null) return 0;
|
||||
return getConfig().getInt("app", "version_check_url_last_timestamp", 0);
|
||||
}
|
||||
|
||||
public void setLastCheckReleaseTimestamp(int timestamp) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setInt("app", "version_check_url_last_timestamp", timestamp);
|
||||
}
|
||||
|
||||
|
@ -1058,10 +1106,12 @@ public class LinphonePreferences {
|
|||
// Disable overlay and use PIP feature
|
||||
return false;
|
||||
}
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "display_overlay", false);
|
||||
}
|
||||
|
||||
public void enableOverlay(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "display_overlay", enable);
|
||||
}
|
||||
|
||||
|
@ -1071,71 +1121,87 @@ public class LinphonePreferences {
|
|||
.checkPermission(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
mContext.getPackageName());
|
||||
if (getConfig() == null) return readExternalStorage == PackageManager.PERMISSION_GRANTED;
|
||||
return getConfig().getBool("app", "device_ringtone", true)
|
||||
&& readExternalStorage == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public void enableDeviceRingtone(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "device_ringtone", enable);
|
||||
LinphoneManager.getInstance().enableDeviceRingtone(enable);
|
||||
}
|
||||
|
||||
public boolean isIncomingCallVibrationEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "incoming_call_vibration", true);
|
||||
}
|
||||
|
||||
public void enableIncomingCallVibration(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "incoming_call_vibration", enable);
|
||||
}
|
||||
|
||||
public boolean isBisFeatureEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "bis_feature", true);
|
||||
}
|
||||
|
||||
public boolean isAutoAnswerEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "auto_answer", false);
|
||||
}
|
||||
|
||||
public void enableAutoAnswer(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "auto_answer", enable);
|
||||
}
|
||||
|
||||
public int getAutoAnswerTime() {
|
||||
if (getConfig() == null) return 0;
|
||||
return getConfig().getInt("app", "auto_answer_delay", 0);
|
||||
}
|
||||
|
||||
public void setAutoAnswerTime(int time) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setInt("app", "auto_answer_delay", time);
|
||||
}
|
||||
|
||||
public void disableFriendsStorage() {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("misc", "store_friends", false);
|
||||
}
|
||||
|
||||
public boolean useBasicChatRoomFor1To1() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "prefer_basic_chat_room", false);
|
||||
}
|
||||
|
||||
// 0 is download all, -1 is disable feature, else size is bytes
|
||||
public int getAutoDownloadFileMaxSize() {
|
||||
if (getLc() == null) return -1;
|
||||
return getLc().getMaxSizeForAutoDownloadIncomingFiles();
|
||||
}
|
||||
|
||||
// 0 is download all, -1 is disable feature, else size is bytes
|
||||
public void setAutoDownloadFileMaxSize(int size) {
|
||||
if (getLc() == null) return;
|
||||
getLc().setMaxSizeForAutoDownloadIncomingFiles(size);
|
||||
}
|
||||
|
||||
public boolean hasPowerSaverDialogBeenPrompted() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "android_power_saver_dialog", false);
|
||||
}
|
||||
|
||||
public void powerSaverDialogPrompted(boolean b) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "android_power_saver_dialog", b);
|
||||
}
|
||||
|
||||
public boolean isDarkModeEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
if (!mContext.getResources().getBoolean(R.bool.allow_dark_mode)) return false;
|
||||
|
||||
boolean useNightModeDefault =
|
||||
AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES;
|
||||
|
@ -1152,63 +1218,78 @@ public class LinphonePreferences {
|
|||
}
|
||||
|
||||
public void enableDarkMode(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "dark_mode", enable);
|
||||
}
|
||||
|
||||
public String getDeviceName(Context context) {
|
||||
String defaultValue = Compatibility.getDeviceName(context);
|
||||
if (getConfig() == null) return defaultValue;
|
||||
return getConfig().getString("app", "device_name", defaultValue);
|
||||
}
|
||||
|
||||
public void setDeviceName(String name) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setString("app", "device_name", name);
|
||||
}
|
||||
|
||||
public boolean isEchoCancellationCalibrationDone() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "echo_cancellation_calibration_done", false);
|
||||
}
|
||||
|
||||
public void setEchoCancellationCalibrationDone(boolean done) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "echo_cancellation_calibration_done", done);
|
||||
}
|
||||
|
||||
public boolean isOpenH264CodecDownloadEnabled() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("app", "open_h264_download_enabled", true);
|
||||
}
|
||||
|
||||
public void setOpenH264CodecDownloadEnabled(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "open_h264_download_enabled", enable);
|
||||
}
|
||||
|
||||
public boolean isVideoPreviewEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
return isVideoEnabled() && getConfig().getBool("app", "video_preview", false);
|
||||
}
|
||||
|
||||
public void setVideoPreviewEnabled(boolean enabled) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "video_preview", enabled);
|
||||
}
|
||||
|
||||
public boolean shortcutsCreationEnabled() {
|
||||
if (getConfig() == null) return false;
|
||||
return getConfig().getBool("app", "shortcuts", false);
|
||||
}
|
||||
|
||||
public void enableChatRoomsShortcuts(boolean enable) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("app", "shortcuts", enable);
|
||||
}
|
||||
|
||||
public boolean hideEmptyChatRooms() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("misc", "hide_empty_chat_rooms", true);
|
||||
}
|
||||
|
||||
public void setHideEmptyChatRooms(boolean hide) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("misc", "hide_empty_chat_rooms", hide);
|
||||
}
|
||||
|
||||
public boolean hideRemovedProxiesChatRooms() {
|
||||
if (getConfig() == null) return true;
|
||||
return getConfig().getBool("misc", "hide_chat_rooms_from_removed_proxies", true);
|
||||
}
|
||||
|
||||
public void setHideRemovedProxiesChatRooms(boolean hide) {
|
||||
if (getConfig() == null) return;
|
||||
getConfig().setBool("misc", "hide_chat_rooms_from_removed_proxies", hide);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,6 +312,7 @@ public class VideoSettingsFragment extends SettingsFragment {
|
|||
: View.GONE);
|
||||
mAutoInitiate.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);
|
||||
mBandwidth.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);
|
||||
mVideoCodecs.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() {
|
||||
|
|
|
@ -151,9 +151,10 @@ public class DeviceUtils {
|
|||
for (final Intent intent : POWERMANAGER_INTENTS) {
|
||||
if (DeviceUtils.isIntentCallable(context, intent)) {
|
||||
Log.w(
|
||||
"[Hacks] "
|
||||
+ android.os.Build.MANUFACTURER
|
||||
+ " device with power saver detected !");
|
||||
"[Hacks] ",
|
||||
android.os.Build.MANUFACTURER,
|
||||
" device with power saver detected: ",
|
||||
intent.getComponent().getClassName());
|
||||
if (!LinphonePreferences.instance().hasPowerSaverDialogBeenPrompted()) {
|
||||
Log.w("[Hacks] Asking power saver for whitelist !");
|
||||
|
||||
|
@ -197,12 +198,19 @@ public class DeviceUtils {
|
|||
public void onClick(View v) {
|
||||
Log.w(
|
||||
"[Hacks] Power saver detected, user is going to settings :)");
|
||||
if (doNotAskAgain.isChecked()) {
|
||||
LinphonePreferences.instance()
|
||||
.powerSaverDialogPrompted(true);
|
||||
}
|
||||
// If user is going into the settings,
|
||||
// assume it will make the change so don't prompt again
|
||||
LinphonePreferences.instance().powerSaverDialogPrompted(true);
|
||||
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (SecurityException se) {
|
||||
Log.e(
|
||||
"[Hacks] Couldn't start intent [",
|
||||
intent.getComponent().getClassName(),
|
||||
"], security exception was thrown: ",
|
||||
se);
|
||||
}
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.linphone.utils;
|
|||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
|
@ -55,7 +56,7 @@ public class ImageUtils {
|
|||
return bm;
|
||||
}
|
||||
|
||||
private static Bitmap getRoundBitmap(Bitmap bitmap) {
|
||||
public static Bitmap getRoundBitmap(Bitmap bitmap) {
|
||||
Bitmap output =
|
||||
Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(output);
|
||||
|
@ -85,4 +86,14 @@ public class ImageUtils {
|
|||
/ ((float) context.getResources().getDisplayMetrics().densityDpi
|
||||
/ 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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="40dp"
|
||||
android:gravity="bottom">
|
||||
|
||||
<!-- This is a better way of splitting screen 50/50 than using weights -->
|
||||
|
@ -119,29 +120,30 @@
|
|||
android:layout_centerHorizontal="true" />
|
||||
|
||||
<include layout="@layout/call_primary_buttons"
|
||||
android:id="@+id/call_primary_buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
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"
|
||||
android:id="@+id/call_secondary_buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/vertical_divider" />
|
||||
|
||||
</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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
android:layout_marginBottom="10dp"
|
||||
android:background="?attr/lighToolbarBackgroundColor">
|
||||
|
||||
<org.linphone.views.EraseButton
|
||||
<org.linphone.dialer.views.EraseButton
|
||||
android:id="@+id/erase"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -23,7 +23,7 @@
|
|||
android:contentDescription="@string/content_description_backspace"
|
||||
android:src="@drawable/backspace" />
|
||||
|
||||
<org.linphone.views.AddressText
|
||||
<org.linphone.dialer.views.AddressText
|
||||
android:id="@+id/address"
|
||||
style="@style/numpad_composed_number_font"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -81,7 +81,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<org.linphone.views.CallButton
|
||||
<org.linphone.call.views.CallButton
|
||||
android:id="@+id/start_call"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -91,7 +91,7 @@
|
|||
android:padding="12dp"
|
||||
android:src="@drawable/call_audio_start" />
|
||||
|
||||
<org.linphone.views.CallButton
|
||||
<org.linphone.call.views.CallButton
|
||||
android:id="@+id/add_call"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -102,7 +102,7 @@
|
|||
android:visibility="gone"
|
||||
android:src="@drawable/call_add" />
|
||||
|
||||
<org.linphone.views.CallButton
|
||||
<org.linphone.call.views.CallButton
|
||||
android:id="@+id/transfer_call"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
android:layout_marginBottom="10dp"
|
||||
android:background="?attr/lighToolbarBackgroundColor">
|
||||
|
||||
<org.linphone.views.EraseButton
|
||||
<org.linphone.dialer.views.EraseButton
|
||||
android:id="@+id/erase"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -54,7 +54,7 @@
|
|||
android:contentDescription="@string/content_description_backspace"
|
||||
android:src="@drawable/backspace" />
|
||||
|
||||
<org.linphone.views.AddressText
|
||||
<org.linphone.dialer.views.AddressText
|
||||
android:id="@+id/address"
|
||||
style="@style/numpad_composed_number_font"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -115,7 +115,7 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<org.linphone.views.CallButton
|
||||
<org.linphone.call.views.CallButton
|
||||
android:id="@+id/start_call"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -125,7 +125,7 @@
|
|||
android:padding="12dp"
|
||||
android:src="@drawable/call_audio_start" />
|
||||
|
||||
<org.linphone.views.CallButton
|
||||
<org.linphone.call.views.CallButton
|
||||
android:id="@+id/add_call"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -136,7 +136,7 @@
|
|||
android:visibility="gone"
|
||||
android:src="@drawable/call_add" />
|
||||
|
||||
<org.linphone.views.CallButton
|
||||
<org.linphone.call.views.CallButton
|
||||
android:id="@+id/transfer_call"
|
||||
android:layout_width="match_parent"
|
||||
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