Huge code refactoring using google tool

This commit is contained in:
Sylvain Berfini 2018-11-30 10:31:22 +01:00
parent 60feb938d4
commit 1f6d92b92a
279 changed files with 26953 additions and 23641 deletions

View file

@ -1,112 +1,114 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest package="org.linphone" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android" package="org.linphone"
android:installLocation="auto"> android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.CALL_PHONE" />
<!-- Needed to allow Linphone to install on tablets, since android.permission.CALL_PHONE implies android.hardware.telephony is required --> <!-- Needed to allow Linphone to install on tablets, since android.permission.CALL_PHONE implies android.hardware.telephony is required -->
<uses-feature <uses-feature
android:name="android.hardware.telephony" android:name="android.hardware.telephony"
android:required="false"/> android:required="false" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.CAMERA" />
<!-- Needed to allow Linphone to install on tablets, since android.permission.CAMERA implies android.hardware.camera and android.hardware.camera.autofocus are required --> <!-- Needed to allow Linphone to install on tablets, since android.permission.CAMERA implies android.hardware.camera and android.hardware.camera.autofocus are required -->
<uses-feature <uses-feature
android:name="android.hardware.camera" android:name="android.hardware.camera"
android:required="false"/> android:required="false" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Needed to store received images if the user wants to --> <!-- Needed to store received images if the user wants to -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Needed to use our own Contact editor --> <!-- Needed to use our own Contact editor -->
<uses-permission android:name="android.permission.WRITE_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- Needed to route the audio to the bluetooth headset if available --> <!-- Needed to route the audio to the bluetooth headset if available -->
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BROADCAST_STICKY"/> <uses-permission android:name="android.permission.BROADCAST_STICKY" />
<!-- Needed to pre fill the wizard email field (only if enabled in custom settings) --> <!-- Needed to pre fill the wizard email field (only if enabled in custom settings) -->
<uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<!-- Needed for in-app purchase --> <!-- Needed for in-app purchase -->
<!-- <uses-permission android:name="com.android.vending.BILLING"/> --> <!-- <uses-permission android:name="com.android.vending.BILLING"/> -->
<!-- Needed for overlay widget and floating notifications --> <!-- Needed for overlay widget and floating notifications -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- Needed for kill application yourself --> <!-- Needed for kill application yourself -->
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<supports-screens <supports-screens
android:anyDensity="true" android:anyDensity="true"
android:largeScreens="true" android:largeScreens="true"
android:normalScreens="true" android:normalScreens="true"
android:smallScreens="true" android:smallScreens="true"
android:xlargeScreens="true"/> android:xlargeScreens="true" />
<application <application
android:allowBackup="false" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="true"> android:largeHeap="true"
android:roundIcon="@mipmap/ic_launcher_round">
<activity <activity
android:name=".LinphoneLauncherActivity" android:name=".LinphoneLauncherActivity"
android:exported="true" android:exported="true"
android:launchMode="singleTask"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/NoTitle" android:launchMode="singleTask"
android:noHistory="true" android:noHistory="true"
android:theme="@style/NoTitle"
android:windowSoftInputMode="adjustPan|stateHidden"> android:windowSoftInputMode="adjustPan|stateHidden">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.CALL"/> <action android:name="android.intent.action.CALL" />
<action android:name="android.intent.action.CALL_PRIVILEGED"/> <action android:name="android.intent.action.CALL_PRIVILEGED" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel"/> <data android:scheme="tel" />
<data android:scheme="sip"/> <data android:scheme="sip" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SENDTO"/> <action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sip"/> <data android:scheme="sip" />
<data android:scheme="imto"/> <data android:scheme="imto" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<data android:mimeType="@string/sync_mimetype"/> <data android:mimeType="@string/sync_mimetype" />
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE"/> <category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="text/*"/>
<data android:mimeType="image/*"/> <data android:mimeType="text/*" />
<data android:mimeType="audio/*"/> <data android:mimeType="image/*" />
<data android:mimeType="video/*"/> <data android:mimeType="audio/*" />
<data android:mimeType="application/*"/> <data android:mimeType="video/*" />
<data android:mimeType="application/*" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="org.linphone.intent.action.CallLaunched" /> <action android:name="org.linphone.intent.action.CallLaunched" />
@ -118,7 +120,7 @@
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@ -127,7 +129,7 @@
android:noHistory="true" android:noHistory="true"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@ -136,7 +138,7 @@
android:noHistory="true" android:noHistory="true"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@ -145,7 +147,7 @@
android:noHistory="true" android:noHistory="true"
android:theme="@style/FullScreen"> android:theme="@style/FullScreen">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
<!-- <!--
<intent-filter> <intent-filter>
@ -161,7 +163,7 @@
android:screenOrientation="behind" android:screenOrientation="behind"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@ -169,7 +171,7 @@
android:screenOrientation="nosensor" android:screenOrientation="nosensor"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@ -177,7 +179,7 @@
android:screenOrientation="nosensor" android:screenOrientation="nosensor"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
@ -185,78 +187,78 @@
android:screenOrientation="nosensor" android:screenOrientation="nosensor"
android:theme="@style/NoTitle"> android:theme="@style/NoTitle">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<data android:scheme="linphone-config"/> <!-- Change if needed --> <data android:scheme="linphone-config" /> <!-- Change if needed -->
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<service <service
android:name=".LinphoneService" android:name=".LinphoneService"
android:label="@string/service_name"/> android:label="@string/service_name" />
<service <service
android:name=".sync.SyncService" android:name=".sync.SyncService"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.content.SyncAdapter"/> <action android:name="android.content.SyncAdapter" />
</intent-filter> </intent-filter>
<meta-data <meta-data
android:name="android.content.SyncAdapter" android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter"/> android:resource="@xml/syncadapter" />
<meta-data <meta-data
android:name="android.provider.CONTACTS_STRUCTURE" android:name="android.provider.CONTACTS_STRUCTURE"
android:resource="@xml/contacts"/> android:resource="@xml/contacts" />
</service> </service>
<service android:name=".sync.AuthenticationService"> <service android:name=".sync.AuthenticationService">
<intent-filter> <intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/> <action android:name="android.accounts.AccountAuthenticator" />
</intent-filter> </intent-filter>
<meta-data <meta-data
android:name="android.accounts.AccountAuthenticator" android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator"/> android:resource="@xml/authenticator" />
</service> </service>
<receiver android:name=".receivers.NetworkManager"> <receiver android:name=".receivers.NetworkManager">
<intent-filter> <intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver <receiver
android:name=".receivers.BluetoothManager" android:name=".receivers.BluetoothManager"
android:enabled="false"> android:enabled="false"></receiver>
</receiver>
<receiver android:name=".receivers.BootReceiver"> <receiver android:name=".receivers.BootReceiver">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN"/> <action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receivers.PhoneStateChangedReceiver"> <receiver android:name=".receivers.PhoneStateChangedReceiver">
<intent-filter android:priority="999"> <intent-filter android:priority="999">
<action android:name="android.intent.action.PHONE_STATE"/> <action android:name="android.intent.action.PHONE_STATE" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- This one needs to be registered from application --> <!-- This one needs to be registered from application -->
<receiver android:name=".receivers.KeepAliveReceiver"/> <receiver android:name=".receivers.KeepAliveReceiver" />
<receiver android:name=".receivers.HookReceiver" > <receiver android:name=".receivers.HookReceiver">
<intent-filter> <intent-filter>
<action android:name="com.base.module.phone.HOOKEVENT" /> <action android:name="com.base.module.phone.HOOKEVENT" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receivers.OutgoingCallReceiver" <receiver
android:permission="android.permission.PROCESS_OUTGOING_CALLS"> android:name=".receivers.OutgoingCallReceiver"
android:permission="android.permission.PROCESS_OUTGOING_CALLS">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter> </intent-filter>
@ -266,18 +268,20 @@
android:name=".receivers.AccountEnableReceiver" android:name=".receivers.AccountEnableReceiver"
android:permission="android.permission.USE_SIP"> android:permission="android.permission.USE_SIP">
<intent-filter> <intent-filter>
<action android:name="org.linphone.intent.ACCOUNTACTIVATE"/> <action android:name="org.linphone.intent.ACCOUNTACTIVATE" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<service android:name=".firebase.FirebaseIdService" android:exported="true"> <service
android:name=".firebase.FirebaseIdService"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter> </intent-filter>
</service> </service>
<service android:name=".firebase.FirebaseMessaging"> <service android:name=".firebase.FirebaseMessaging">
<intent-filter> <intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/> <action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter> </intent-filter>
</service> </service>
@ -288,10 +292,10 @@
android:grantUriPermissions="true"> android:grantUriPermissions="true">
<meta-data <meta-data
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/> android:resource="@xml/provider_paths" />
</provider> </provider>
<activity android:name=".utils.LinphoneGenericActivity"/> <activity android:name=".utils.LinphoneGenericActivity" />
<receiver <receiver
android:name=".notifications.NotificationBroadcastReceiver" android:name=".notifications.NotificationBroadcastReceiver"

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,8 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static android.content.Intent.ACTION_MAIN;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
@ -26,19 +28,13 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.assistant.RemoteProvisioningActivity; import org.linphone.assistant.RemoteProvisioningActivity;
import org.linphone.call.CallActivity; import org.linphone.call.CallActivity;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.FileUtils; import org.linphone.utils.FileUtils;
import org.linphone.utils.LinphoneUtils;
import static android.content.Intent.ACTION_MAIN; /** Launch Linphone main activity when Service is ready. */
/**
* Launch Linphone main activity when Service is ready.
*/
public class LinphoneLauncherActivity extends Activity { public class LinphoneLauncherActivity extends Activity {
private final String ACTION_CALL_LINPHONE = "org.linphone.intent.action.CallLaunched"; private final String ACTION_CALL_LINPHONE = "org.linphone.intent.action.CallLaunched";
@ -75,7 +71,10 @@ public class LinphoneLauncherActivity extends Activity {
} }
} else if (Intent.ACTION_VIEW.equals(action)) { } else if (Intent.ACTION_VIEW.equals(action)) {
if (LinphoneService.isReady()) { if (LinphoneService.isReady()) {
addressToCall = ContactsManager.getInstance().getAddressOrNumberForAndroidContact(getContentResolver(), intent.getData()); addressToCall =
ContactsManager.getInstance()
.getAddressOrNumberForAndroidContact(
getContentResolver(), intent.getData());
} else { } else {
uriToResolve = intent.getData(); uriToResolve = intent.getData();
} }
@ -104,72 +103,90 @@ public class LinphoneLauncherActivity extends Activity {
protected void onServiceReady() { protected void onServiceReady() {
final Class<? extends Activity> classToStart; final Class<? extends Activity> classToStart;
/*if (getResources().getBoolean(R.bool.show_tutorials_instead_of_app)) { /*if (getResources().getBoolean(R.bool.show_tutorials_instead_of_app)) {
classToStart = TutorialLauncherActivity.class; classToStart = TutorialLauncherActivity.class;
} else */ } else */
if (getResources().getBoolean(R.bool.display_sms_remote_provisioning_activity) && LinphonePreferences.instance().isFirstRemoteProvisioning()) { if (getResources().getBoolean(R.bool.display_sms_remote_provisioning_activity)
&& LinphonePreferences.instance().isFirstRemoteProvisioning()) {
classToStart = RemoteProvisioningActivity.class; classToStart = RemoteProvisioningActivity.class;
} else { } else {
classToStart = LinphoneActivity.class; classToStart = LinphoneActivity.class;
} }
mHandler.postDelayed(new Runnable() { mHandler.postDelayed(
@Override new Runnable() {
public void run() { @Override
Intent newIntent = new Intent(LinphoneLauncherActivity.this, classToStart); public void run() {
Intent intent = getIntent(); Intent newIntent = new Intent(LinphoneLauncherActivity.this, classToStart);
String stringFileShared = null; Intent intent = getIntent();
String stringUriFileShared = null; String stringFileShared = null;
Uri fileUri = null; String stringUriFileShared = null;
if (intent != null) { Uri fileUri = null;
String action = intent.getAction(); if (intent != null) {
String type = intent.getType(); String action = intent.getAction();
newIntent.setData(intent.getData()); String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) { newIntent.setData(intent.getData());
if (("text/plain").equals(type) && (String) intent.getStringExtra(Intent.EXTRA_TEXT) != null) { if (Intent.ACTION_SEND.equals(action) && type != null) {
stringFileShared = intent.getStringExtra(Intent.EXTRA_TEXT); if (("text/plain").equals(type)
newIntent.putExtra("msgShared", stringFileShared); && (String) intent.getStringExtra(Intent.EXTRA_TEXT)
} else { != null) {
fileUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); stringFileShared = intent.getStringExtra(Intent.EXTRA_TEXT);
stringUriFileShared = FileUtils.getFilePath(getBaseContext(), fileUri); newIntent.putExtra("msgShared", stringFileShared);
newIntent.putExtra("fileShared", stringUriFileShared); } else {
fileUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
stringUriFileShared =
FileUtils.getFilePath(getBaseContext(), fileUri);
newIntent.putExtra("fileShared", stringUriFileShared);
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
if (type.startsWith("image/")) {
// TODO : Manage multiple files sharing
}
} else if (ACTION_CALL_LINPHONE.equals(action)
&& (intent.getStringExtra("NumberToCall") != null)) {
String numberToCall = intent.getStringExtra("NumberToCall");
if (CallActivity.isInstanciated()) {
CallActivity.instance().startIncomingCallActivity();
} else {
LinphoneManager.getInstance()
.newOutgoingCall(numberToCall, null);
}
}
} }
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { if (uriToResolve != null) {
if (type.startsWith("image/")) { addressToCall =
//TODO : Manage multiple files sharing ContactsManager.getInstance()
.getAddressOrNumberForAndroidContact(
getContentResolver(), uriToResolve);
Log.i(
"LinphoneLauncher",
"Intent has uri to resolve : " + uriToResolve.toString());
uriToResolve = null;
} }
} else if (ACTION_CALL_LINPHONE.equals(action) && (intent.getStringExtra("NumberToCall") != null)) { if (addressToCall != null) {
String numberToCall = intent.getStringExtra("NumberToCall"); newIntent.putExtra("SipUriOrNumber", addressToCall);
if (CallActivity.isInstanciated()) { Log.i(
CallActivity.instance().startIncomingCallActivity(); "LinphoneLauncher",
} else { "Intent has address to call : " + addressToCall);
LinphoneManager.getInstance().newOutgoingCall(numberToCall, null); addressToCall = null;
}
startActivity(newIntent);
if (classToStart == LinphoneActivity.class
&& LinphoneActivity.isInstanciated()
&& (stringFileShared != null || fileUri != null)) {
if (stringFileShared != null) {
LinphoneActivity.instance()
.displayChat(null, stringFileShared, null);
} else if (fileUri != null) {
LinphoneActivity.instance()
.displayChat(null, null, stringUriFileShared);
}
} }
} }
} },
if (uriToResolve != null) { 1000);
addressToCall = ContactsManager.getInstance().getAddressOrNumberForAndroidContact(getContentResolver(), uriToResolve);
Log.i("LinphoneLauncher", "Intent has uri to resolve : " + uriToResolve.toString());
uriToResolve = null;
}
if (addressToCall != null) {
newIntent.putExtra("SipUriOrNumber", addressToCall);
Log.i("LinphoneLauncher", "Intent has address to call : " + addressToCall);
addressToCall = null;
}
startActivity(newIntent);
if (classToStart == LinphoneActivity.class && LinphoneActivity.isInstanciated() && (stringFileShared != null || fileUri != null)) {
if (stringFileShared != null) {
LinphoneActivity.instance().displayChat(null, stringFileShared, null);
} else if (fileUri != null) {
LinphoneActivity.instance().displayChat(null, null, stringUriFileShared);
}
}
}
}, 1000);
} }
private class ServiceWaitThread extends Thread { private class ServiceWaitThread extends Thread {
public void run() { public void run() {
while (!LinphoneService.isReady()) { while (!LinphoneService.isReady()) {
@ -179,16 +196,14 @@ public class LinphoneLauncherActivity extends Activity {
throw new RuntimeException("waiting thread sleep() has been interrupted"); throw new RuntimeException("waiting thread sleep() has been interrupted");
} }
} }
mHandler.post(new Runnable() { mHandler.post(
@Override new Runnable() {
public void run() { @Override
onServiceReady(); public void run() {
} onServiceReady();
}); }
});
mServiceThread = null; mServiceThread = null;
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,7 @@ import android.os.IBinder;
import android.os.SystemClock; import android.os.SystemClock;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.view.WindowManager; import android.view.WindowManager;
import java.util.ArrayList;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.core.Call.State; import org.linphone.core.Call.State;
@ -51,19 +51,19 @@ import org.linphone.notifications.NotificationsManager;
import org.linphone.receivers.BluetoothManager; import org.linphone.receivers.BluetoothManager;
import org.linphone.receivers.KeepAliveReceiver; import org.linphone.receivers.KeepAliveReceiver;
import org.linphone.settings.LinphonePreferences; import org.linphone.settings.LinphonePreferences;
import org.linphone.views.LinphoneOverlay;
import org.linphone.utils.LinphoneUtils; import org.linphone.utils.LinphoneUtils;
import org.linphone.views.LinphoneOverlay;
import java.util.ArrayList;
/** /**
* Linphone service, reacting to Incoming calls, ...<br /> * Linphone service, reacting to Incoming calls, ...<br>
* <p> *
* Roles include:<ul> * <p>Roles include:
* <li>Initializing LinphoneManager</li> *
* <li>Starting C libLinphone through LinphoneManager</li> * <ul>
* <li>Reacting to LinphoneManager state changes</li> * <li>Initializing LinphoneManager
* <li>Delegating GUI state change actions to GUI listener</li> * <li>Starting C libLinphone through LinphoneManager
* <li>Reacting to LinphoneManager state changes
* <li>Delegating GUI state change actions to GUI listener
*/ */
public final class LinphoneService extends Service { public final class LinphoneService extends Service {
/* Listener needs to be implemented in the Service as it calls /* Listener needs to be implemented in the Service as it calls
@ -72,6 +72,15 @@ public final class LinphoneService extends Service {
public static final String START_LINPHONE_LOGS = " ==== Phone information dump ===="; public static final String START_LINPHONE_LOGS = " ==== Phone information dump ====";
private static LinphoneService instance; private static LinphoneService instance;
public Handler mHandler = new Handler();
private boolean mTestDelayElapsed = true;
private CoreListenerStub mListener;
private WindowManager mWindowManager;
private LinphoneOverlay mOverlay;
private Application.ActivityLifecycleCallbacks mActivityCallbacks;
private NotificationsManager mNotificationManager;
private String incomingReceivedActivityName;
private Class<? extends Activity> incomingReceivedActivity = LinphoneActivity.class;
public static boolean isReady() { public static boolean isReady() {
return instance != null && instance.mTestDelayElapsed; return instance != null && instance.mTestDelayElapsed;
@ -83,17 +92,6 @@ public final class LinphoneService extends Service {
throw new RuntimeException("LinphoneService not instantiated yet"); throw new RuntimeException("LinphoneService not instantiated yet");
} }
public Handler mHandler = new Handler();
private boolean mTestDelayElapsed = true;
private CoreListenerStub mListener;
private WindowManager mWindowManager;
private LinphoneOverlay mOverlay;
private Application.ActivityLifecycleCallbacks mActivityCallbacks;
private NotificationsManager mNotificationManager;
private String incomingReceivedActivityName;
private Class<? extends Activity> incomingReceivedActivity = LinphoneActivity.class;
public NotificationsManager getNotificationManager() { public NotificationsManager getNotificationManager() {
return mNotificationManager; return mNotificationManager;
} }
@ -110,7 +108,8 @@ public final class LinphoneService extends Service {
protected void onBackgroundMode() { protected void onBackgroundMode() {
Log.i("App has entered background mode"); Log.i("App has entered background mode");
if (LinphonePreferences.instance() != null && LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) { if (LinphonePreferences.instance() != null
&& LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) {
if (LinphoneManager.isInstanciated()) if (LinphoneManager.isInstanciated())
LinphoneManager.getInstance().subscribeFriendList(false); LinphoneManager.getInstance().subscribeFriendList(false);
} }
@ -121,7 +120,8 @@ public final class LinphoneService extends Service {
protected void onForegroundMode() { protected void onForegroundMode() {
Log.i("App has left background mode"); Log.i("App has left background mode");
if (LinphonePreferences.instance() != null && LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) { if (LinphonePreferences.instance() != null
&& LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) {
if (LinphoneManager.isInstanciated()) if (LinphoneManager.isInstanciated())
LinphoneManager.getInstance().subscribeFriendList(true); LinphoneManager.getInstance().subscribeFriendList(true);
} }
@ -132,7 +132,8 @@ public final class LinphoneService extends Service {
private void setupActivityMonitor() { private void setupActivityMonitor() {
if (mActivityCallbacks != null) return; if (mActivityCallbacks != null) return;
getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks = new ActivityMonitor()); getApplication()
.registerActivityLifecycleCallbacks(mActivityCallbacks = new ActivityMonitor());
} }
@Override @Override
@ -152,69 +153,101 @@ public final class LinphoneService extends Service {
instance = this; // instance is ready once linphone manager has been created instance = this; // instance is ready once linphone manager has been created
mNotificationManager = new NotificationsManager(this); mNotificationManager = new NotificationsManager(this);
LinphoneManager.getLc().addListener(mListener = new CoreListenerStub() { LinphoneManager.getLc()
@Override .addListener(
public void onCallStateChanged(Core lc, Call call, Call.State state, String message) { mListener =
if (instance == null) { new CoreListenerStub() {
Log.i("Service not ready, discarding call state change to ", state.toString()); @Override
return; public void onCallStateChanged(
} Core lc, Call call, Call.State state, String message) {
if (instance == null) {
Log.i(
"Service not ready, discarding call state change to ",
state.toString());
return;
}
if (getResources().getBoolean(R.bool.enable_call_notification)) { if (getResources()
mNotificationManager.displayCallNotification(call); .getBoolean(R.bool.enable_call_notification)) {
} mNotificationManager.displayCallNotification(call);
}
if (state == Call.State.IncomingReceived) { if (state == Call.State.IncomingReceived) {
if (!LinphoneManager.getInstance().getCallGsmON()) if (!LinphoneManager.getInstance().getCallGsmON())
onIncomingReceived(); onIncomingReceived();
} }
if (state == State.End || state == State.Released || state == State.Error) { if (state == State.End
destroyOverlay(); || state == State.Released
} || state == State.Error) {
destroyOverlay();
}
if (state == State.Released && call.getCallLog().getStatus() == Call.Status.Missed) { if (state == State.Released
mNotificationManager.displayMissedCallNotification(call); && call.getCallLog().getStatus()
} == Call.Status.Missed) {
} mNotificationManager.displayMissedCallNotification(
call);
}
}
@Override @Override
public void onGlobalStateChanged(Core lc, GlobalState state, String message) { public void onGlobalStateChanged(
//TODO global state if ON Core lc, GlobalState state, String message) {
} // TODO global state if ON
}
@Override @Override
public void onRegistrationStateChanged(Core lc, ProxyConfig cfg, RegistrationState state, String smessage) { public void onRegistrationStateChanged(
//TODO registration status Core lc,
} ProxyConfig cfg,
}); RegistrationState state,
String smessage) {
// TODO registration status
}
});
if (Version.sdkAboveOrEqual(Version.API26_O_80) && intent.getBooleanExtra("ForceStartForeground", false)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)
&& intent.getBooleanExtra("ForceStartForeground", false)) {
mNotificationManager.startForeground(); mNotificationManager.startForeground();
} }
if (!Version.sdkAboveOrEqual(Version.API26_O_80) if (!Version.sdkAboveOrEqual(Version.API26_O_80)
|| (ContactsManager.getInstance() != null && ContactsManager.getInstance().hasContactsAccess())) { || (ContactsManager.getInstance() != null
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, ContactsManager.getInstance()); && ContactsManager.getInstance().hasContactsAccess())) {
getContentResolver()
.registerContentObserver(
ContactsContract.Contacts.CONTENT_URI,
true,
ContactsManager.getInstance());
} }
if (!mTestDelayElapsed) { if (!mTestDelayElapsed) {
// Only used when testing. Simulates a 5 seconds delay for launching service // Only used when testing. Simulates a 5 seconds delay for launching service
mHandler.postDelayed(new Runnable() { mHandler.postDelayed(
@Override new Runnable() {
public void run() { @Override
mTestDelayElapsed = true; public void run() {
} mTestDelayElapsed = true;
}, 5000); }
},
5000);
} }
//make sure the application will at least wakes up every 10 mn // make sure the application will at least wakes up every 10 mn
if (LinphonePreferences.instance().isBackgroundModeEnabled() && if (LinphonePreferences.instance().isBackgroundModeEnabled()
(!LinphonePreferences.instance().isPushNotificationEnabled() || !LinphoneManager.getInstance().hasLinphoneAccount())) { && (!LinphonePreferences.instance().isPushNotificationEnabled()
|| !LinphoneManager.getInstance().hasLinphoneAccount())) {
Intent keepAliveIntent = new Intent(this, KeepAliveReceiver.class); Intent keepAliveIntent = new Intent(this, KeepAliveReceiver.class);
PendingIntent keepAlivePendingIntent = PendingIntent.getBroadcast(this, 0, keepAliveIntent, PendingIntent.FLAG_ONE_SHOT); PendingIntent keepAlivePendingIntent =
AlarmManager alarmManager = ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)); PendingIntent.getBroadcast(
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 600000, keepAlivePendingIntent); this, 0, keepAliveIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager =
((AlarmManager) this.getSystemService(Context.ALARM_SERVICE));
alarmManager.setExact(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 600000,
keepAlivePendingIntent);
} }
BluetoothManager.getInstance().initBluetooth(); BluetoothManager.getInstance().initBluetooth();
@ -240,9 +273,11 @@ public final class LinphoneService extends Service {
dumpDeviceInformation(); dumpDeviceInformation();
dumpInstalledLinphoneInformation(); dumpInstalledLinphoneInformation();
incomingReceivedActivityName = LinphonePreferences.instance().getActivityToLaunchOnIncomingReceived(); incomingReceivedActivityName =
LinphonePreferences.instance().getActivityToLaunchOnIncomingReceived();
try { try {
incomingReceivedActivity = (Class<? extends Activity>) Class.forName(incomingReceivedActivityName); incomingReceivedActivity =
(Class<? extends Activity>) Class.forName(incomingReceivedActivityName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
Log.e(e); Log.e(e);
} }
@ -356,17 +391,19 @@ public final class LinphoneService extends Service {
try { try {
incomingReceivedActivity = (Class<? extends Activity>) Class.forName(activityName); incomingReceivedActivity = (Class<? extends Activity>) Class.forName(activityName);
incomingReceivedActivityName = activityName; incomingReceivedActivityName = activityName;
LinphonePreferences.instance().setActivityToLaunchOnIncomingReceived(incomingReceivedActivityName); LinphonePreferences.instance()
.setActivityToLaunchOnIncomingReceived(incomingReceivedActivityName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
Log.e(e); Log.e(e);
} }
} }
protected void onIncomingReceived() { protected void onIncomingReceived() {
//wakeup linphone // wakeup linphone
startActivity(new Intent() startActivity(
.setClass(this, incomingReceivedActivity) new Intent()
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); .setClass(this, incomingReceivedActivity)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} }
/*Believe me or not, but knowing the application visibility state on Android is a nightmare. /*Believe me or not, but knowing the application visibility state on Android is a nightmare.
@ -376,34 +413,12 @@ public final class LinphoneService extends Service {
private ArrayList<Activity> activities = new ArrayList<>(); private ArrayList<Activity> activities = new ArrayList<>();
private boolean mActive = false; private boolean mActive = false;
private int mRunningActivities = 0; private int mRunningActivities = 0;
class InactivityChecker implements Runnable {
private boolean isCanceled;
public void cancel() {
isCanceled = true;
}
@Override
public void run() {
synchronized (LinphoneService.this) {
if (!isCanceled) {
if (ActivityMonitor.this.mRunningActivities == 0 && mActive) {
mActive = false;
LinphoneService.this.onBackgroundMode();
}
}
}
}
}
private InactivityChecker mLastChecker; private InactivityChecker mLastChecker;
@Override @Override
public synchronized void onActivityCreated(Activity activity, Bundle savedInstanceState) { public synchronized void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Activity created:" + activity); Log.i("Activity created:" + activity);
if (!activities.contains(activity)) if (!activities.contains(activity)) activities.add(activity);
activities.add(activity);
} }
@Override @Override
@ -419,7 +434,6 @@ public final class LinphoneService extends Service {
Log.i("runningActivities=" + mRunningActivities); Log.i("runningActivities=" + mRunningActivities);
checkActivity(); checkActivity();
} }
} }
@Override @Override
@ -430,7 +444,6 @@ public final class LinphoneService extends Service {
Log.i("runningActivities=" + mRunningActivities); Log.i("runningActivities=" + mRunningActivities);
checkActivity(); checkActivity();
} }
} }
@Override @Override
@ -439,9 +452,7 @@ public final class LinphoneService extends Service {
} }
@Override @Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
}
@Override @Override
public synchronized void onActivityDestroyed(Activity activity) { public synchronized void onActivityDestroyed(Activity activity) {
@ -471,6 +482,25 @@ public final class LinphoneService extends Service {
} }
} }
} }
class InactivityChecker implements Runnable {
private boolean isCanceled;
public void cancel() {
isCanceled = true;
}
@Override
public void run() {
synchronized (LinphoneService.this) {
if (!isCanceled) {
if (ActivityMonitor.this.mRunningActivities == 0 && mActive) {
mActive = false;
LinphoneService.this.onBackgroundMode();
}
}
}
}
}
} }
} }

View file

@ -36,8 +36,6 @@ import android.content.pm.PackageManager;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -51,15 +49,16 @@ import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import org.linphone.LinphoneManager; import androidx.core.content.ContextCompat;
import org.linphone.settings.LinphonePreferences; import java.util.ArrayList;
import org.linphone.settings.LinphonePreferences.AccountBuilder; import java.util.Arrays;
import org.linphone.LinphoneService; import java.util.List;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneLauncherActivity; import org.linphone.LinphoneLauncherActivity;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneService;
import org.linphone.R;
import org.linphone.core.AccountCreator; import org.linphone.core.AccountCreator;
import org.linphone.core.AccountCreatorListener; import org.linphone.core.AccountCreatorListener;
import org.linphone.core.Address; import org.linphone.core.Address;
@ -77,13 +76,19 @@ import org.linphone.core.tools.OpenH264DownloadHelper;
import org.linphone.fragments.StatusFragment; import org.linphone.fragments.StatusFragment;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version; import org.linphone.mediastream.Version;
import org.linphone.settings.LinphonePreferences;
import org.linphone.settings.LinphonePreferences.AccountBuilder;
import org.linphone.utils.LinphoneUtils;
import java.util.ArrayList; public class AssistantActivity extends Activity
import java.util.Arrays; implements OnClickListener,
import java.util.List; ActivityCompat.OnRequestPermissionsResultCallback,
AccountCreatorListener {
public class AssistantActivity extends Activity implements OnClickListener, ActivityCompat.OnRequestPermissionsResultCallback, AccountCreatorListener { private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201;
private static AssistantActivity instance; private static AssistantActivity instance;
public DialPlan country;
public String phone_number;
public String email;
private ImageView back, cancel; private ImageView back, cancel;
private AssistantFragmentsEnum currentFragment; private AssistantFragmentsEnum currentFragment;
private AssistantFragmentsEnum lastFragment; private AssistantFragmentsEnum lastFragment;
@ -98,13 +103,12 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
private Dialog dialog; private Dialog dialog;
private boolean remoteProvisioningInProgress; private boolean remoteProvisioningInProgress;
private boolean echoCancellerAlreadyDone; private boolean echoCancellerAlreadyDone;
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201;
private AccountCreator mAccountCreator; private AccountCreator mAccountCreator;
private CountryListAdapter countryListAdapter; private CountryListAdapter countryListAdapter;
public DialPlan country; public static AssistantActivity instance() {
public String phone_number; return instance;
public String email; }
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -118,20 +122,29 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
if (getIntent().getBooleanExtra("LinkPhoneNumber", false)) { if (getIntent().getBooleanExtra("LinkPhoneNumber", false)) {
isLink = true; isLink = true;
if (getIntent().getBooleanExtra("FromPref", false)) if (getIntent().getBooleanExtra("FromPref", false)) fromPref = true;
fromPref = true;
displayCreateAccount(); displayCreateAccount();
} else { } else {
firstFragment = getResources().getBoolean(R.bool.assistant_use_linphone_login_as_first_fragment) ? AssistantFragmentsEnum.LINPHONE_LOGIN : AssistantFragmentsEnum.WELCOME; firstFragment =
getResources().getBoolean(R.bool.assistant_use_linphone_login_as_first_fragment)
? AssistantFragmentsEnum.LINPHONE_LOGIN
: AssistantFragmentsEnum.WELCOME;
if (firstFragment == AssistantFragmentsEnum.WELCOME) { if (firstFragment == AssistantFragmentsEnum.WELCOME) {
firstFragment = getResources().getBoolean(R.bool.assistant_use_create_linphone_account_as_first_fragment) ? AssistantFragmentsEnum.CREATE_ACCOUNT : AssistantFragmentsEnum.WELCOME; firstFragment =
getResources()
.getBoolean(
R.bool.assistant_use_create_linphone_account_as_first_fragment)
? AssistantFragmentsEnum.CREATE_ACCOUNT
: AssistantFragmentsEnum.WELCOME;
} }
if (findViewById(R.id.fragment_container) != null) { if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState == null) { if (savedInstanceState == null) {
display(firstFragment); display(firstFragment);
} else { } else {
currentFragment = (AssistantFragmentsEnum) savedInstanceState.getSerializable("CurrentFragment"); currentFragment =
(AssistantFragmentsEnum)
savedInstanceState.getSerializable("CurrentFragment");
} }
} }
} }
@ -144,56 +157,70 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
status.enableSideMenu(false); status.enableSideMenu(false);
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) { if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
mAccountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); mAccountCreator =
LinphoneManager.getLc()
.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
mAccountCreator.setListener(this); mAccountCreator.setListener(this);
} }
countryListAdapter = new CountryListAdapter(getApplicationContext()); countryListAdapter = new CountryListAdapter(getApplicationContext());
mListener = new CoreListenerStub() { mListener =
new CoreListenerStub() {
@Override @Override
public void onConfiguringStatus(Core lc, final ConfiguringState state, String message) { public void onConfiguringStatus(
if (progress != null) progress.dismiss(); Core lc, final ConfiguringState state, String message) {
if (state == ConfiguringState.Successful) { if (progress != null) progress.dismiss();
goToLinphoneActivity(); if (state == ConfiguringState.Successful) {
} else if (state == ConfiguringState.Failed) { goToLinphoneActivity();
Toast.makeText(AssistantActivity.instance(), getString(R.string.remote_provisioning_failure), Toast.LENGTH_LONG).show(); } else if (state == ConfiguringState.Failed) {
} Toast.makeText(
} AssistantActivity.instance(),
getString(R.string.remote_provisioning_failure),
@Override Toast.LENGTH_LONG)
public void onRegistrationStateChanged(Core lc, ProxyConfig cfg, RegistrationState state, String smessage) { .show();
if (remoteProvisioningInProgress) {
if (progress != null) progress.dismiss();
if (state == RegistrationState.Ok) {
remoteProvisioningInProgress = false;
success();
}
} else if (accountCreated && !newAccount) {
if (address != null && address.asString().equals(cfg.getIdentityAddress().asString())) {
if (state == RegistrationState.Ok) {
if (progress != null) progress.dismiss();
if (getResources().getBoolean(R.bool.use_phone_number_validation)
&& cfg.getDomain().equals(getString(R.string.default_domain))
&& LinphoneManager.getLc().getDefaultProxyConfig() != null) {
loadAccountCreator(cfg).isAccountExist();
} else {
success();
}
} else if (state == RegistrationState.Failed) {
if (progress != null) progress.dismiss();
if (dialog == null || !dialog.isShowing()) {
dialog = createErrorDialog(cfg, smessage);
dialog.setCancelable(false);
dialog.show();
}
} else if (!(state == RegistrationState.Progress)) {
if (progress != null) progress.dismiss();
} }
} }
}
} @Override
}; public void onRegistrationStateChanged(
Core lc, ProxyConfig cfg, RegistrationState state, String smessage) {
if (remoteProvisioningInProgress) {
if (progress != null) progress.dismiss();
if (state == RegistrationState.Ok) {
remoteProvisioningInProgress = false;
success();
}
} else if (accountCreated && !newAccount) {
if (address != null
&& address.asString()
.equals(cfg.getIdentityAddress().asString())) {
if (state == RegistrationState.Ok) {
if (progress != null) progress.dismiss();
if (getResources()
.getBoolean(R.bool.use_phone_number_validation)
&& cfg.getDomain()
.equals(getString(R.string.default_domain))
&& LinphoneManager.getLc().getDefaultProxyConfig()
!= null) {
loadAccountCreator(cfg).isAccountExist();
} else {
success();
}
} else if (state == RegistrationState.Failed) {
if (progress != null) progress.dismiss();
if (dialog == null || !dialog.isShowing()) {
dialog = createErrorDialog(cfg, smessage);
dialog.setCancelable(false);
dialog.show();
}
} else if (!(state == RegistrationState.Progress)) {
if (progress != null) progress.dismiss();
}
}
}
}
};
instance = this; instance = this;
} }
@ -224,10 +251,6 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
public static AssistantActivity instance() {
return instance;
}
public void updateStatusFragment(StatusFragment fragment) { public void updateStatusFragment(StatusFragment fragment) {
status = fragment; status = fragment;
} }
@ -315,7 +338,8 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
public void hideKeyboard() { public void hideKeyboard() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
View view = this.getCurrentFocus(); View view = this.getCurrentFocus();
if (imm != null && view != null) { if (imm != null && view != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0); imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
@ -328,20 +352,34 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
public void checkAndRequestPermission(String permission, int result) { public void checkAndRequestPermission(String permission, int result) {
int permissionGranted = getPackageManager().checkPermission(permission, getPackageName()); int permissionGranted = getPackageManager().checkPermission(permission, getPackageName());
Log.i("[Permission] " + permission + " is " + (permissionGranted == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); Log.i(
"[Permission] "
+ permission
+ " is "
+ (permissionGranted == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
if (permissionGranted != PackageManager.PERMISSION_GRANTED) { if (permissionGranted != PackageManager.PERMISSION_GRANTED) {
if (LinphonePreferences.instance().firstTimeAskingForPermission(permission) || ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) { if (LinphonePreferences.instance().firstTimeAskingForPermission(permission)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
Log.i("[Permission] Asking for " + permission); Log.i("[Permission] Asking for " + permission);
ActivityCompat.requestPermissions(this, new String[]{permission}, result); ActivityCompat.requestPermissions(this, new String[] {permission}, result);
} }
} }
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
for (int i = 0; i < permissions.length; i++) { for (int i = 0; i < permissions.length; i++) {
Log.i("[Permission] " + permissions[i] + " is " + (grantResults[i] == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); Log.i(
"[Permission] "
+ permissions[i]
+ " is "
+ (grantResults[i] == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
} }
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) { if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
@ -354,8 +392,14 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
private void launchEchoCancellerCalibration(boolean sendEcCalibrationResult) { private void launchEchoCancellerCalibration(boolean sendEcCalibrationResult) {
int recordAudio = getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()); int recordAudio =
Log.i("[Permission] Record audio permission is " + (recordAudio == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); getPackageManager()
.checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName());
Log.i(
"[Permission] Record audio permission is "
+ (recordAudio == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
if (recordAudio == PackageManager.PERMISSION_GRANTED) { if (recordAudio == PackageManager.PERMISSION_GRANTED) {
EchoCancellerCalibrationFragment fragment = new EchoCancellerCalibrationFragment(); EchoCancellerCalibrationFragment fragment = new EchoCancellerCalibrationFragment();
@ -385,22 +429,23 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
address = addr; address = addr;
proxyConfig.edit(); proxyConfig.edit();
proxyConfig.setIdentityAddress(addr); proxyConfig.setIdentityAddress(addr);
if (accountCreator.getPhoneNumber() != null && accountCreator.getPhoneNumber().length() > 0) if (accountCreator.getPhoneNumber() != null && accountCreator.getPhoneNumber().length() > 0)
proxyConfig.setDialPrefix(org.linphone.core.Utils.getPrefixFromE164(accountCreator.getPhoneNumber())); proxyConfig.setDialPrefix(
org.linphone.core.Utils.getPrefixFromE164(accountCreator.getPhoneNumber()));
proxyConfig.done(); proxyConfig.done();
authInfo = Factory.instance().createAuthInfo( authInfo =
accountCreator.getUsername(), Factory.instance()
null, .createAuthInfo(
accountCreator.getPassword(), accountCreator.getUsername(),
accountCreator.getHa1(), null,
proxyConfig.getRealm(), accountCreator.getPassword(),
proxyConfig.getDomain()); accountCreator.getHa1(),
proxyConfig.getRealm(),
proxyConfig.getDomain());
lc.addProxyConfig(proxyConfig); lc.addProxyConfig(proxyConfig);
@ -412,9 +457,11 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
LinphonePreferences.instance().setPushNotificationEnabled(true); LinphonePreferences.instance().setPushNotificationEnabled(true);
if (LinphonePreferences.instance() != null) if (LinphonePreferences.instance() != null)
mPrefs.enabledFriendlistSubscription(getResources().getBoolean(R.bool.use_friendlist_subscription)); mPrefs.enabledFriendlistSubscription(
getResources().getBoolean(R.bool.use_friendlist_subscription));
LinphoneManager.getInstance().subscribeFriendList(getResources().getBoolean(R.bool.use_friendlist_subscription)); LinphoneManager.getInstance()
.subscribeFriendList(getResources().getBoolean(R.bool.use_friendlist_subscription));
if (!newAccount) { if (!newAccount) {
displayRegistrationInProgressDialog(); displayRegistrationInProgressDialog();
@ -423,12 +470,22 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
public void linphoneLogIn(AccountCreator accountCreator) { public void linphoneLogIn(AccountCreator accountCreator) {
LinphoneManager.getLc().getConfig().loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile()); LinphoneManager.getLc()
.getConfig()
.loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile());
configureProxyConfig(accountCreator); configureProxyConfig(accountCreator);
} }
public void genericLogIn(String username, String userid, String password, String displayname, String prefix, String domain, TransportType transport) { public void genericLogIn(
saveCreatedAccount(username, userid, password, displayname, null, prefix, domain, transport); String username,
String userid,
String password,
String displayname,
String prefix,
String domain,
TransportType transport) {
saveCreatedAccount(
username, userid, password, displayname, null, prefix, domain, transport);
} }
private void display(AssistantFragmentsEnum fragment) { private void display(AssistantFragmentsEnum fragment) {
@ -503,15 +560,17 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
private void launchDownloadCodec() { private void launchDownloadCodec() {
if (OpenH264DownloadHelper.isOpenH264DownloadEnabled()) { if (OpenH264DownloadHelper.isOpenH264DownloadEnabled()) {
OpenH264DownloadHelper downloadHelper = Factory.instance().createOpenH264DownloadHelper(this); OpenH264DownloadHelper downloadHelper =
if (Version.getCpuAbis().contains("armeabi-v7a") && !Version.getCpuAbis().contains("x86") && !downloadHelper.isCodecFound()) { Factory.instance().createOpenH264DownloadHelper(this);
if (Version.getCpuAbis().contains("armeabi-v7a")
&& !Version.getCpuAbis().contains("x86")
&& !downloadHelper.isCodecFound()) {
CodecDownloaderFragment codecFragment = new CodecDownloaderFragment(); CodecDownloaderFragment codecFragment = new CodecDownloaderFragment();
changeFragment(codecFragment); changeFragment(codecFragment);
currentFragment = AssistantFragmentsEnum.DOWNLOAD_CODEC; currentFragment = AssistantFragmentsEnum.DOWNLOAD_CODEC;
back.setVisibility(View.VISIBLE); back.setVisibility(View.VISIBLE);
cancel.setEnabled(false); cancel.setEnabled(false);
} else } else goToLinphoneActivity();
goToLinphoneActivity();
} else { } else {
goToLinphoneActivity(); goToLinphoneActivity();
} }
@ -523,11 +582,20 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
public String getPhoneWithCountry() { public String getPhoneWithCountry() {
if (country == null || phone_number == null) return ""; if (country == null || phone_number == null) return "";
String phoneNumberWithCountry = country.getCountryCallingCode() + phone_number.replace("\\D", ""); String phoneNumberWithCountry =
country.getCountryCallingCode() + phone_number.replace("\\D", "");
return phoneNumberWithCountry; return phoneNumberWithCountry;
} }
public void saveCreatedAccount(String username, String userid, String password, String displayname, String ha1, String prefix, String domain, TransportType transport) { public void saveCreatedAccount(
String username,
String userid,
String password,
String displayname,
String ha1,
String prefix,
String domain,
TransportType transport) {
username = LinphoneUtils.getDisplayableUsernameFromAddress(username); username = LinphoneUtils.getDisplayableUsernameFromAddress(username);
domain = LinphoneUtils.getDisplayableUsernameFromAddress(domain); domain = LinphoneUtils.getDisplayableUsernameFromAddress(domain);
@ -535,13 +603,14 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
String identity = "sip:" + username + "@" + domain; String identity = "sip:" + username + "@" + domain;
address = Factory.instance().createAddress(identity); address = Factory.instance().createAddress(identity);
AccountBuilder builder = new AccountBuilder(LinphoneManager.getLc()) AccountBuilder builder =
.setUsername(username) new AccountBuilder(LinphoneManager.getLc())
.setDomain(domain) .setUsername(username)
.setHa1(ha1) .setDomain(domain)
.setUserid(userid) .setHa1(ha1)
.setDisplayName(displayname) .setUserid(userid)
.setPassword(password); .setDisplayName(displayname)
.setPassword(password);
if (prefix != null) { if (prefix != null) {
builder.setPrefix(prefix); builder.setPrefix(prefix);
@ -549,9 +618,7 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
String forcedProxy = ""; String forcedProxy = "";
if (!TextUtils.isEmpty(forcedProxy)) { if (!TextUtils.isEmpty(forcedProxy)) {
builder.setServerAddr(forcedProxy) builder.setServerAddr(forcedProxy).setOutboundProxyEnabled(true).setAvpfRrInterval(5);
.setOutboundProxyEnabled(true)
.setAvpfRrInterval(5);
} }
if (transport != null) { if (transport != null) {
builder.setTransport(transport); builder.setTransport(transport);
@ -573,7 +640,10 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
progress = ProgressDialog.show(this, null, null); progress = ProgressDialog.show(this, null, null);
Drawable d = new ColorDrawable(ContextCompat.getColor(this, R.color.colorE)); Drawable d = new ColorDrawable(ContextCompat.getColor(this, R.color.colorE));
d.setAlpha(200); d.setAlpha(200);
progress.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); progress.getWindow()
.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
progress.getWindow().setBackgroundDrawable(d); progress.getWindow().setBackgroundDrawable(d);
progress.setContentView(R.layout.progress_dialog); progress.setContentView(R.layout.progress_dialog);
progress.show(); progress.show();
@ -586,7 +656,10 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
progress = ProgressDialog.show(this, null, null); progress = ProgressDialog.show(this, null, null);
Drawable d = new ColorDrawable(ContextCompat.getColor(this, R.color.colorE)); Drawable d = new ColorDrawable(ContextCompat.getColor(this, R.color.colorE));
d.setAlpha(200); d.setAlpha(200);
progress.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); progress.getWindow()
.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
progress.getWindow().setBackgroundDrawable(d); progress.getWindow().setBackgroundDrawable(d);
progress.setContentView(R.layout.progress_dialog); progress.setContentView(R.layout.progress_dialog);
progress.show(); progress.show();
@ -606,7 +679,8 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
back.setVisibility(View.INVISIBLE); back.setVisibility(View.INVISIBLE);
} }
public void displayAssistantCodeConfirm(String username, String phone, String dialcode, boolean recoverAccount) { public void displayAssistantCodeConfirm(
String username, String phone, String dialcode, boolean recoverAccount) {
CreateAccountCodeActivationFragment fragment = new CreateAccountCodeActivationFragment(); CreateAccountCodeActivationFragment fragment = new CreateAccountCodeActivationFragment();
newAccount = true; newAccount = true;
Bundle extras = new Bundle(); Bundle extras = new Bundle();
@ -636,7 +710,8 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
public void isAccountVerified(String username) { public void isAccountVerified(String username) {
Toast.makeText(this, getString(R.string.assistant_account_validated), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.assistant_account_validated), Toast.LENGTH_LONG)
.show();
hideKeyboard(); hideKeyboard();
success(); success();
} }
@ -652,19 +727,25 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
builder.setMessage(message) builder.setMessage(message)
.setTitle(proxy.getState().toString()) .setTitle(proxy.getState().toString())
.setPositiveButton(getString(R.string.continue_text), new DialogInterface.OnClickListener() { .setPositiveButton(
public void onClick(DialogInterface dialog, int id) { getString(R.string.continue_text),
success(); new DialogInterface.OnClickListener() {
} public void onClick(DialogInterface dialog, int id) {
}) success();
.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { }
public void onClick(DialogInterface dialog, int id) { })
LinphoneManager.getLc().removeProxyConfig(LinphoneManager.getLc().getDefaultProxyConfig()); .setNegativeButton(
LinphonePreferences.instance().resetDefaultProxyConfig(); getString(R.string.cancel),
LinphoneManager.getLc().refreshRegisters(); new DialogInterface.OnClickListener() {
dialog.dismiss(); public void onClick(DialogInterface dialog, int id) {
} LinphoneManager.getLc()
}); .removeProxyConfig(
LinphoneManager.getLc().getDefaultProxyConfig());
LinphonePreferences.instance().resetDefaultProxyConfig();
LinphoneManager.getLc().refreshRegisters();
dialog.dismiss();
}
});
return builder.show(); return builder.show();
} }
@ -679,7 +760,10 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
private void goToLinphoneActivity() { private void goToLinphoneActivity() {
mPrefs.firstLaunchSuccessful(); mPrefs.firstLaunchSuccessful();
startActivity(new Intent().setClass(this, LinphoneActivity.class).putExtra("isNewProxyConfig", true)); startActivity(
new Intent()
.setClass(this, LinphoneActivity.class)
.putExtra("isNewProxyConfig", true));
finish(); finish();
} }
@ -697,7 +781,12 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
mPrefs.firstLaunchSuccessful(); mPrefs.firstLaunchSuccessful();
Intent mStartActivity = new Intent(this, LinphoneLauncherActivity.class); Intent mStartActivity = new Intent(this, LinphoneLauncherActivity.class);
PendingIntent mPendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent mPendingIntent =
PendingIntent.getActivity(
this,
(int) System.currentTimeMillis(),
mStartActivity,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); AlarmManager mgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 500, mPendingIntent); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 500, mPendingIntent);
@ -709,7 +798,8 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
@Override @Override
public void onIsAccountExist(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountExist(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (status.equals(AccountCreator.Status.AccountExistWithAlias)) { if (status.equals(AccountCreator.Status.AccountExistWithAlias)) {
success(); success();
} else { } else {
@ -720,57 +810,48 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
} }
@Override @Override
public void onCreateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onCreateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onActivateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onLinkAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onLinkAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onActivateAlias(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAlias(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAccountActivated(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountActivated(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onRecoverAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onRecoverAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAccountLinked(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountLinked(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAliasUsed(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAliasUsed(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onUpdateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onUpdateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
public CountryListAdapter getCountryListAdapter() { public CountryListAdapter getCountryListAdapter() {
return countryListAdapter; return countryListAdapter;
} }
/** /**
* This class reads a JSON file containing Country-specific phone number description, * This class reads a JSON file containing Country-specific phone number description, and allows
* and allows to present them into a ListView * to present them into a ListView
*/ */
public class CountryListAdapter extends BaseAdapter implements Filterable { public class CountryListAdapter extends BaseAdapter implements Filterable {
@ -789,12 +870,10 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
mInflater = inf; mInflater = inf;
} }
public DialPlan getCountryFromCountryCode(String countryCode) { public DialPlan getCountryFromCountryCode(String countryCode) {
countryCode = (countryCode.startsWith("+")) ? countryCode.substring(1) : countryCode; countryCode = (countryCode.startsWith("+")) ? countryCode.substring(1) : countryCode;
for (DialPlan c : allCountries) { for (DialPlan c : allCountries) {
if (c.getCountryCallingCode().compareTo(countryCode) == 0) if (c.getCountryCallingCode().compareTo(countryCode) == 0) return c;
return c;
} }
return null; return null;
} }
@ -831,7 +910,10 @@ public class AssistantActivity extends Activity implements OnClickListener, Acti
TextView dial_code = (TextView) view.findViewById(R.id.country_prefix); TextView dial_code = (TextView) view.findViewById(R.id.country_prefix);
if (context != null) if (context != null)
dial_code.setText(String.format(context.getString(R.string.country_code), c.getCountryCallingCode())); dial_code.setText(
String.format(
context.getString(R.string.country_code),
c.getCountryCallingCode()));
view.setTag(c); view.setTag(c);
return view; return view;

View file

@ -29,7 +29,6 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.PayloadType; import org.linphone.core.PayloadType;
@ -48,8 +47,8 @@ public class CodecDownloaderFragment extends Fragment {
private TextView downloadingInfo; private TextView downloadingInfo;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.assistant_codec_downloader, container, false); final View view = inflater.inflate(R.layout.assistant_codec_downloader, container, false);
question = view.findViewById(R.id.question); question = view.findViewById(R.id.question);
@ -61,101 +60,112 @@ public class CodecDownloaderFragment extends Fragment {
bar = view.findViewById(R.id.progressBar); bar = view.findViewById(R.id.progressBar);
downloadingInfo = view.findViewById(R.id.downloadingInfo); downloadingInfo = view.findViewById(R.id.downloadingInfo);
final OpenH264DownloadHelper codecDownloader = LinphoneManager.getInstance().getOpenH264DownloadHelper(); final OpenH264DownloadHelper codecDownloader =
final OpenH264DownloadHelperListener codecListener = new OpenH264DownloadHelperListener() { LinphoneManager.getInstance().getOpenH264DownloadHelper();
final OpenH264DownloadHelperListener codecListener =
new OpenH264DownloadHelperListener() {
@Override
public void OnProgress(final int current, final int max) {
mHandler.post(new Runnable() {
@Override @Override
public void run() { public void OnProgress(final int current, final int max) {
if (current <= max) { mHandler.post(
hideAllItems(); new Runnable() {
downloadingInfo.setText(current + " / " + max); @Override
downloadingInfo.setVisibility(View.VISIBLE); public void run() {
downloading.setVisibility(View.VISIBLE); if (current <= max) {
bar.setMax(max); hideAllItems();
bar.setProgress(current); downloadingInfo.setText(current + " / " + max);
bar.setVisibility(View.VISIBLE); downloadingInfo.setVisibility(View.VISIBLE);
} else { downloading.setVisibility(View.VISIBLE);
hideAllItems(); bar.setMax(max);
downloaded.setVisibility(View.VISIBLE); bar.setProgress(current);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { bar.setVisibility(View.VISIBLE);
enabledH264(true); } else {
LinphoneManager.getLc().reloadMsPlugins(AssistantActivity.instance().getApplicationInfo().nativeLibraryDir); hideAllItems();
AssistantActivity.instance().endDownloadCodec(); downloaded.setVisibility(View.VISIBLE);
} else { if (Build.VERSION.SDK_INT
// We need to restart due to bad android linker >= Build.VERSION_CODES.LOLLIPOP_MR1) {
AssistantActivity.instance().restartApplication(); enabledH264(true);
} LinphoneManager.getLc()
} .reloadMsPlugins(
AssistantActivity.instance()
.getApplicationInfo()
.nativeLibraryDir);
AssistantActivity.instance().endDownloadCodec();
} else {
// We need to restart due to bad android linker
AssistantActivity.instance().restartApplication();
}
}
}
});
}
@Override
public void OnError(final String error) {
mHandler.post(
new Runnable() {
@Override
public void run() {
hideAllItems();
downloaded.setText("Sorry an error has occurred.");
downloaded.setVisibility(View.VISIBLE);
ok.setVisibility(View.VISIBLE);
enabledH264(false);
AssistantActivity.instance().endDownloadCodec();
}
});
}
};
codecDownloader.setOpenH264HelperListener(codecListener);
yes.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
hideAllItems();
bar.setVisibility(View.VISIBLE);
codecDownloader.downloadCodec();
} }
}); });
}
@Override no.setOnClickListener(
public void OnError(final String error) { new View.OnClickListener() {
mHandler.post(new Runnable() {
@Override @Override
public void run() { public void onClick(View v) {
hideAllItems();
downloaded.setText("Sorry an error has occurred.");
downloaded.setVisibility(View.VISIBLE);
ok.setVisibility(View.VISIBLE);
enabledH264(false); enabledH264(false);
AssistantActivity.instance().endDownloadCodec(); AssistantActivity.instance().endDownloadCodec();
} }
}); });
}
};
codecDownloader.setOpenH264HelperListener(codecListener);
yes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hideAllItems();
bar.setVisibility(View.VISIBLE);
codecDownloader.downloadCodec();
}
});
no.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
enabledH264(false);
AssistantActivity.instance().endDownloadCodec();
}
});
hideAllItems(); hideAllItems();
if (savedInstanceState != null) { if (savedInstanceState != null) {
if (savedInstanceState.containsKey("question")) if (savedInstanceState.containsKey("question"))
question.setVisibility((Integer) savedInstanceState.getSerializable("question")); question.setVisibility((Integer) savedInstanceState.getSerializable("question"));
else else question.setVisibility(View.VISIBLE);
question.setVisibility(View.VISIBLE);
if (savedInstanceState.containsKey("yes")) if (savedInstanceState.containsKey("yes"))
yes.setVisibility((Integer) savedInstanceState.getSerializable("yes")); yes.setVisibility((Integer) savedInstanceState.getSerializable("yes"));
else else yes.setVisibility(View.VISIBLE);
yes.setVisibility(View.VISIBLE);
if (savedInstanceState.containsKey("no")) if (savedInstanceState.containsKey("no"))
no.setVisibility((Integer) savedInstanceState.getSerializable("no")); no.setVisibility((Integer) savedInstanceState.getSerializable("no"));
else else no.setVisibility(View.VISIBLE);
no.setVisibility(View.VISIBLE);
if (savedInstanceState.containsKey("downloading")) if (savedInstanceState.containsKey("downloading"))
downloading.setVisibility((Integer) savedInstanceState.getSerializable("downloading")); downloading.setVisibility(
(Integer) savedInstanceState.getSerializable("downloading"));
if (savedInstanceState.containsKey("downloaded")) if (savedInstanceState.containsKey("downloaded"))
downloaded.setVisibility((Integer) savedInstanceState.getSerializable("downloaded")); downloaded.setVisibility(
(Integer) savedInstanceState.getSerializable("downloaded"));
if (savedInstanceState.containsKey("context_bar")) if (savedInstanceState.containsKey("context_bar"))
bar.setVisibility((Integer) savedInstanceState.getSerializable("context_bar")); bar.setVisibility((Integer) savedInstanceState.getSerializable("context_bar"));
if (savedInstanceState.containsKey("downloadingInfo")) if (savedInstanceState.containsKey("downloadingInfo"))
downloadingInfo.setVisibility((Integer) savedInstanceState.getSerializable("downloadingInfo")); downloadingInfo.setVisibility(
(Integer) savedInstanceState.getSerializable("downloadingInfo"));
if (savedInstanceState.containsKey("ok")) if (savedInstanceState.containsKey("ok"))
ok.setVisibility((Integer) savedInstanceState.getSerializable("ok")); ok.setVisibility((Integer) savedInstanceState.getSerializable("ok"));

View file

@ -30,19 +30,19 @@ import android.widget.AdapterView;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.DialPlan; import org.linphone.core.DialPlan;
public class CountryListFragment extends Fragment implements AdapterView.OnItemClickListener, View.OnClickListener { public class CountryListFragment extends Fragment
implements AdapterView.OnItemClickListener, View.OnClickListener {
private ListView list; private ListView list;
private EditText search; private EditText search;
private ImageView clearSearchField; private ImageView clearSearchField;
private AssistantActivity.CountryListAdapter adapter; private AssistantActivity.CountryListAdapter adapter;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_country_list, container, false); View view = inflater.inflate(R.layout.assistant_country_list, container, false);
adapter = AssistantActivity.instance().getCountryListAdapter(); adapter = AssistantActivity.instance().getCountryListAdapter();
@ -56,21 +56,20 @@ public class CountryListFragment extends Fragment implements AdapterView.OnItemC
list.setAdapter(adapter); list.setAdapter(adapter);
list.setOnItemClickListener(this); list.setOnItemClickListener(this);
search.addTextChangedListener(new TextWatcher() { search.addTextChangedListener(
@Override new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override
} public void beforeTextChanged(
CharSequence s, int start, int count, int after) {}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s); adapter.getFilter().filter(s);
} }
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
});
}
});
search.setText(""); search.setText("");
return view; return view;

View file

@ -27,25 +27,29 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.AccountCreator; import org.linphone.core.AccountCreator;
import org.linphone.core.AccountCreatorListener; import org.linphone.core.AccountCreatorListener;
import org.linphone.settings.LinphonePreferences;
public class CreateAccountActivationFragment extends Fragment implements OnClickListener, AccountCreatorListener { public class CreateAccountActivationFragment extends Fragment
implements OnClickListener, AccountCreatorListener {
private String username, password; private String username, password;
private Button checkAccount; private Button checkAccount;
private TextView email; private TextView email;
private AccountCreator accountCreator; private AccountCreator accountCreator;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_account_creation_email_activation, container, false); View view =
inflater.inflate(
R.layout.assistant_account_creation_email_activation, container, false);
accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); accountCreator =
LinphoneManager.getLc()
.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
accountCreator.setListener(this); accountCreator.setListener(this);
username = getArguments().getString("Username"); username = getArguments().getString("Username");
@ -72,55 +76,63 @@ public class CreateAccountActivationFragment extends Fragment implements OnClick
} }
@Override @Override
public void onIsAccountExist(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountExist(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onCreateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onCreateAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onActivateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onLinkAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onLinkAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onActivateAlias(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAlias(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onIsAccountActivated(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountActivated(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (AssistantActivity.instance() == null) { if (AssistantActivity.instance() == null) {
return; return;
} }
if (status.equals(AccountCreator.Status.AccountNotActivated)) { if (status.equals(AccountCreator.Status.AccountNotActivated)) {
Toast.makeText(getActivity(), getString(R.string.assistant_account_not_validated), Toast.LENGTH_LONG).show(); Toast.makeText(
getActivity(),
getString(R.string.assistant_account_not_validated),
Toast.LENGTH_LONG)
.show();
} else if (status.equals(AccountCreator.Status.AccountActivated)) { } else if (status.equals(AccountCreator.Status.AccountActivated)) {
AssistantActivity.instance().linphoneLogIn(accountCreator); AssistantActivity.instance().linphoneLogIn(accountCreator);
AssistantActivity.instance().isAccountVerified(username); AssistantActivity.instance().isAccountVerified(username);
} else { } else {
Toast.makeText(getActivity(), getString(R.string.wizard_server_unavailable), Toast.LENGTH_LONG).show(); Toast.makeText(
getActivity(),
getString(R.string.wizard_server_unavailable),
Toast.LENGTH_LONG)
.show();
} }
checkAccount.setEnabled(true); checkAccount.setEnabled(true);
} }
@Override @Override
public void onRecoverAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onRecoverAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onIsAccountLinked(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountLinked(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onIsAliasUsed(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAliasUsed(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onUpdateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onUpdateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
} }

View file

@ -31,14 +31,14 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.AccountCreator; import org.linphone.core.AccountCreator;
import org.linphone.core.AccountCreatorListener; import org.linphone.core.AccountCreatorListener;
import org.linphone.settings.LinphonePreferences;
public class CreateAccountCodeActivationFragment extends Fragment implements AccountCreatorListener { public class CreateAccountCodeActivationFragment extends Fragment
implements AccountCreatorListener {
private String username, phone, dialcode; private String username, phone, dialcode;
private TextView title, phonenumber; private TextView title, phonenumber;
private EditText code; private EditText code;
@ -49,9 +49,11 @@ public class CreateAccountCodeActivationFragment extends Fragment implements Acc
private AccountCreator accountCreator; private AccountCreator accountCreator;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_account_creation_code_activation, container, false); View view =
inflater.inflate(
R.layout.assistant_account_creation_code_activation, container, false);
username = getArguments().getString("Username"); username = getArguments().getString("Username");
phone = getArguments().getString("Phone"); phone = getArguments().getString("Phone");
@ -61,14 +63,15 @@ public class CreateAccountCodeActivationFragment extends Fragment implements Acc
accountNumber = getArguments().getInt("AccountNumber"); accountNumber = getArguments().getInt("AccountNumber");
code_length = LinphonePreferences.instance().getCodeLength(); code_length = LinphonePreferences.instance().getCodeLength();
accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); accountCreator =
LinphoneManager.getLc()
.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
accountCreator.setListener(this); accountCreator.setListener(this);
accountCreator.setUsername(username); accountCreator.setUsername(username);
accountCreator.setPhoneNumber(phone, dialcode); accountCreator.setPhoneNumber(phone, dialcode);
back = view.findViewById(R.id.back); back = view.findViewById(R.id.back);
if (back != null) if (back != null) back.setVisibility(Button.INVISIBLE);
back.setVisibility(Button.INVISIBLE);
title = view.findViewById(R.id.title_account_activation); title = view.findViewById(R.id.title_account_activation);
if (linkAccount) { if (linkAccount) {
@ -81,46 +84,47 @@ public class CreateAccountCodeActivationFragment extends Fragment implements Acc
phonenumber.setText(accountCreator.getPhoneNumber()); phonenumber.setText(accountCreator.getPhoneNumber());
code = view.findViewById(R.id.assistant_code); code = view.findViewById(R.id.assistant_code);
code.addTextChangedListener(new TextWatcher() { code.addTextChangedListener(
@Override new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override
} public void beforeTextChanged(
CharSequence s, int start, int count, int after) {}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {}
}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
if (s.length() == code_length) { if (s.length() == code_length) {
checkAccount.setEnabled(true); checkAccount.setEnabled(true);
} else { } else {
checkAccount.setEnabled(false); checkAccount.setEnabled(false);
} }
} }
}); });
checkAccount = view.findViewById(R.id.assistant_check); checkAccount = view.findViewById(R.id.assistant_check);
checkAccount.setEnabled(false); checkAccount.setEnabled(false);
checkAccount.setOnClickListener(new OnClickListener() { checkAccount.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
checkAccount.setEnabled(false); public void onClick(View v) {
accountCreator.setActivationCode(code.getText().toString()); checkAccount.setEnabled(false);
if (linkAccount) { accountCreator.setActivationCode(code.getText().toString());
linkAccount(); if (linkAccount) {
} else { linkAccount();
activateAccount(); } else {
} activateAccount();
} }
}); }
});
return view; return view;
} }
private void linkAccount() { private void linkAccount() {
accountCreator.setUsername(LinphonePreferences.instance().getAccountUsername(accountNumber)); accountCreator.setUsername(
LinphonePreferences.instance().getAccountUsername(accountNumber));
accountCreator.setHa1(LinphonePreferences.instance().getAccountHa1(accountNumber)); accountCreator.setHa1(LinphonePreferences.instance().getAccountHa1(accountNumber));
accountCreator.activateAlias(); accountCreator.activateAlias();
} }
@ -133,15 +137,16 @@ public class CreateAccountCodeActivationFragment extends Fragment implements Acc
} }
@Override @Override
public void onIsAccountExist(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountExist(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onCreateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onCreateAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onActivateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (AssistantActivity.instance() == null) { if (AssistantActivity.instance() == null) {
return; return;
} }
@ -163,25 +168,37 @@ public class CreateAccountCodeActivationFragment extends Fragment implements Acc
} }
} }
} else if (status.equals(AccountCreator.Status.RequestFailed)) { } else if (status.equals(AccountCreator.Status.RequestFailed)) {
Toast.makeText(getActivity(), getString(R.string.wizard_server_unavailable), Toast.LENGTH_LONG).show(); Toast.makeText(
getActivity(),
getString(R.string.wizard_server_unavailable),
Toast.LENGTH_LONG)
.show();
} else { } else {
Toast.makeText(getActivity(), getString(R.string.assistant_error_confirmation_code), Toast.LENGTH_LONG).show(); Toast.makeText(
getActivity(),
getString(R.string.assistant_error_confirmation_code),
Toast.LENGTH_LONG)
.show();
AssistantActivity.instance().displayAssistantLinphoneLogin(phone, dialcode); AssistantActivity.instance().displayAssistantLinphoneLogin(phone, dialcode);
} }
} }
@Override @Override
public void onLinkAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onLinkAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onActivateAlias(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAlias(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (AssistantActivity.instance() == null) { if (AssistantActivity.instance() == null) {
return; return;
} }
if (status.equals(AccountCreator.Status.AccountActivated)) { if (status.equals(AccountCreator.Status.AccountActivated)) {
LinphonePreferences.instance().setPrefix(accountNumber, org.linphone.core.Utils.getPrefixFromE164(accountCreator.getPhoneNumber())); LinphonePreferences.instance()
.setPrefix(
accountNumber,
org.linphone.core.Utils.getPrefixFromE164(
accountCreator.getPhoneNumber()));
LinphonePreferences.instance().setLinkPopupTime(""); LinphonePreferences.instance().setLinkPopupTime("");
AssistantActivity.instance().hideKeyboard(); AssistantActivity.instance().hideKeyboard();
AssistantActivity.instance().success(); AssistantActivity.instance().success();
@ -189,26 +206,22 @@ public class CreateAccountCodeActivationFragment extends Fragment implements Acc
} }
@Override @Override
public void onIsAccountActivated(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountActivated(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onRecoverAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onRecoverAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onIsAccountLinked(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountLinked(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAliasUsed(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAliasUsed(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onUpdateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onUpdateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
} }

View file

@ -40,25 +40,36 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.AccountCreator; import org.linphone.core.AccountCreator;
import org.linphone.core.AccountCreator.Status; import org.linphone.core.AccountCreator.Status;
import org.linphone.core.AccountCreatorListener; import org.linphone.core.AccountCreatorListener;
import org.linphone.core.DialPlan; import org.linphone.core.DialPlan;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
import java.util.Locale; public class CreateAccountFragment extends Fragment
import java.util.regex.Matcher; implements CompoundButton.OnCheckedChangeListener, OnClickListener, AccountCreatorListener {
import java.util.regex.Pattern; private final Pattern UPPER_CASE_REGEX = Pattern.compile("[A-Z]");
private EditText phoneNumberEdit,
public class CreateAccountFragment extends Fragment implements CompoundButton.OnCheckedChangeListener, OnClickListener, AccountCreatorListener { usernameEdit,
private EditText phoneNumberEdit, usernameEdit, passwordEdit, passwordConfirmEdit, emailEdit, dialCode; passwordEdit,
private TextView phoneNumberError, passwordError, passwordConfirmError, emailError, assisstantTitle, sipUri, skip, instruction; passwordConfirmEdit,
emailEdit,
dialCode;
private TextView phoneNumberError,
passwordError,
passwordConfirmError,
emailError,
assisstantTitle,
sipUri,
skip,
instruction;
private ImageView phoneNumberInfo; private ImageView phoneNumberInfo;
private boolean passwordOk = false; private boolean passwordOk = false;
private boolean emailOk = false; private boolean emailOk = false;
private boolean confirmPasswordOk = false; private boolean confirmPasswordOk = false;
@ -67,16 +78,22 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
private CheckBox useUsername, useEmail; private CheckBox useUsername, useEmail;
private String addressSip = ""; private String addressSip = "";
private int countryCode; private int countryCode;
private LinearLayout phoneNumberLayout, usernameLayout, emailLayout, passwordLayout, passwordConfirmLayout; private LinearLayout phoneNumberLayout,
private final Pattern UPPER_CASE_REGEX = Pattern.compile("[A-Z]"); usernameLayout,
emailLayout,
passwordLayout,
passwordConfirmLayout;
private AccountCreator accountCreator; private AccountCreator accountCreator;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_account_creation, container, false); View view = inflater.inflate(R.layout.assistant_account_creation, container, false);
//Initialize accountCreator // Initialize accountCreator
accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); accountCreator =
LinphoneManager.getLc()
.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
accountCreator.setListener(this); accountCreator.setListener(this);
instruction = view.findViewById(R.id.message_create_account); instruction = view.findViewById(R.id.message_create_account);
@ -115,13 +132,15 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
skip = view.findViewById(R.id.assistant_skip); skip = view.findViewById(R.id.assistant_skip);
//Phone number // Phone number
if (getResources().getBoolean(R.bool.use_phone_number_validation)) { if (getResources().getBoolean(R.bool.use_phone_number_validation)) {
getActivity().getApplicationContext(); getActivity().getApplicationContext();
//Automatically get the country code from the phone // Automatically get the country code from the phone
TelephonyManager tm = TelephonyManager tm =
(TelephonyManager) getActivity().getApplicationContext().getSystemService( (TelephonyManager)
Context.TELEPHONY_SERVICE); getActivity()
.getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String countryIso = tm.getNetworkCountryIso(); String countryIso = tm.getNetworkCountryIso();
countryCode = org.linphone.core.Utils.getCccFromIso(countryIso.toUpperCase()); countryCode = org.linphone.core.Utils.getCccFromIso(countryIso.toUpperCase());
@ -137,19 +156,25 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
DialPlan c = AssistantActivity.instance().country; DialPlan c = AssistantActivity.instance().country;
if (c != null) { if (c != null) {
selectCountry.setText(c.getCountry()); selectCountry.setText(c.getCountry());
dialCode.setText(c.getCountryCallingCode().contains("+") ? dialCode.setText(
c.getCountryCallingCode() : "+" + c.getCountryCallingCode()); c.getCountryCallingCode().contains("+")
? c.getCountryCallingCode()
: "+" + c.getCountryCallingCode());
} else { } else {
c = AssistantActivity.instance().getCountryListAdapter() c =
.getCountryFromCountryCode(String.valueOf(countryCode)); AssistantActivity.instance()
.getCountryListAdapter()
.getCountryFromCountryCode(String.valueOf(countryCode));
if (c != null) { if (c != null) {
selectCountry.setText(c.getCountry()); selectCountry.setText(c.getCountry());
dialCode.setText(c.getCountryCallingCode().contains("+") ? dialCode.setText(
c.getCountryCallingCode() : "+" + c.getCountryCallingCode()); c.getCountryCallingCode().contains("+")
? c.getCountryCallingCode()
: "+" + c.getCountryCallingCode());
} }
} }
//Allow user to enter a username instead use the phone number as username // Allow user to enter a username instead use the phone number as username
if (getResources().getBoolean(R.bool.assistant_allow_username)) { if (getResources().getBoolean(R.bool.assistant_allow_username)) {
useUsername.setVisibility(View.VISIBLE); useUsername.setVisibility(View.VISIBLE);
useUsername.setOnCheckedChangeListener(this); useUsername.setOnCheckedChangeListener(this);
@ -158,14 +183,15 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
addPhoneNumberHandler(dialCode, null); addPhoneNumberHandler(dialCode, null);
} }
//Password & email address // Password & email address
if (getResources().getBoolean(R.bool.isTablet) if (getResources().getBoolean(R.bool.isTablet)
|| !getResources().getBoolean(R.bool.use_phone_number_validation)) { || !getResources().getBoolean(R.bool.use_phone_number_validation)) {
useEmail.setVisibility(View.VISIBLE); useEmail.setVisibility(View.VISIBLE);
useEmail.setOnCheckedChangeListener(this); useEmail.setOnCheckedChangeListener(this);
if (getResources().getBoolean(R.bool.pre_fill_email_in_assistant)) { if (getResources().getBoolean(R.bool.pre_fill_email_in_assistant)) {
Account[] accounts = AccountManager.get(getActivity()).getAccountsByType("com.google"); Account[] accounts =
AccountManager.get(getActivity()).getAccountsByType("com.google");
for (Account account : accounts) { for (Account account : accounts) {
if (isEmailCorrect(account.name)) { if (isEmailCorrect(account.name)) {
@ -183,7 +209,7 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
addEmailHandler(emailEdit, null); addEmailHandler(emailEdit, null);
} }
//Hide phone number and display username/email/password // Hide phone number and display username/email/password
if (!getResources().getBoolean(R.bool.use_phone_number_validation)) { if (!getResources().getBoolean(R.bool.use_phone_number_validation)) {
useEmail.setVisibility(View.GONE); useEmail.setVisibility(View.GONE);
useUsername.setVisibility(View.GONE); useUsername.setVisibility(View.GONE);
@ -194,7 +220,7 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
emailLayout.setVisibility(View.VISIBLE); emailLayout.setVisibility(View.VISIBLE);
} }
//Link account with phone number // Link account with phone number
if (getArguments().getBoolean("LinkPhoneNumber")) { if (getArguments().getBoolean("LinkPhoneNumber")) {
linkAccount = true; linkAccount = true;
useEmail.setVisibility(View.GONE); useEmail.setVisibility(View.GONE);
@ -296,8 +322,12 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
if (linkAccount) { if (linkAccount) {
new AlertDialog.Builder(getActivity()) new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.phone_number_info_title)) .setTitle(getString(R.string.phone_number_info_title))
.setMessage(getString(R.string.phone_number_link_info_content) + "\n" .setMessage(
+ getString(R.string.phone_number_link_info_content_already_account)) getString(R.string.phone_number_link_info_content)
+ "\n"
+ getString(
R.string
.phone_number_link_info_content_already_account))
.show(); .show();
} else { } else {
new AlertDialog.Builder(getActivity()) new AlertDialog.Builder(getActivity())
@ -312,11 +342,15 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
} else { } else {
if (useEmail.isChecked()) accountCreator.setPhoneNumber(null, null); if (useEmail.isChecked()) accountCreator.setPhoneNumber(null, null);
if (!getResources().getBoolean(R.bool.isTablet) || getUsername().length() > 0) { if (!getResources().getBoolean(R.bool.isTablet) || getUsername().length() > 0) {
LinphoneManager.getLc().getConfig().loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile()); LinphoneManager.getLc()
.getConfig()
.loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile());
accountCreator.isAccountExist(); accountCreator.isAccountExist();
} else { } else {
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForUsernameStatus(AccountCreator.UsernameStatus.TooShort) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); LinphoneUtils.errorForUsernameStatus(
AccountCreator.UsernameStatus.TooShort),
AssistantActivity.instance());
createAccount.setEnabled(true); createAccount.setEnabled(true);
} }
} }
@ -333,23 +367,29 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
} }
private void addAlias() { private void addAlias() {
accountCreator.setUsername(LinphonePreferences.instance().getAccountUsername( accountCreator.setUsername(
LinphonePreferences.instance().getDefaultAccountIndex()) LinphonePreferences.instance()
); .getAccountUsername(
int status = accountCreator.setPhoneNumber( LinphonePreferences.instance().getDefaultAccountIndex()));
phoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(dialCode)); int status =
accountCreator.setPhoneNumber(
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode));
boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt(); boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt();
if (isOk) { if (isOk) {
accountCreator.linkAccount(); accountCreator.linkAccount();
} else { } else {
createAccount.setEnabled(true); createAccount.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForPhoneNumberStatus(status), AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.displayError(isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); LinphoneUtils.errorForPhoneNumberStatus(status), AssistantActivity.instance());
LinphoneUtils.displayError(
isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status));
} }
} }
private void createAccount() { private void createAccount() {
if ((getResources().getBoolean(R.bool.isTablet) || !getResources().getBoolean(R.bool.use_phone_number_validation)) if ((getResources().getBoolean(R.bool.isTablet)
|| !getResources().getBoolean(R.bool.use_phone_number_validation))
&& useEmail.isChecked()) { && useEmail.isChecked()) {
AccountCreator.EmailStatus emailStatus; AccountCreator.EmailStatus emailStatus;
AccountCreator.PasswordStatus passwordStatus; AccountCreator.PasswordStatus passwordStatus;
@ -358,16 +398,23 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
emailStatus = accountCreator.setEmail(emailEdit.getText().toString()); emailStatus = accountCreator.setEmail(emailEdit.getText().toString());
if (!emailOk) { if (!emailOk) {
LinphoneUtils.displayError(false, emailError, LinphoneUtils.errorForEmailStatus(emailStatus)); LinphoneUtils.displayError(
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForEmailStatus(emailStatus) false, emailError, LinphoneUtils.errorForEmailStatus(emailStatus));
, AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForEmailStatus(emailStatus),
AssistantActivity.instance());
} else if (!passwordOk) { } else if (!passwordOk) {
LinphoneUtils.displayError(false, passwordError, LinphoneUtils.errorForPasswordStatus(passwordStatus)); LinphoneUtils.displayError(
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForPasswordStatus(passwordStatus) false, passwordError, LinphoneUtils.errorForPasswordStatus(passwordStatus));
, AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForPasswordStatus(passwordStatus),
AssistantActivity.instance());
} else if (!confirmPasswordOk) { } else if (!confirmPasswordOk) {
String msg; String msg;
if (passwordConfirmEdit.getText().toString().equals(passwordEdit.getText().toString())) { if (passwordConfirmEdit
.getText()
.toString()
.equals(passwordEdit.getText().toString())) {
msg = getString(R.string.wizard_password_incorrect); msg = getString(R.string.wizard_password_incorrect);
} else { } else {
msg = getString(R.string.wizard_passwords_unmatched); msg = getString(R.string.wizard_passwords_unmatched);
@ -381,8 +428,10 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
if (phoneNumberEdit.length() > 0 || dialCode.length() > 1) { if (phoneNumberEdit.length() > 0 || dialCode.length() > 1) {
int phoneStatus; int phoneStatus;
boolean isOk; boolean isOk;
phoneStatus = accountCreator.setPhoneNumber( phoneStatus =
phoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(dialCode)); accountCreator.setPhoneNumber(
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode));
isOk = phoneStatus == AccountCreator.PhoneNumberStatus.Ok.toInt(); isOk = phoneStatus == AccountCreator.PhoneNumberStatus.Ok.toInt();
if (!useUsername.isChecked() && accountCreator.getUsername() == null) { if (!useUsername.isChecked() && accountCreator.getUsername() == null) {
accountCreator.setUsername(accountCreator.getPhoneNumber()); accountCreator.setUsername(accountCreator.getPhoneNumber());
@ -394,22 +443,28 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
if (isOk) { if (isOk) {
accountCreator.createAccount(); accountCreator.createAccount();
} else { } else {
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForPhoneNumberStatus(phoneStatus) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); LinphoneUtils.errorForPhoneNumberStatus(phoneStatus),
LinphoneUtils.displayError(isOk, phoneNumberError AssistantActivity.instance());
, LinphoneUtils.errorForPhoneNumberStatus(phoneStatus)); LinphoneUtils.displayError(
isOk,
phoneNumberError,
LinphoneUtils.errorForPhoneNumberStatus(phoneStatus));
} }
} else { } else {
LinphoneUtils.displayErrorAlert(getString(R.string.assistant_create_account_part_1) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); getString(R.string.assistant_create_account_part_1),
AssistantActivity.instance());
} }
} }
createAccount.setEnabled(true); createAccount.setEnabled(true);
} }
private int getPhoneNumberStatus() { private int getPhoneNumberStatus() {
int status = accountCreator.setPhoneNumber( int status =
phoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(dialCode)); accountCreator.setPhoneNumber(
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode));
addressSip = accountCreator.getPhoneNumber(); addressSip = accountCreator.getPhoneNumber();
return status; return status;
} }
@ -418,13 +473,16 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
String msg = ""; String msg = "";
accountCreator.setUsername(getUsername()); accountCreator.setUsername(getUsername());
if (!useEmail.isChecked() && getResources().getBoolean(R.bool.use_phone_number_validation)) { if (!useEmail.isChecked()
&& getResources().getBoolean(R.bool.use_phone_number_validation)) {
int status = getPhoneNumberStatus(); int status = getPhoneNumberStatus();
boolean isOk = (status == AccountCreator.PhoneNumberStatus.Ok.toInt()); boolean isOk = (status == AccountCreator.PhoneNumberStatus.Ok.toInt());
LinphoneUtils.displayError(isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); LinphoneUtils.displayError(
isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status));
// Username or phone number // Username or phone number
if (getResources().getBoolean(R.bool.assistant_allow_username) && useUsername.isChecked()) { if (getResources().getBoolean(R.bool.assistant_allow_username)
&& useUsername.isChecked()) {
addressSip = getUsername(); addressSip = getUsername();
} }
@ -441,133 +499,168 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
dialCode.setBackgroundResource(R.drawable.resizable_textfield); dialCode.setBackgroundResource(R.drawable.resizable_textfield);
phoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); phoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield);
if (!linkAccount && addressSip.length() > 0) { if (!linkAccount && addressSip.length() > 0) {
msg = getResources().getString(R.string.assistant_create_account_phone_number_address) msg =
+ " <" + addressSip + "@" + getResources().getString(R.string.default_domain) + ">"; getResources()
.getString(
R.string
.assistant_create_account_phone_number_address)
+ " <"
+ addressSip
+ "@"
+ getResources().getString(R.string.default_domain)
+ ">";
} }
} }
} else { } else {
addressSip = getUsername(); addressSip = getUsername();
if (addressSip.length() > 0) { if (addressSip.length() > 0) {
msg = getResources().getString(R.string.assistant_create_account_phone_number_address) msg =
+ " <sip:" + addressSip + "@" + getResources().getString(R.string.default_domain) + ">"; getResources()
.getString(
R.string
.assistant_create_account_phone_number_address)
+ " <sip:"
+ addressSip
+ "@"
+ getResources().getString(R.string.default_domain)
+ ">";
} }
} }
sipUri.setText(msg); sipUri.setText(msg);
} }
private void addPhoneNumberHandler(final EditText field, final ImageView icon) { private void addPhoneNumberHandler(final EditText field, final ImageView icon) {
field.addTextChangedListener(new TextWatcher() { field.addTextChangedListener(
public void afterTextChanged(Editable s) { new TextWatcher() {
if (field.equals(dialCode)) { public void afterTextChanged(Editable s) {
DialPlan c = AssistantActivity.instance().getCountryListAdapter() if (field.equals(dialCode)) {
.getCountryFromCountryCode(dialCode.getText().toString()); DialPlan c =
if (c != null) { AssistantActivity.instance()
AssistantActivity.instance().country = c; .getCountryListAdapter()
selectCountry.setText(c.getCountry()); .getCountryFromCountryCode(
} else { dialCode.getText().toString());
selectCountry.setText(R.string.select_your_country); if (c != null) {
AssistantActivity.instance().country = c;
selectCountry.setText(c.getCountry());
} else {
selectCountry.setText(R.string.select_your_country);
}
}
} }
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {
onTextChanged2(); onTextChanged2();
} }
}); });
} }
private void addUsernameHandler(final EditText field, final ImageView icon) { private void addUsernameHandler(final EditText field, final ImageView icon) {
field.addTextChangedListener(new TextWatcher() { field.addTextChangedListener(
public void afterTextChanged(Editable s) { new TextWatcher() {
Matcher matcher = UPPER_CASE_REGEX.matcher(s); public void afterTextChanged(Editable s) {
while (matcher.find()) { Matcher matcher = UPPER_CASE_REGEX.matcher(s);
CharSequence upperCaseRegion = s.subSequence(matcher.start(), matcher.end()); while (matcher.find()) {
s.replace(matcher.start(), matcher.end(), upperCaseRegion.toString().toLowerCase()); CharSequence upperCaseRegion =
} s.subSequence(matcher.start(), matcher.end());
} s.replace(
matcher.start(),
matcher.end(),
upperCaseRegion.toString().toLowerCase());
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {
onTextChanged2(); onTextChanged2();
} }
}); });
} }
private void addEmailHandler(final EditText field, final ImageView icon) { private void addEmailHandler(final EditText field, final ImageView icon) {
field.addTextChangedListener(new TextWatcher() { field.addTextChangedListener(
public void afterTextChanged(Editable s) { new TextWatcher() {
emailOk = false; public void afterTextChanged(Editable s) {
AccountCreator.EmailStatus status = accountCreator.setEmail(field.getText().toString()); emailOk = false;
if (status.equals(AccountCreator.EmailStatus.Ok)) { AccountCreator.EmailStatus status =
emailOk = true; accountCreator.setEmail(field.getText().toString());
LinphoneUtils.displayError(emailOk, emailError, ""); if (status.equals(AccountCreator.EmailStatus.Ok)) {
} else { emailOk = true;
LinphoneUtils.displayError(emailOk LinphoneUtils.displayError(emailOk, emailError, "");
, emailError, LinphoneUtils.errorForEmailStatus(status)); } else {
} LinphoneUtils.displayError(
} emailOk, emailError, LinphoneUtils.errorForEmailStatus(status));
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {}
} });
});
} }
private void addPasswordHandler(final EditText field1, final ImageView icon) { private void addPasswordHandler(final EditText field1, final ImageView icon) {
TextWatcher passwordListener = new TextWatcher() { TextWatcher passwordListener =
public void afterTextChanged(Editable s) { new TextWatcher() {
passwordOk = false; public void afterTextChanged(Editable s) {
AccountCreator.PasswordStatus status = accountCreator.setPassword(field1.getText().toString()); passwordOk = false;
if (isPasswordCorrect(field1.getText().toString())) { AccountCreator.PasswordStatus status =
passwordOk = true; accountCreator.setPassword(field1.getText().toString());
LinphoneUtils.displayError(passwordOk, passwordError, ""); if (isPasswordCorrect(field1.getText().toString())) {
} else { passwordOk = true;
LinphoneUtils.displayError(passwordOk LinphoneUtils.displayError(passwordOk, passwordError, "");
, passwordError, LinphoneUtils.errorForPasswordStatus(status)); } else {
} LinphoneUtils.displayError(
} passwordOk,
passwordError,
LinphoneUtils.errorForPasswordStatus(status));
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {}
} };
};
field1.addTextChangedListener(passwordListener); field1.addTextChangedListener(passwordListener);
} }
private void addConfirmPasswordHandler(final EditText field1, final EditText field2, final ImageView icon) { private void addConfirmPasswordHandler(
TextWatcher passwordListener = new TextWatcher() { final EditText field1, final EditText field2, final ImageView icon) {
public void afterTextChanged(Editable s) { TextWatcher passwordListener =
confirmPasswordOk = false; new TextWatcher() {
if (field1.getText().toString().equals(field2.getText().toString())) { public void afterTextChanged(Editable s) {
confirmPasswordOk = true; confirmPasswordOk = false;
if (!isPasswordCorrect(field1.getText().toString())) { if (field1.getText().toString().equals(field2.getText().toString())) {
LinphoneUtils.displayError(passwordOk confirmPasswordOk = true;
, passwordError, getString(R.string.wizard_password_incorrect)); if (!isPasswordCorrect(field1.getText().toString())) {
} else { LinphoneUtils.displayError(
LinphoneUtils.displayError(confirmPasswordOk, passwordConfirmError, ""); passwordOk,
passwordError,
getString(R.string.wizard_password_incorrect));
} else {
LinphoneUtils.displayError(
confirmPasswordOk, passwordConfirmError, "");
}
} else {
LinphoneUtils.displayError(
confirmPasswordOk,
passwordConfirmError,
getString(R.string.wizard_passwords_unmatched));
}
} }
} else {
LinphoneUtils.displayError(confirmPasswordOk
, passwordConfirmError, getString(R.string.wizard_passwords_unmatched));
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {}
} };
};
field1.addTextChangedListener(passwordListener); field1.addTextChangedListener(passwordListener);
field2.addTextChangedListener(passwordListener); field2.addTextChangedListener(passwordListener);
} }
@ -577,10 +670,12 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
if (status.equals(Status.AccountExist) || status.equals(Status.AccountExistWithAlias)) { if (status.equals(Status.AccountExist) || status.equals(Status.AccountExistWithAlias)) {
if (useEmail.isChecked()) { if (useEmail.isChecked()) {
createAccount.setEnabled(true); createAccount.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); LinphoneUtils.errorForStatus(status), AssistantActivity.instance());
} else { } else {
LinphoneManager.getLc().getConfig().loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile()); LinphoneManager.getLc()
.getConfig()
.loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile());
accountCreator.isAliasUsed(); accountCreator.isAliasUsed();
} }
} else { } else {
@ -591,24 +686,30 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
@Override @Override
public void onCreateAccount(AccountCreator accountCreator, Status status, String resp) { public void onCreateAccount(AccountCreator accountCreator, Status status, String resp) {
if (status.equals(Status.AccountCreated)) { if (status.equals(Status.AccountCreated)) {
if (useEmail.isChecked() || !getResources().getBoolean(R.bool.use_phone_number_validation)) { if (useEmail.isChecked()
AssistantActivity.instance().displayAssistantConfirm(getUsername() || !getResources().getBoolean(R.bool.use_phone_number_validation)) {
, passwordEdit.getText().toString(), emailEdit.getText().toString()); AssistantActivity.instance()
.displayAssistantConfirm(
getUsername(),
passwordEdit.getText().toString(),
emailEdit.getText().toString());
} else { } else {
AssistantActivity.instance().displayAssistantCodeConfirm(getUsername() AssistantActivity.instance()
, phoneNumberEdit.getText().toString() .displayAssistantCodeConfirm(
, LinphoneUtils.getCountryCode(dialCode), false); getUsername(),
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode),
false);
} }
} else { } else {
createAccount.setEnabled(true); createAccount.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); LinphoneUtils.errorForStatus(status), AssistantActivity.instance());
} }
} }
@Override @Override
public void onActivateAccount(AccountCreator accountCreator, Status status, String resp) { public void onActivateAccount(AccountCreator accountCreator, Status status, String resp) {}
}
@Override @Override
public void onLinkAccount(AccountCreator accountCreator, Status status, String resp) { public void onLinkAccount(AccountCreator accountCreator, Status status, String resp) {
@ -616,9 +717,12 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
return; return;
} }
if (status.equals(Status.RequestOk)) { if (status.equals(Status.RequestOk)) {
AssistantActivity.instance().displayAssistantCodeConfirm(getUsername() AssistantActivity.instance()
, phoneNumberEdit.getText().toString() .displayAssistantCodeConfirm(
, LinphoneUtils.getCountryCode(dialCode), false); getUsername(),
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode),
false);
} }
} }
@ -628,9 +732,12 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
return; return;
} }
if (status.equals(Status.RequestOk)) { if (status.equals(Status.RequestOk)) {
AssistantActivity.instance().displayAssistantCodeConfirm(getUsername() AssistantActivity.instance()
, phoneNumberEdit.getText().toString() .displayAssistantCodeConfirm(
, LinphoneUtils.getCountryCode(dialCode), false); getUsername(),
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode),
false);
} }
} }
@ -642,14 +749,14 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
if (status.equals(Status.AccountNotActivated)) { if (status.equals(Status.AccountNotActivated)) {
if (getResources().getBoolean(R.bool.isTablet) if (getResources().getBoolean(R.bool.isTablet)
|| !getResources().getBoolean(R.bool.use_phone_number_validation)) { || !getResources().getBoolean(R.bool.use_phone_number_validation)) {
//accountCreator.activateAccount(); // Resend email TODO // accountCreator.activateAccount(); // Resend email TODO
} else { } else {
accountCreator.recoverAccount(); // Resend SMS accountCreator.recoverAccount(); // Resend SMS
} }
} else { } else {
createAccount.setEnabled(true); createAccount.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); LinphoneUtils.errorForStatus(status), AssistantActivity.instance());
} }
} }
@ -659,19 +766,22 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
return; return;
} }
if (status.equals(Status.RequestOk)) { if (status.equals(Status.RequestOk)) {
AssistantActivity.instance().displayAssistantCodeConfirm(getUsername() AssistantActivity.instance()
, phoneNumberEdit.getText().toString(), dialCode.getText().toString(), false); .displayAssistantCodeConfirm(
getUsername(),
phoneNumberEdit.getText().toString(),
dialCode.getText().toString(),
false);
} else { } else {
createAccount.setEnabled(true); createAccount.setEnabled(true);
//SMS error // SMS error
LinphoneUtils.displayErrorAlert(getString(R.string.request_failed) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); getString(R.string.request_failed), AssistantActivity.instance());
} }
} }
@Override @Override
public void onIsAccountLinked(AccountCreator accountCreator, Status status, String resp) { public void onIsAccountLinked(AccountCreator accountCreator, Status status, String resp) {}
}
@Override @Override
public void onIsAliasUsed(AccountCreator ac, Status status, String resp) { public void onIsAliasUsed(AccountCreator ac, Status status, String resp) {
@ -679,13 +789,15 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
return; return;
} }
if (status.equals(Status.AliasIsAccount) || status.equals(Status.AliasExist)) { if (status.equals(Status.AliasIsAccount) || status.equals(Status.AliasExist)) {
if (accountCreator.getPhoneNumber() != null && accountCreator.getUsername() != null if (accountCreator.getPhoneNumber() != null
&& accountCreator.getPhoneNumber().compareTo(accountCreator.getUsername()) == 0) { && accountCreator.getUsername() != null
&& accountCreator.getPhoneNumber().compareTo(accountCreator.getUsername())
== 0) {
accountCreator.isAccountActivated(); accountCreator.isAccountActivated();
} else { } else {
createAccount.setEnabled(true); createAccount.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status) LinphoneUtils.displayErrorAlert(
, AssistantActivity.instance()); LinphoneUtils.errorForStatus(status), AssistantActivity.instance());
} }
} else { } else {
accountCreator.isAccountActivated(); accountCreator.isAccountActivated();
@ -693,7 +805,5 @@ public class CreateAccountFragment extends Fragment implements CompoundButton.On
} }
@Override @Override
public void onUpdateAccount(AccountCreator accountCreator, Status status, String resp) { public void onUpdateAccount(AccountCreator accountCreator, Status status, String resp) {}
}
} }

View file

@ -26,9 +26,7 @@ import android.os.Handler;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.CoreException; import org.linphone.core.CoreException;
@ -39,6 +37,7 @@ import org.linphone.core.XmlRpcRequest;
import org.linphone.core.XmlRpcRequestListener; import org.linphone.core.XmlRpcRequestListener;
import org.linphone.core.XmlRpcSession; import org.linphone.core.XmlRpcSession;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
public class EchoCancellerCalibrationFragment extends Fragment implements XmlRpcRequestListener { public class EchoCancellerCalibrationFragment extends Fragment implements XmlRpcRequestListener {
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
@ -49,30 +48,36 @@ public class EchoCancellerCalibrationFragment extends Fragment implements XmlRpc
private Runnable runFinished; private Runnable runFinished;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_ec_calibration, container, false); View view = inflater.inflate(R.layout.assistant_ec_calibration, container, false);
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onEcCalibrationResult(Core lc, EcCalibratorStatus status, int delay_ms) { @Override
lc.removeListener(mListener); public void onEcCalibrationResult(
LinphoneManager.getInstance().routeAudioToReceiver(); Core lc, EcCalibratorStatus status, int delay_ms) {
if (mSendEcCalibrationResult) { lc.removeListener(mListener);
sendEcCalibrationResult(status, delay_ms); LinphoneManager.getInstance().routeAudioToReceiver();
} else { if (mSendEcCalibrationResult) {
AssistantActivity.instance().isEchoCalibrationFinished(); sendEcCalibrationResult(status, delay_ms);
} } else {
} AssistantActivity.instance().isEchoCalibrationFinished();
}; }
runFinished = new Runnable() { }
public void run() { };
AssistantActivity.instance().isEchoCalibrationFinished(); runFinished =
} new Runnable() {
}; public void run() {
AssistantActivity.instance().isEchoCalibrationFinished();
}
};
xmlRpcSession = LinphoneManager.getLcIfManagerNotDestroyedOrNull().createXmlRpcSession(LinphonePreferences.instance().getXmlrpcUrl()); xmlRpcSession =
xmlRpcRequest = xmlRpcSession.createRequest(XmlRpcArgType.None, "add_ec_calibration_result"); LinphoneManager.getLcIfManagerNotDestroyedOrNull()
.createXmlRpcSession(LinphonePreferences.instance().getXmlrpcUrl());
xmlRpcRequest =
xmlRpcSession.createRequest(XmlRpcArgType.None, "add_ec_calibration_result");
xmlRpcRequest.setListener(this); xmlRpcRequest.setListener(this);
try { try {
@ -96,7 +101,18 @@ public class EchoCancellerCalibrationFragment extends Fragment implements XmlRpc
private void sendEcCalibrationResult(EcCalibratorStatus status, int delayMs) { private void sendEcCalibrationResult(EcCalibratorStatus status, int delayMs) {
Boolean hasBuiltInEchoCanceler = LinphoneManager.getLc().hasBuiltinEchoCanceller(); Boolean hasBuiltInEchoCanceler = LinphoneManager.getLc().hasBuiltinEchoCanceller();
Log.i("Add echo canceller calibration result: manufacturer=" + Build.MANUFACTURER + " model=" + Build.MODEL + " status=" + status + " delay=" + delayMs + "ms" + " hasBuiltInEchoCanceler " + hasBuiltInEchoCanceler); Log.i(
"Add echo canceller calibration result: manufacturer="
+ Build.MANUFACTURER
+ " model="
+ Build.MODEL
+ " status="
+ status
+ " delay="
+ delayMs
+ "ms"
+ " hasBuiltInEchoCanceler "
+ hasBuiltInEchoCanceler);
xmlRpcRequest.addStringArg(Build.MANUFACTURER); xmlRpcRequest.addStringArg(Build.MANUFACTURER);
xmlRpcRequest.addStringArg(Build.MODEL); xmlRpcRequest.addStringArg(Build.MODEL);
xmlRpcRequest.addStringArg(status.toString()); xmlRpcRequest.addStringArg(status.toString());

View file

@ -39,18 +39,20 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import java.util.Locale;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.AccountCreator; import org.linphone.core.AccountCreator;
import org.linphone.core.AccountCreatorListener; import org.linphone.core.AccountCreatorListener;
import org.linphone.core.DialPlan; import org.linphone.core.DialPlan;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
import java.util.Locale; public class LinphoneLoginFragment extends Fragment
implements CompoundButton.OnCheckedChangeListener,
public class LinphoneLoginFragment extends Fragment implements CompoundButton.OnCheckedChangeListener, OnClickListener, TextWatcher, AccountCreatorListener { OnClickListener,
TextWatcher,
AccountCreatorListener {
private EditText login, password, phoneNumberEdit, dialCode; private EditText login, password, phoneNumberEdit, dialCode;
private Button apply, selectCountry; private Button apply, selectCountry;
private CheckBox useUsername; private CheckBox useUsername;
@ -63,11 +65,13 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
private ImageView phoneNumberInfo; private ImageView phoneNumberInfo;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_linphone_login, container, false); View view = inflater.inflate(R.layout.assistant_linphone_login, container, false);
accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); accountCreator =
LinphoneManager.getLc()
.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
accountCreator.setListener(this); accountCreator.setListener(this);
String url = "http://linphone.org/free-sip-service.html&action=recover"; String url = "http://linphone.org/free-sip-service.html&action=recover";
@ -98,33 +102,40 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
apply.setEnabled(true); apply.setEnabled(true);
apply.setOnClickListener(this); apply.setOnClickListener(this);
//Phone number // Phone number
if (getResources().getBoolean(R.bool.use_phone_number_validation)) { if (getResources().getBoolean(R.bool.use_phone_number_validation)) {
messagePhoneNumber.setText(getString(R.string.assistant_create_account_part_1)); messagePhoneNumber.setText(getString(R.string.assistant_create_account_part_1));
phone = getArguments().getString("Phone"); phone = getArguments().getString("Phone");
dialcode = getArguments().getString("Dialcode"); dialcode = getArguments().getString("Dialcode");
getActivity().getApplicationContext(); getActivity().getApplicationContext();
//Automatically get the country code from the phone // Automatically get the country code from the phone
TelephonyManager tm = TelephonyManager tm =
(TelephonyManager) getActivity().getApplicationContext().getSystemService( (TelephonyManager)
Context.TELEPHONY_SERVICE); getActivity()
.getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String countryIso = tm.getNetworkCountryIso(); String countryIso = tm.getNetworkCountryIso();
countryCode = org.linphone.core.Utils.getCccFromIso(countryIso.toUpperCase()); countryCode = org.linphone.core.Utils.getCccFromIso(countryIso.toUpperCase());
DialPlan c = AssistantActivity.instance().country; DialPlan c = AssistantActivity.instance().country;
if (c != null) { if (c != null) {
selectCountry.setText(c.getCountry()); selectCountry.setText(c.getCountry());
dialCode.setText(c.getCountryCallingCode().contains("+") ? dialCode.setText(
c.getCountryCallingCode() : "+" + c.getCountryCallingCode()); c.getCountryCallingCode().contains("+")
? c.getCountryCallingCode()
: "+" + c.getCountryCallingCode());
} else { } else {
c = AssistantActivity.instance().getCountryListAdapter() c =
.getCountryFromCountryCode(String.valueOf(countryCode)); AssistantActivity.instance()
.getCountryListAdapter()
.getCountryFromCountryCode(String.valueOf(countryCode));
if (c != null) { if (c != null) {
selectCountry.setText(c.getCountry()); selectCountry.setText(c.getCountry());
dialCode.setText(c.getCountryCallingCode().contains("+") ? dialCode.setText(
c.getCountryCallingCode() : "+" + c.getCountryCallingCode()); c.getCountryCallingCode().contains("+")
? c.getCountryCallingCode()
: "+" + c.getCountryCallingCode());
} }
} }
@ -137,27 +148,31 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
phoneNumberEdit.setText(previousPhone); phoneNumberEdit.setText(previousPhone);
} }
//Allow user to enter a username instead use the phone number as username // Allow user to enter a username instead use the phone number as username
if (getResources().getBoolean(R.bool.assistant_allow_username)) { if (getResources().getBoolean(R.bool.assistant_allow_username)) {
useUsername.setVisibility(View.VISIBLE); useUsername.setVisibility(View.VISIBLE);
useUsername.setOnCheckedChangeListener(this); useUsername.setOnCheckedChangeListener(this);
} }
if (phone != null) if (phone != null) phoneNumberEdit.setText(phone);
phoneNumberEdit.setText(phone); if (dialcode != null) dialCode.setText("+" + dialcode);
if (dialcode != null)
dialCode.setText("+" + dialcode);
} }
if (getResources().getBoolean(R.bool.assistant_allow_username)) { if (getResources().getBoolean(R.bool.assistant_allow_username)) {
useUsername.setVisibility(View.VISIBLE); useUsername.setVisibility(View.VISIBLE);
useUsername.setOnCheckedChangeListener(this); useUsername.setOnCheckedChangeListener(this);
password.addTextChangedListener(this); password.addTextChangedListener(this);
forgotPassword.setText(Html.fromHtml("<a href=\"" + url + "\"'>" + getString(R.string.forgot_password) + "</a>")); forgotPassword.setText(
Html.fromHtml(
"<a href=\""
+ url
+ "\"'>"
+ getString(R.string.forgot_password)
+ "</a>"));
forgotPassword.setMovementMethod(LinkMovementMethod.getInstance()); forgotPassword.setMovementMethod(LinkMovementMethod.getInstance());
} }
//Hide phone number and display username/email/password // Hide phone number and display username/email/password
if (!getResources().getBoolean(R.bool.use_phone_number_validation)) { if (!getResources().getBoolean(R.bool.use_phone_number_validation)) {
phoneNumberLayout.setVisibility(View.GONE); phoneNumberLayout.setVisibility(View.GONE);
useUsername.setVisibility(View.GONE); useUsername.setVisibility(View.GONE);
@ -187,8 +202,13 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
} }
public void linphoneLogIn() { public void linphoneLogIn() {
if (login.getText() == null || login.length() == 0 || password.getText() == null || password.length() == 0) { if (login.getText() == null
LinphoneUtils.displayErrorAlert(getString(R.string.first_launch_no_login_password), AssistantActivity.instance()); || login.length() == 0
|| password.getText() == null
|| password.length() == 0) {
LinphoneUtils.displayErrorAlert(
getString(R.string.first_launch_no_login_password),
AssistantActivity.instance());
apply.setEnabled(true); apply.setEnabled(true);
return; return;
} }
@ -198,39 +218,43 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
} }
private int getPhoneNumberStatus() { private int getPhoneNumberStatus() {
return accountCreator.setPhoneNumber(phoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(dialCode)); return accountCreator.setPhoneNumber(
phoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(dialCode));
} }
private void addPhoneNumberHandler(final EditText field, final ImageView icon) { private void addPhoneNumberHandler(final EditText field, final ImageView icon) {
field.addTextChangedListener(new TextWatcher() { field.addTextChangedListener(
public void afterTextChanged(Editable s) { new TextWatcher() {
if (field.equals(dialCode)) { public void afterTextChanged(Editable s) {
DialPlan c = AssistantActivity.instance().getCountryListAdapter().getCountryFromCountryCode(dialCode.getText().toString()); if (field.equals(dialCode)) {
if (c != null) { DialPlan c =
AssistantActivity.instance().country = c; AssistantActivity.instance()
selectCountry.setText(c.getCountry()); .getCountryListAdapter()
} else { .getCountryFromCountryCode(
selectCountry.setText(R.string.select_your_country); dialCode.getText().toString());
if (c != null) {
AssistantActivity.instance().country = c;
selectCountry.setText(c.getCountry());
} else {
selectCountry.setText(R.string.select_your_country);
}
}
} }
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {
onTextChanged2(); onTextChanged2();
} }
}); });
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (useUsername != null && useUsername.isChecked()) if (useUsername != null && useUsername.isChecked()) recoverAccount = false;
recoverAccount = false; else recoverAccount = true;
else
recoverAccount = true;
} }
@Override @Override
@ -251,7 +275,6 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
} else if (id == R.id.select_country) { } else if (id == R.id.select_country) {
AssistantActivity.instance().displayCountryChooser(); AssistantActivity.instance().displayCountryChooser();
} }
} }
private void recoverAccount() { private void recoverAccount() {
@ -259,29 +282,34 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
int status = getPhoneNumberStatus(); int status = getPhoneNumberStatus();
boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt(); boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt();
if (isOk) { if (isOk) {
LinphoneManager.getLc().getConfig().loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile()); LinphoneManager.getLc()
.getConfig()
.loadFromXmlFile(LinphoneManager.getInstance().getmDynamicConfigFile());
accountCreator.isAliasUsed(); accountCreator.isAliasUsed();
} else { } else {
apply.setEnabled(true); apply.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForPhoneNumberStatus(status), LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForPhoneNumberStatus(status),
AssistantActivity.instance()); AssistantActivity.instance());
LinphoneUtils.displayError(isOk, phoneNumberError, LinphoneUtils.displayError(
LinphoneUtils.errorForPhoneNumberStatus(status)); isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status));
} }
} else { } else {
apply.setEnabled(true); apply.setEnabled(true);
LinphoneUtils.displayErrorAlert(getString(R.string.assistant_create_account_part_1), AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
getString(R.string.assistant_create_account_part_1),
AssistantActivity.instance());
} }
} }
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
}
public void onTextChanged2() { public void onTextChanged2() {
int status = getPhoneNumberStatus(); int status = getPhoneNumberStatus();
boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt(); boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt();
LinphoneUtils.displayError(isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); LinphoneUtils.displayError(
isOk, phoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status));
if (!isOk) { if (!isOk) {
if ((1 == (status & AccountCreator.PhoneNumberStatus.InvalidCountryCode.toInt()))) { if ((1 == (status & AccountCreator.PhoneNumberStatus.InvalidCountryCode.toInt()))) {
dialCode.setBackgroundResource(R.drawable.resizable_textfield_error); dialCode.setBackgroundResource(R.drawable.resizable_textfield_error);
@ -291,7 +319,8 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
phoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield_error); phoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield_error);
} }
} else { } else {
accountCreator.setPhoneNumber(phoneNumberEdit.getText().toString(), dialCode.getText().toString()); accountCreator.setPhoneNumber(
phoneNumberEdit.getText().toString(), dialCode.getText().toString());
dialCode.setBackgroundResource(R.drawable.resizable_textfield); dialCode.setBackgroundResource(R.drawable.resizable_textfield);
phoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); phoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield);
} }
@ -303,8 +332,7 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
} }
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
}
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@ -328,73 +356,86 @@ public class LinphoneLoginFragment extends Fragment implements CompoundButton.On
} }
@Override @Override
public void onIsAccountExist(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountExist(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (AssistantActivity.instance() == null) { if (AssistantActivity.instance() == null) {
apply.setEnabled(true); apply.setEnabled(true);
return; return;
} }
if (status.equals(AccountCreator.Status.AccountExist) || status.equals(AccountCreator.Status.AccountExistWithAlias)) { if (status.equals(AccountCreator.Status.AccountExist)
|| status.equals(AccountCreator.Status.AccountExistWithAlias)) {
AssistantActivity.instance().linphoneLogIn(accountCreator); AssistantActivity.instance().linphoneLogIn(accountCreator);
} else { } else {
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForStatus(status), AssistantActivity.instance());
} }
apply.setEnabled(true); apply.setEnabled(true);
} }
@Override @Override
public void onCreateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onCreateAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onActivateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onLinkAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onLinkAccount(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onActivateAlias(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAlias(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onIsAccountActivated(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountActivated(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onRecoverAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onRecoverAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (AssistantActivity.instance() == null) { if (AssistantActivity.instance() == null) {
apply.setEnabled(true); apply.setEnabled(true);
return; return;
} }
if (status.equals(AccountCreator.Status.ServerError)) { if (status.equals(AccountCreator.Status.ServerError)) {
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(AccountCreator.Status.RequestFailed), AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForStatus(AccountCreator.Status.RequestFailed),
AssistantActivity.instance());
apply.setEnabled(true); apply.setEnabled(true);
} else { } else {
AssistantActivity.instance().displayAssistantCodeConfirm(accountCreator.getUsername(), phoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(dialCode), true); AssistantActivity.instance()
.displayAssistantCodeConfirm(
accountCreator.getUsername(),
phoneNumberEdit.getText().toString(),
LinphoneUtils.getCountryCode(dialCode),
true);
} }
} }
@Override @Override
public void onIsAccountLinked(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountLinked(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onIsAliasUsed(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAliasUsed(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (AssistantActivity.instance() == null) { if (AssistantActivity.instance() == null) {
apply.setEnabled(true); apply.setEnabled(true);
return; return;
} }
if (status.equals(AccountCreator.Status.AliasIsAccount) || status.equals(AccountCreator.Status.AliasExist)) { if (status.equals(AccountCreator.Status.AliasIsAccount)
|| status.equals(AccountCreator.Status.AliasExist)) {
accountCreator.recoverAccount(); accountCreator.recoverAccount();
} else { } else {
apply.setEnabled(true); apply.setEnabled(true);
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForStatus(status), AssistantActivity.instance());
} }
} }
@Override @Override
public void onUpdateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onUpdateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
} }

View file

@ -30,7 +30,6 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.Toast; import android.widget.Toast;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.TransportType; import org.linphone.core.TransportType;
@ -40,8 +39,8 @@ public class LoginFragment extends Fragment implements OnClickListener, TextWatc
private Button apply; private Button apply;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_login, container, false); View view = inflater.inflate(R.layout.assistant_login, container, false);
login = view.findViewById(R.id.assistant_username); login = view.findViewById(R.id.assistant_username);
@ -67,8 +66,17 @@ public class LoginFragment extends Fragment implements OnClickListener, TextWatc
int id = v.getId(); int id = v.getId();
if (id == R.id.assistant_apply) { if (id == R.id.assistant_apply) {
if (login.getText() == null || login.length() == 0 || password.getText() == null || password.length() == 0 || domain.getText() == null || domain.length() == 0) { if (login.getText() == null
Toast.makeText(getActivity(), getString(R.string.first_launch_no_login_password), Toast.LENGTH_LONG).show(); || login.length() == 0
|| password.getText() == null
|| password.length() == 0
|| domain.getText() == null
|| domain.length() == 0) {
Toast.makeText(
getActivity(),
getString(R.string.first_launch_no_login_password),
Toast.LENGTH_LONG)
.show();
return; return;
} }
@ -84,24 +92,34 @@ public class LoginFragment extends Fragment implements OnClickListener, TextWatc
} }
if (domain.getText().toString().compareTo(getString(R.string.default_domain)) == 0) { if (domain.getText().toString().compareTo(getString(R.string.default_domain)) == 0) {
AssistantActivity.instance().displayLoginLinphone(login.getText().toString(), password.getText().toString()); AssistantActivity.instance()
.displayLoginLinphone(
login.getText().toString(), password.getText().toString());
} else { } else {
AssistantActivity.instance().genericLogIn(login.getText().toString(), userid.getText().toString(), password.getText().toString(), displayName.getText().toString(), null, domain.getText().toString(), transport); AssistantActivity.instance()
.genericLogIn(
login.getText().toString(),
userid.getText().toString(),
password.getText().toString(),
displayName.getText().toString(),
null,
domain.getText().toString(),
transport);
} }
} }
} }
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
apply.setEnabled(!login.getText().toString().isEmpty() && !password.getText().toString().isEmpty() && !domain.getText().toString().isEmpty()); apply.setEnabled(
!login.getText().toString().isEmpty()
&& !password.getText().toString().isEmpty()
&& !domain.getText().toString().isEmpty());
} }
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
}
} }

View file

@ -28,19 +28,17 @@ import android.os.Handler;
import android.view.View; import android.view.View;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import org.linphone.LinphoneLauncherActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneLauncherActivity;
import org.linphone.core.ConfiguringState; import org.linphone.core.ConfiguringState;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub; import org.linphone.core.CoreListenerStub;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
public class RemoteProvisioningActivity extends Activity { public class RemoteProvisioningActivity extends Activity {
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
@ -54,17 +52,23 @@ public class RemoteProvisioningActivity extends Activity {
setContentView(R.layout.remote_provisioning); setContentView(R.layout.remote_provisioning);
spinner = findViewById(R.id.spinner); spinner = findViewById(R.id.spinner);
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onConfiguringStatus(Core lc, final ConfiguringState state, String message) { @Override
if (spinner != null) spinner.setVisibility(View.GONE); public void onConfiguringStatus(
if (state == ConfiguringState.Successful) { Core lc, final ConfiguringState state, String message) {
goToLinphoneActivity(); if (spinner != null) spinner.setVisibility(View.GONE);
} else if (state == ConfiguringState.Failed) { if (state == ConfiguringState.Successful) {
Toast.makeText(RemoteProvisioningActivity.this, R.string.remote_provisioning_failure, Toast.LENGTH_LONG).show(); goToLinphoneActivity();
} } else if (state == ConfiguringState.Failed) {
} Toast.makeText(
}; RemoteProvisioningActivity.this,
R.string.remote_provisioning_failure,
Toast.LENGTH_LONG)
.show();
}
}
};
} }
@Override @Override
@ -100,75 +104,97 @@ public class RemoteProvisioningActivity extends Activity {
} }
private void checkIntentForConfigUri(final Intent intent) { private void checkIntentForConfigUri(final Intent intent) {
new Thread(new Runnable() { new Thread(
new Runnable() {
@Override @Override
public void run() { public void run() {
Uri openUri = intent.getData(); Uri openUri = intent.getData();
if (openUri != null) { if (openUri != null) {
// We expect something like linphone-config://http://linphone.org/config.xml // We expect something like
configUriParam = openUri.getEncodedSchemeSpecificPart().substring(2); // Removes the linphone-config:// // linphone-config://http://linphone.org/config.xml
try { configUriParam =
configUriParam = URLDecoder.decode(configUriParam, "UTF-8"); openUri.getEncodedSchemeSpecificPart()
} catch (UnsupportedEncodingException e) { .substring(2); // Removes the linphone-config://
Log.e(e); try {
} configUriParam = URLDecoder.decode(configUriParam, "UTF-8");
Log.d("Using config uri: " + configUriParam); } catch (UnsupportedEncodingException e) {
} Log.e(e);
}
Log.d("Using config uri: " + configUriParam);
}
if (configUriParam == null) { if (configUriParam == null) {
if (!LinphonePreferences.instance().isFirstRemoteProvisioning()) { if (!LinphonePreferences.instance()
mHandler.post(new Runnable() { .isFirstRemoteProvisioning()) {
@Override mHandler.post(
public void run() { new Runnable() {
goToLinphoneActivity(); @Override
public void run() {
goToLinphoneActivity();
}
});
} else if (!getResources()
.getBoolean(
R.bool.forbid_app_usage_until_remote_provisioning_completed)) {
// Show this view for a few seconds then go to the dialer
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
goToLinphoneActivity();
}
},
1500);
} // else we do nothing if there is no config uri parameter and
// if user not allowed to leave this screen
} else {
if (getResources()
.getBoolean(
R.bool.display_confirmation_popup_after_first_configuration)
&& !LinphonePreferences.instance()
.isFirstRemoteProvisioning()) {
mHandler.post(
new Runnable() {
@Override
public void run() {
displayDialogConfirmation();
}
});
} else {
mHandler.post(
new Runnable() {
@Override
public void run() {
setRemoteProvisioningAddressAndRestart(
configUriParam);
}
});
}
}
} }
}); })
} else if (!getResources().getBoolean(R.bool.forbid_app_usage_until_remote_provisioning_completed)) { .start();
// Show this view for a few seconds then go to the dialer
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
goToLinphoneActivity();
}
}, 1500);
} // else we do nothing if there is no config uri parameter and if user not allowed to leave this screen
} else {
if (getResources().getBoolean(R.bool.display_confirmation_popup_after_first_configuration)
&& !LinphonePreferences.instance().isFirstRemoteProvisioning()) {
mHandler.post(new Runnable() {
@Override
public void run() {
displayDialogConfirmation();
}
});
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
setRemoteProvisioningAddressAndRestart(configUriParam);
}
});
}
}
}
}).start();
} }
private void displayDialogConfirmation() { private void displayDialogConfirmation() {
new AlertDialog.Builder(RemoteProvisioningActivity.this) new AlertDialog.Builder(RemoteProvisioningActivity.this)
.setTitle(getString(R.string.remote_provisioning_again_title)) .setTitle(getString(R.string.remote_provisioning_again_title))
.setMessage(getString(R.string.remote_provisioning_again_message)) .setMessage(getString(R.string.remote_provisioning_again_message))
.setPositiveButton(R.string.accept, new DialogInterface.OnClickListener() { .setPositiveButton(
public void onClick(DialogInterface dialog, int which) { R.string.accept,
setRemoteProvisioningAddressAndRestart(configUriParam); new DialogInterface.OnClickListener() {
} public void onClick(DialogInterface dialog, int which) {
}) setRemoteProvisioningAddressAndRestart(configUriParam);
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { }
public void onClick(DialogInterface dialog, int which) { })
goToLinphoneActivity(); .setNegativeButton(
} R.string.cancel,
}) new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
goToLinphoneActivity();
}
})
.show(); .show();
} }
@ -178,22 +204,24 @@ public class RemoteProvisioningActivity extends Activity {
LinphonePreferences.instance().setContext(this); // Needed, else the next call will crash LinphonePreferences.instance().setContext(this); // Needed, else the next call will crash
LinphonePreferences.instance().setRemoteProvisioningUrl(configUri); LinphonePreferences.instance().setRemoteProvisioningUrl(configUri);
mHandler.postDelayed(new Runnable() { mHandler.postDelayed(
@Override new Runnable() {
public void run() { @Override
LinphoneManager.getInstance().restartCore(); public void run() {
} LinphoneManager.getInstance().restartCore();
}, 1000); }
},
1000);
} }
private void goToLinphoneActivity() { private void goToLinphoneActivity() {
if (LinphoneService.isReady()) { if (LinphoneService.isReady()) {
LinphoneService.instance().setActivityToLaunchOnIncomingReceived("org.linphone.LinphoneLauncherActivity"); LinphoneService.instance()
//finish(); // To prevent the user to come back to this page using back button .setActivityToLaunchOnIncomingReceived("org.linphone.LinphoneLauncherActivity");
// finish(); // To prevent the user to come back to this page using back button
startActivity(new Intent().setClass(this, LinphoneLauncherActivity.class)); startActivity(new Intent().setClass(this, LinphoneLauncherActivity.class));
} else { } else {
finish(); finish();
} }
} }
} }

View file

@ -28,18 +28,17 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.R; import org.linphone.R;
import org.linphone.settings.LinphonePreferences;
public class RemoteProvisioningFragment extends Fragment implements OnClickListener, TextWatcher { public class RemoteProvisioningFragment extends Fragment implements OnClickListener, TextWatcher {
private EditText remoteProvisioningUrl; private EditText remoteProvisioningUrl;
private Button apply; private Button apply;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_remote_provisioning, container, false); View view = inflater.inflate(R.layout.assistant_remote_provisioning, container, false);
remoteProvisioningUrl = view.findViewById(R.id.assistant_remote_provisioning_url); remoteProvisioningUrl = view.findViewById(R.id.assistant_remote_provisioning_url);
@ -66,9 +65,7 @@ public class RemoteProvisioningFragment extends Fragment implements OnClickListe
} }
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
@ -76,7 +73,5 @@ public class RemoteProvisioningFragment extends Fragment implements OnClickListe
} }
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
}
} }

View file

@ -25,13 +25,12 @@ import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.ConfiguringState; import org.linphone.core.ConfiguringState;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub; import org.linphone.core.CoreListenerStub;
import org.linphone.settings.LinphonePreferences;
import org.linphone.xmlrpc.XmlRpcHelper; import org.linphone.xmlrpc.XmlRpcHelper;
import org.linphone.xmlrpc.XmlRpcListenerBase; import org.linphone.xmlrpc.XmlRpcListenerBase;
@ -58,20 +57,28 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick
domain.setEnabled(false); domain.setEnabled(false);
} }
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onConfiguringStatus(Core lc, final ConfiguringState state, String message) { @Override
if (state == ConfiguringState.Successful) { public void onConfiguringStatus(
//TODO Core lc, final ConfiguringState state, String message) {
} else if (state == ConfiguringState.Failed) { if (state == ConfiguringState.Successful) {
Toast.makeText(RemoteProvisioningLoginActivity.this, R.string.remote_provisioning_failure, Toast.LENGTH_LONG).show(); // TODO
} } else if (state == ConfiguringState.Failed) {
} Toast.makeText(
}; RemoteProvisioningLoginActivity.this,
R.string.remote_provisioning_failure,
Toast.LENGTH_LONG)
.show();
}
}
};
} }
private void cancelWizard(boolean bypassCheck) { private void cancelWizard(boolean bypassCheck) {
if (bypassCheck || getResources().getBoolean(R.bool.allow_cancel_remote_provisioning_login_activity)) { if (bypassCheck
|| getResources()
.getBoolean(R.bool.allow_cancel_remote_provisioning_login_activity)) {
LinphonePreferences.instance().disableProvisioningLoginView(); LinphonePreferences.instance().disableProvisioningLoginView();
setResult(bypassCheck ? Activity.RESULT_OK : Activity.RESULT_CANCELED); setResult(bypassCheck ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
finish(); finish();
@ -80,13 +87,17 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick
private boolean storeAccount(String username, String password, String domain) { private boolean storeAccount(String username, String password, String domain) {
XmlRpcHelper xmlRpcHelper = new XmlRpcHelper(); XmlRpcHelper xmlRpcHelper = new XmlRpcHelper();
xmlRpcHelper.getRemoteProvisioningFilenameAsync(new XmlRpcListenerBase() { xmlRpcHelper.getRemoteProvisioningFilenameAsync(
@Override new XmlRpcListenerBase() {
public void onRemoteProvisioningFilenameSent(String result) { @Override
LinphonePreferences.instance().setRemoteProvisioningUrl(result); public void onRemoteProvisioningFilenameSent(String result) {
LinphoneManager.getInstance().restartCore(); LinphonePreferences.instance().setRemoteProvisioningUrl(result);
} LinphoneManager.getInstance().restartCore();
}, username.toString(), password.toString(), domain.toString()); }
},
username.toString(),
password.toString(),
domain.toString());
LinphonePreferences.instance().firstLaunchSuccessful(); LinphonePreferences.instance().firstLaunchSuccessful();
setResult(Activity.RESULT_OK); setResult(Activity.RESULT_OK);
@ -120,7 +131,10 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick
cancelWizard(false); cancelWizard(false);
} }
if (id == R.id.assistant_connect) { if (id == R.id.assistant_connect) {
storeAccount(login.getText().toString(), password.getText().toString(), domain.getText().toString()); storeAccount(
login.getText().toString(),
password.getText().toString(),
domain.getText().toString());
} }
} }

View file

@ -25,15 +25,14 @@ import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import org.linphone.R; import org.linphone.R;
public class WelcomeFragment extends Fragment implements OnClickListener { public class WelcomeFragment extends Fragment implements OnClickListener {
private Button createAccount, logLinphoneAccount, logGenericAccount, remoteProvisioning; private Button createAccount, logLinphoneAccount, logGenericAccount, remoteProvisioning;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.assistant_welcome, container, false); View view = inflater.inflate(R.layout.assistant_welcome, container, false);
createAccount = view.findViewById(R.id.create_account); createAccount = view.findViewById(R.id.create_account);

View file

@ -32,12 +32,6 @@ public class BandwidthManager {
private int currentProfile = HIGH_RESOLUTION; private int currentProfile = HIGH_RESOLUTION;
public static final synchronized BandwidthManager getInstance() {
if (instance == null) instance = new BandwidthManager();
return instance;
}
private BandwidthManager() { private BandwidthManager() {
// FIXME register a listener on NetworkManager to get notified of network state // FIXME register a listener on NetworkManager to get notified of network state
// FIXME register a listener on Preference to get notified of change in video enable value // FIXME register a listener on Preference to get notified of change in video enable value
@ -45,6 +39,10 @@ public class BandwidthManager {
// FIXME initially get those values // FIXME initially get those values
} }
public static final synchronized BandwidthManager getInstance() {
if (instance == null) instance = new BandwidthManager();
return instance;
}
public void updateWithProfileSettings(Core lc, CallParams callParams) { public void updateWithProfileSettings(Core lc, CallParams callParams) {
if (callParams != null) { // in call if (callParams != null) { // in call

File diff suppressed because it is too large Load diff

View file

@ -24,15 +24,14 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.linphone.R; import org.linphone.R;
public class CallAudioFragment extends Fragment { public class CallAudioFragment extends Fragment {
private CallActivity incallActvityInstance; private CallActivity incallActvityInstance;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.audio, container, false); View view = inflater.inflate(R.layout.audio, container, false);
return view; return view;
} }

View file

@ -26,37 +26,33 @@ import android.content.Intent;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import org.linphone.LinphoneManager; import java.util.ArrayList;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.utils.LinphoneGenericActivity; import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.core.Call.State; import org.linphone.core.Call.State;
import org.linphone.core.CallParams;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub; import org.linphone.core.CoreListenerStub;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneGenericActivity;
import org.linphone.utils.LinphoneUtils;
import org.linphone.views.CallIncomingAnswerButton; import org.linphone.views.CallIncomingAnswerButton;
import org.linphone.views.CallIncomingButtonListener; import org.linphone.views.CallIncomingButtonListener;
import org.linphone.views.CallIncomingDeclineButton; import org.linphone.views.CallIncomingDeclineButton;
import java.util.ArrayList;
public class CallIncomingActivity extends LinphoneGenericActivity { public class CallIncomingActivity extends LinphoneGenericActivity {
private static CallIncomingActivity instance; private static CallIncomingActivity instance;
@ -95,7 +91,10 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
contactPicture = findViewById(R.id.contact_picture); contactPicture = findViewById(R.id.contact_picture);
// set this flag so this activity will stay in front of the keyguard // set this flag so this activity will stay in front of the keyguard
int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; int flags =
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
getWindow().addFlags(flags); getWindow().addFlags(flags);
acceptUnlock = findViewById(R.id.acceptUnlock); acceptUnlock = findViewById(R.id.acceptUnlock);
@ -106,14 +105,19 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
acceptIcon = findViewById(R.id.acceptIcon); acceptIcon = findViewById(R.id.acceptIcon);
lookupCurrentCall(); lookupCurrentCall();
if (LinphonePreferences.instance() != null && mCall != null && mCall.getRemoteParams() != null && if (LinphonePreferences.instance() != null
LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests() && && mCall != null
mCall.getRemoteParams().videoEnabled()) { && mCall.getRemoteParams() != null
&& LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()
&& mCall.getRemoteParams().videoEnabled()) {
acceptIcon.setImageResource(R.drawable.call_video_start); acceptIcon.setImageResource(R.drawable.call_video_start);
} }
mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean doNotUseSliders = getResources().getBoolean(R.bool.do_not_use_sliders_to_answer_hangup_call_if_phone_unlocked); boolean doNotUseSliders =
getResources()
.getBoolean(
R.bool.do_not_use_sliders_to_answer_hangup_call_if_phone_unlocked);
if (doNotUseSliders && !mKeyguardManager.inKeyguardRestrictedInputMode()) { if (doNotUseSliders && !mKeyguardManager.inKeyguardRestrictedInputMode()) {
accept.setSliderMode(false); accept.setSliderMode(false);
decline.setSliderMode(false); decline.setSliderMode(false);
@ -123,33 +127,43 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
accept.setDeclineButton(decline); accept.setDeclineButton(decline);
decline.setAnswerButton(accept); decline.setAnswerButton(accept);
} }
accept.setListener(new CallIncomingButtonListener() { accept.setListener(
@Override new CallIncomingButtonListener() {
public void onAction() { @Override
answer(); public void onAction() {
} answer();
}); }
decline.setListener(new CallIncomingButtonListener() { });
@Override decline.setListener(
public void onAction() { new CallIncomingButtonListener() {
decline(); @Override
} public void onAction() {
}); decline();
}
});
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onCallStateChanged(Core lc, Call call, State state, String message) { @Override
if (call == mCall && State.End == state) { public void onCallStateChanged(
finish(); Core lc, Call call, State state, String message) {
} else if (state == State.Connected) { if (call == mCall && State.End == state) {
startActivity(new Intent(CallIncomingActivity.this, CallActivity.class)); finish();
} else if (state == State.StreamsRunning) { } else if (state == State.Connected) {
Log.e("CallIncommingActivity - onCreate - State.StreamsRunning - speaker = " + LinphoneManager.getInstance().isSpeakerEnabled()); startActivity(
// The following should not be needed except some devices need it (e.g. Galaxy S). new Intent(CallIncomingActivity.this, CallActivity.class));
LinphoneManager.getInstance().enableSpeaker(LinphoneManager.getInstance().isSpeakerEnabled()); } else if (state == State.StreamsRunning) {
} Log.e(
} "CallIncommingActivity - onCreate - State.StreamsRunning - speaker = "
}; + LinphoneManager.getInstance().isSpeakerEnabled());
// The following should not be needed except some devices need it (e.g.
// Galaxy S).
LinphoneManager.getInstance()
.enableSpeaker(
LinphoneManager.getInstance().isSpeakerEnabled());
}
}
};
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
instance = this; instance = this;
@ -170,17 +184,17 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
// Only one call ringing at a time is allowed // Only one call ringing at a time is allowed
lookupCurrentCall(); lookupCurrentCall();
if (mCall == null) { if (mCall == null) {
//The incoming call no longer exists. // The incoming call no longer exists.
Log.d("Couldn't find incoming call"); Log.d("Couldn't find incoming call");
finish(); finish();
return; return;
} }
Address address = mCall.getRemoteAddress(); Address address = mCall.getRemoteAddress();
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address);
if (contact != null) { if (contact != null) {
ImageUtils.setImagePictureFromUri(this, contactPicture, contact.getPhotoUri(), contact.getThumbnailUri()); ImageUtils.setImagePictureFromUri(
this, contactPicture, contact.getPhotoUri(), contact.getThumbnailUri());
name.setText(contact.getFullName()); name.setText(contact.getFullName());
} else { } else {
name.setText(LinphoneUtils.getAddressDisplayName(address)); name.setText(LinphoneUtils.getAddressDisplayName(address));
@ -211,7 +225,8 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
if (LinphoneManager.isInstanciated() && (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) { if (LinphoneManager.isInstanciated()
&& (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) {
LinphoneManager.getLc().terminateCall(mCall); LinphoneManager.getLc().terminateCall(mCall);
finish(); finish();
} }
@ -260,20 +275,36 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
private void checkAndRequestCallPermissions() { private void checkAndRequestCallPermissions() {
ArrayList<String> permissionsList = new ArrayList<String>(); ArrayList<String> permissionsList = new ArrayList<String>();
int recordAudio = getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()); int recordAudio =
Log.i("[Permission] Record audio permission is " + (recordAudio == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); getPackageManager()
int camera = getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()); .checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName());
Log.i("[Permission] Camera permission is " + (camera == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); 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"));
if (recordAudio != PackageManager.PERMISSION_GRANTED) { if (recordAudio != PackageManager.PERMISSION_GRANTED) {
if (LinphonePreferences.instance().firstTimeAskingForPermission(Manifest.permission.RECORD_AUDIO) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { if (LinphonePreferences.instance()
.firstTimeAskingForPermission(Manifest.permission.RECORD_AUDIO)
|| ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.RECORD_AUDIO)) {
Log.i("[Permission] Asking for record audio"); Log.i("[Permission] Asking for record audio");
permissionsList.add(Manifest.permission.RECORD_AUDIO); permissionsList.add(Manifest.permission.RECORD_AUDIO);
} }
} }
if (LinphonePreferences.instance().shouldInitiateVideoCall() || LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) { if (LinphonePreferences.instance().shouldInitiateVideoCall()
|| LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
if (camera != PackageManager.PERMISSION_GRANTED) { if (camera != PackageManager.PERMISSION_GRANTED) {
if (LinphonePreferences.instance().firstTimeAskingForPermission(Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { if (LinphonePreferences.instance()
.firstTimeAskingForPermission(Manifest.permission.CAMERA)
|| ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.CAMERA)) {
Log.i("[Permission] Asking for camera"); Log.i("[Permission] Asking for camera");
permissionsList.add(Manifest.permission.CAMERA); permissionsList.add(Manifest.permission.CAMERA);
} }
@ -288,9 +319,16 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
for (int i = 0; i < permissions.length; i++) { for (int i = 0; i < permissions.length; i++) {
Log.i("[Permission] " + permissions[i] + " is " + (grantResults[i] == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); Log.i(
"[Permission] "
+ permissions[i]
+ " is "
+ (grantResults[i] == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
} }
} }
} }

View file

@ -20,23 +20,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.utils.FileUtils;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.core.CallParams; import org.linphone.core.CallParams;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.CoreException; import org.linphone.core.CoreException;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.utils.FileUtils;
/** /** Handle call updating, reinvites. */
* Handle call updating, reinvites.
*/
public class CallManager { public class CallManager {
private static CallManager instance; private static CallManager instance;
private CallManager() { private CallManager() {}
}
public static final synchronized CallManager getInstance() { public static final synchronized CallManager getInstance() {
if (instance == null) instance = new CallManager(); if (instance == null) instance = new CallManager();
@ -47,7 +44,8 @@ public class CallManager {
return BandwidthManager.getInstance(); return BandwidthManager.getInstance();
} }
public void inviteAddress(Address lAddress, boolean videoEnabled, boolean lowBandwidth) throws CoreException { public void inviteAddress(Address lAddress, boolean videoEnabled, boolean lowBandwidth)
throws CoreException {
Core lc = LinphoneManager.getLc(); Core lc = LinphoneManager.getLc();
CallParams params = lc.createCallParams(null); CallParams params = lc.createCallParams(null);
@ -64,16 +62,17 @@ public class CallManager {
Log.d("Low bandwidth enabled in call params"); Log.d("Low bandwidth enabled in call params");
} }
String recordFile = FileUtils.getCallRecordingFilename(LinphoneManager.getInstance().getContext(), lAddress); String recordFile =
FileUtils.getCallRecordingFilename(
LinphoneManager.getInstance().getContext(), lAddress);
params.setRecordFile(recordFile); params.setRecordFile(recordFile);
lc.inviteAddressWithParams(lAddress, params); lc.inviteAddressWithParams(lAddress, params);
} }
/** /**
* Add video to a currently running voice only call. * Add video to a currently running voice only call. No re-invite is sent if the current call is
* No re-invite is sent if the current call is already video * already video or if the bandwidth settings are too low.
* or if the bandwidth settings are too low.
* *
* @return if updateCall called * @return if updateCall called
*/ */
@ -88,7 +87,6 @@ public class CallManager {
if (params.videoEnabled()) return false; if (params.videoEnabled()) return false;
// Check if video possible regarding bandwidth limitations // Check if video possible regarding bandwidth limitations
bm().updateWithProfileSettings(lc, params); bm().updateWithProfileSettings(lc, params);
@ -104,8 +102,8 @@ public class CallManager {
/** /**
* Change the preferred video size used by linphone core. (impact landscape/portrait buffer). * Change the preferred video size used by linphone core. (impact landscape/portrait buffer).
* Update current call, without reinvite. * Update current call, without reinvite. The camera will be restarted when mediastreamer chain
* The camera will be restarted when mediastreamer chain is recreated and setParameters is called. * is recreated and setParameters is called.
*/ */
public void updateCall() { public void updateCall() {
Core lc = LinphoneManager.getLc(); Core lc = LinphoneManager.getLc();
@ -118,5 +116,4 @@ public class CallManager {
bm().updateWithProfileSettings(lc, params); bm().updateWithProfileSettings(lc, params);
lc.updateCall(lCall, null); lc.updateCall(lCall, null);
} }
} }

View file

@ -23,7 +23,6 @@ import android.Manifest;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import android.view.Gravity; import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -34,14 +33,11 @@ import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import org.linphone.LinphoneManager; import java.util.ArrayList;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.utils.LinphoneGenericActivity; import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
@ -51,8 +47,10 @@ import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub; import org.linphone.core.CoreListenerStub;
import org.linphone.core.Reason; import org.linphone.core.Reason;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import java.util.ArrayList; import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneGenericActivity;
import org.linphone.utils.LinphoneUtils;
public class CallOutgoingActivity extends LinphoneGenericActivity implements OnClickListener { public class CallOutgoingActivity extends LinphoneGenericActivity implements OnClickListener {
private static CallOutgoingActivity instance; private static CallOutgoingActivity instance;
@ -95,53 +93,69 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
speaker.setOnClickListener(this); speaker.setOnClickListener(this);
// set this flag so this activity will stay in front of the keyguard // set this flag so this activity will stay in front of the keyguard
int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; int flags =
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
getWindow().addFlags(flags); getWindow().addFlags(flags);
hangUp = findViewById(R.id.outgoing_hang_up); hangUp = findViewById(R.id.outgoing_hang_up);
hangUp.setOnClickListener(this); hangUp.setOnClickListener(this);
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onCallStateChanged(Core lc, Call call, Call.State state, String message) { @Override
if (call == mCall && State.Connected == state) { public void onCallStateChanged(
if (!LinphoneActivity.isInstanciated()) { Core lc, Call call, Call.State state, String message) {
return; if (call == mCall && State.Connected == state) {
} if (!LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().startIncallActivity(); return;
return; }
} else if (state == State.Error) { LinphoneActivity.instance().startIncallActivity();
// Convert Core message for internalization return;
if (call.getErrorInfo().getReason() == Reason.Declined) { } else if (state == State.Error) {
displayCustomToast(getString(R.string.error_call_declined), Toast.LENGTH_SHORT); // Convert Core message for internalization
decline(); if (call.getErrorInfo().getReason() == Reason.Declined) {
} else if (call.getErrorInfo().getReason() == Reason.NotFound) { displayCustomToast(
displayCustomToast(getString(R.string.error_user_not_found), Toast.LENGTH_SHORT); getString(R.string.error_call_declined),
decline(); Toast.LENGTH_SHORT);
} else if (call.getErrorInfo().getReason() == Reason.NotAcceptable) { decline();
displayCustomToast(getString(R.string.error_incompatible_media), Toast.LENGTH_SHORT); } else if (call.getErrorInfo().getReason() == Reason.NotFound) {
decline(); displayCustomToast(
} else if (call.getErrorInfo().getReason() == Reason.Busy) { getString(R.string.error_user_not_found),
displayCustomToast(getString(R.string.error_user_busy), Toast.LENGTH_SHORT); Toast.LENGTH_SHORT);
decline(); decline();
} else if (message != null) { } else if (call.getErrorInfo().getReason() == Reason.NotAcceptable) {
displayCustomToast(getString(R.string.error_unknown) + " - " + message, Toast.LENGTH_SHORT); displayCustomToast(
decline(); getString(R.string.error_incompatible_media),
} Toast.LENGTH_SHORT);
} else if (state == State.End) { decline();
// Convert Core message for internalization } else if (call.getErrorInfo().getReason() == Reason.Busy) {
if (call.getErrorInfo().getReason() == Reason.Declined) { displayCustomToast(
displayCustomToast(getString(R.string.error_call_declined), Toast.LENGTH_SHORT); getString(R.string.error_user_busy), Toast.LENGTH_SHORT);
decline(); decline();
} } else if (message != null) {
} displayCustomToast(
getString(R.string.error_unknown) + " - " + message,
Toast.LENGTH_SHORT);
decline();
}
} else if (state == State.End) {
// Convert Core message for internalization
if (call.getErrorInfo().getReason() == Reason.Declined) {
displayCustomToast(
getString(R.string.error_call_declined),
Toast.LENGTH_SHORT);
decline();
}
}
if (LinphoneManager.getLc().getCallsNb() == 0) { if (LinphoneManager.getLc().getCallsNb() == 0) {
finish(); finish();
return; return;
} }
} }
}; };
instance = this; instance = this;
} }
@ -160,8 +174,10 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) { if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
for (Call call : LinphoneManager.getLc().getCalls()) { for (Call call : LinphoneManager.getLc().getCalls()) {
State cstate = call.getState(); State cstate = call.getState();
if (State.OutgoingInit == cstate || State.OutgoingProgress == cstate if (State.OutgoingInit == cstate
|| State.OutgoingRinging == cstate || State.OutgoingEarlyMedia == cstate) { || State.OutgoingProgress == cstate
|| State.OutgoingRinging == cstate
|| State.OutgoingEarlyMedia == cstate) {
mCall = call; mCall = call;
break; break;
} }
@ -183,7 +199,8 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
Address address = mCall.getRemoteAddress(); Address address = mCall.getRemoteAddress();
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address);
if (contact != null) { if (contact != null) {
ImageUtils.setImagePictureFromUri(this, contactPicture, contact.getPhotoUri(), contact.getThumbnailUri()); ImageUtils.setImagePictureFromUri(
this, contactPicture, contact.getPhotoUri(), contact.getThumbnailUri());
name.setText(contact.getFullName()); name.setText(contact.getFullName());
} else { } else {
name.setText(LinphoneUtils.getAddressDisplayName(address)); name.setText(LinphoneUtils.getAddressDisplayName(address));
@ -241,7 +258,8 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
if (LinphoneManager.isInstanciated() && (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) { if (LinphoneManager.isInstanciated()
&& (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) {
LinphoneManager.getLc().terminateCall(mCall); LinphoneManager.getLc().terminateCall(mCall);
finish(); finish();
} }
@ -270,20 +288,36 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
private void checkAndRequestCallPermissions() { private void checkAndRequestCallPermissions() {
ArrayList<String> permissionsList = new ArrayList<String>(); ArrayList<String> permissionsList = new ArrayList<String>();
int recordAudio = getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()); int recordAudio =
Log.i("[Permission] Record audio permission is " + (recordAudio == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); getPackageManager()
int camera = getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()); .checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName());
Log.i("[Permission] Camera permission is " + (camera == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); 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"));
if (recordAudio != PackageManager.PERMISSION_GRANTED) { if (recordAudio != PackageManager.PERMISSION_GRANTED) {
if (LinphonePreferences.instance().firstTimeAskingForPermission(Manifest.permission.RECORD_AUDIO) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { if (LinphonePreferences.instance()
.firstTimeAskingForPermission(Manifest.permission.RECORD_AUDIO)
|| ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.RECORD_AUDIO)) {
Log.i("[Permission] Asking for record audio"); Log.i("[Permission] Asking for record audio");
permissionsList.add(Manifest.permission.RECORD_AUDIO); permissionsList.add(Manifest.permission.RECORD_AUDIO);
} }
} }
if (LinphonePreferences.instance().shouldInitiateVideoCall() || LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) { if (LinphonePreferences.instance().shouldInitiateVideoCall()
|| LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
if (camera != PackageManager.PERMISSION_GRANTED) { if (camera != PackageManager.PERMISSION_GRANTED) {
if (LinphonePreferences.instance().firstTimeAskingForPermission(Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { if (LinphonePreferences.instance()
.firstTimeAskingForPermission(Manifest.permission.CAMERA)
|| ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.CAMERA)) {
Log.i("[Permission] Asking for camera"); Log.i("[Permission] Asking for camera");
permissionsList.add(Manifest.permission.CAMERA); permissionsList.add(Manifest.permission.CAMERA);
} }
@ -298,9 +332,16 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
for (int i = 0; i < permissions.length; i++) { for (int i = 0; i < permissions.length; i++) {
Log.i("[Permission] " + permissions[i] + " is " + (grantResults[i] == PackageManager.PERMISSION_GRANTED ? "granted" : "denied")); Log.i(
"[Permission] "
+ permissions[i]
+ " is "
+ (grantResults[i] == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
} }
} }
} }

View file

@ -32,11 +32,8 @@ import android.view.View;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.compatibility.CompatibilityScaleGestureDetector; import org.linphone.compatibility.CompatibilityScaleGestureDetector;
import org.linphone.compatibility.CompatibilityScaleGestureListener; import org.linphone.compatibility.CompatibilityScaleGestureListener;
@ -44,8 +41,11 @@ import org.linphone.core.Call;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.VideoDefinition; import org.linphone.core.VideoDefinition;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
public class CallVideoFragment extends Fragment implements OnGestureListener, OnDoubleTapListener, CompatibilityScaleGestureListener { public class CallVideoFragment extends Fragment
implements OnGestureListener, OnDoubleTapListener, CompatibilityScaleGestureListener {
private TextureView mVideoView; private TextureView mVideoView;
private TextureView mCaptureView; private TextureView mCaptureView;
private GestureDetector mGestureDetector; private GestureDetector mGestureDetector;
@ -58,8 +58,8 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
// Warning useless because value is ignored and automatically set by new APIs. // Warning useless because value is ignored and automatically set by new APIs.
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view; View view;
if (LinphoneManager.getLc().hasCrappyOpengl()) { if (LinphoneManager.getLc().hasCrappyOpengl()) {
view = inflater.inflate(R.layout.video_no_opengl, container, false); view = inflater.inflate(R.layout.video_no_opengl, container, false);
@ -69,48 +69,55 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
mVideoView = view.findViewById(R.id.videoSurface); mVideoView = view.findViewById(R.id.videoSurface);
mCaptureView = view.findViewById(R.id.videoCaptureSurface); mCaptureView = view.findViewById(R.id.videoCaptureSurface);
LinphoneManager.getLc().setNativeVideoWindowId(mVideoView); LinphoneManager.getLc().setNativeVideoWindowId(mVideoView);
LinphoneManager.getLc().setNativePreviewWindowId(mCaptureView); LinphoneManager.getLc().setNativePreviewWindowId(mCaptureView);
mVideoView.setOnTouchListener(new OnTouchListener() { mVideoView.setOnTouchListener(
public boolean onTouch(View v, MotionEvent event) { new OnTouchListener() {
if (mScaleDetector != null) { public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event); if (mScaleDetector != null) {
} mScaleDetector.onTouchEvent(event);
}
mGestureDetector.onTouchEvent(event); mGestureDetector.onTouchEvent(event);
if (inCallActivity != null) { if (inCallActivity != null) {
inCallActivity.displayVideoCallControlsIfHidden(); inCallActivity.displayVideoCallControlsIfHidden();
} }
return true; return true;
} }
}); });
mCaptureView.setOnTouchListener(new OnTouchListener() { mCaptureView.setOnTouchListener(
@Override new OnTouchListener() {
public boolean onTouch(View view, MotionEvent motionEvent) { @Override
switch (motionEvent.getAction()) { public boolean onTouch(View view, MotionEvent motionEvent) {
case MotionEvent.ACTION_DOWN: switch (motionEvent.getAction()) {
previewX = (int) motionEvent.getX(); case MotionEvent.ACTION_DOWN:
previewY = (int) motionEvent.getY(); previewX = (int) motionEvent.getX();
break; previewY = (int) motionEvent.getY();
case MotionEvent.ACTION_MOVE: break;
int x = (int) motionEvent.getX(); case MotionEvent.ACTION_MOVE:
int y = (int) motionEvent.getY(); int x = (int) motionEvent.getX();
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mCaptureView.getLayoutParams(); int y = (int) motionEvent.getY();
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0); // Clears the rule, as there is no removeRule until API 17. RelativeLayout.LayoutParams lp =
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0); (RelativeLayout.LayoutParams)
int left = lp.leftMargin + (x - previewX); mCaptureView.getLayoutParams();
int top = lp.topMargin + (y - previewY); lp.addRule(
lp.leftMargin = left; RelativeLayout.ALIGN_PARENT_BOTTOM,
lp.topMargin = top; 0); // Clears the rule, as there is no removeRule until API
view.setLayoutParams(lp); // 17.
break; lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
} int left = lp.leftMargin + (x - previewX);
return true; int top = lp.topMargin + (y - previewY);
} lp.leftMargin = left;
}); lp.topMargin = top;
view.setLayoutParams(lp);
break;
}
return true;
}
});
return view; return view;
} }
@ -135,9 +142,12 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
DisplayMetrics metrics = new DisplayMetrics(); DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenHeight = metrics.heightPixels; int screenHeight = metrics.heightPixels;
int maxHeight = screenHeight / 4; // Let's take at most 1/4 of the screen for the camera preview int maxHeight =
screenHeight / 4; // Let's take at most 1/4 of the screen for the camera preview
VideoDefinition videoSize = call.getCurrentParams().getSentVideoDefinition(); // It already takes care of rotation VideoDefinition videoSize =
call.getCurrentParams()
.getSentVideoDefinition(); // It already takes care of rotation
if (videoSize.getWidth() == 0 || videoSize.getHeight() == 0) { if (videoSize.getWidth() == 0 || videoSize.getHeight() == 0) {
Log.w("Couldn't get sent video definition, using default video definition"); Log.w("Couldn't get sent video definition, using default video definition");
videoSize = lc.getPreferredVideoDefinition(); videoSize = lc.getPreferredVideoDefinition();
@ -155,7 +165,9 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
} }
RelativeLayout.LayoutParams newLp = new RelativeLayout.LayoutParams(width, height); RelativeLayout.LayoutParams newLp = new RelativeLayout.LayoutParams(width, height);
newLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 1); // Clears the rule, as there is no removeRule until API 17. newLp.addRule(
RelativeLayout.ALIGN_PARENT_BOTTOM,
1); // Clears the rule, as there is no removeRule until API 17.
newLp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 1); newLp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 1);
mCaptureView.setLayoutParams(newLp); mCaptureView.setLayoutParams(newLp);
Log.d("Video preview size set to " + width + "x" + height); Log.d("Video preview size set to " + width + "x" + height);
@ -175,12 +187,9 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
} }
String newDevice; String newDevice;
if (index == 1) if (index == 1) newDevice = devices[0];
newDevice = devices[0]; else if (devices.length > 1) newDevice = devices[1];
else if (devices.length > 1) else newDevice = devices[index];
newDevice = devices[1];
else
newDevice = devices[index];
LinphoneManager.getLc().setVideoDevice(newDevice); LinphoneManager.getLc().setVideoDevice(newDevice);
CallManager.getInstance().updateCall(); CallManager.getInstance().updateCall();
@ -217,10 +226,15 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
mZoomFactor *= detector.getScaleFactor(); mZoomFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large. // Don't let the object get too small or too large.
// Zoom to make the video fill the screen vertically // Zoom to make the video fill the screen vertically
float portraitZoomFactor = ((float) mVideoView.getHeight()) / (float) ((3 * mVideoView.getWidth()) / 4); float portraitZoomFactor =
((float) mVideoView.getHeight()) / (float) ((3 * mVideoView.getWidth()) / 4);
// Zoom to make the video fill the screen horizontally // Zoom to make the video fill the screen horizontally
float landscapeZoomFactor = ((float) mVideoView.getWidth()) / (float) ((3 * mVideoView.getHeight()) / 4); float landscapeZoomFactor =
mZoomFactor = Math.max(0.1f, Math.min(mZoomFactor, Math.max(portraitZoomFactor, landscapeZoomFactor))); ((float) mVideoView.getWidth()) / (float) ((3 * mVideoView.getHeight()) / 4);
mZoomFactor =
Math.max(
0.1f,
Math.min(mZoomFactor, Math.max(portraitZoomFactor, landscapeZoomFactor)));
Call currentCall = LinphoneManager.getLc().getCurrentCall(); Call currentCall = LinphoneManager.getLc().getCurrentCall();
if (currentCall != null) { if (currentCall != null) {
@ -246,16 +260,14 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
mZoomCenterY -= 0.01; mZoomCenterY -= 0.01;
} }
if (mZoomCenterX > 1) if (mZoomCenterX > 1) mZoomCenterX = 1;
mZoomCenterX = 1; if (mZoomCenterX < 0) mZoomCenterX = 0;
if (mZoomCenterX < 0) if (mZoomCenterY > 1) mZoomCenterY = 1;
mZoomCenterX = 0; if (mZoomCenterY < 0) mZoomCenterY = 0;
if (mZoomCenterY > 1)
mZoomCenterY = 1;
if (mZoomCenterY < 0)
mZoomCenterY = 0;
LinphoneManager.getLc().getCurrentCall().zoom(mZoomFactor, mZoomCenterX, mZoomCenterY); LinphoneManager.getLc()
.getCurrentCall()
.zoom(mZoomFactor, mZoomCenterX, mZoomCenterY);
return true; return true;
} }
} }
@ -268,9 +280,13 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
if (LinphoneUtils.isCallEstablished(LinphoneManager.getLc().getCurrentCall())) { if (LinphoneUtils.isCallEstablished(LinphoneManager.getLc().getCurrentCall())) {
if (mZoomFactor == 1.f) { if (mZoomFactor == 1.f) {
// Zoom to make the video fill the screen vertically // Zoom to make the video fill the screen vertically
float portraitZoomFactor = ((float) mVideoView.getHeight()) / (float) ((3 * mVideoView.getWidth()) / 4); float portraitZoomFactor =
((float) mVideoView.getHeight())
/ (float) ((3 * mVideoView.getWidth()) / 4);
// Zoom to make the video fill the screen horizontally // Zoom to make the video fill the screen horizontally
float landscapeZoomFactor = ((float) mVideoView.getWidth()) / (float) ((3 * mVideoView.getHeight()) / 4); float landscapeZoomFactor =
((float) mVideoView.getWidth())
/ (float) ((3 * mVideoView.getHeight()) / 4);
mZoomFactor = Math.max(portraitZoomFactor, landscapeZoomFactor); mZoomFactor = Math.max(portraitZoomFactor, landscapeZoomFactor);
} else { } else {
@ -326,20 +342,15 @@ public class CallVideoFragment extends Fragment implements OnGestureListener, On
} }
@Override @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float velocityY) {
return false; return false;
} }
@Override @Override
public void onLongPress(MotionEvent e) { public void onLongPress(MotionEvent e) {}
}
@Override @Override
public void onShowPress(MotionEvent e) { public void onShowPress(MotionEvent e) {}
}
@Override @Override
public boolean onSingleTapUp(MotionEvent e) { public boolean onSingleTapUp(MotionEvent e) {

View file

@ -20,8 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.content.Context; import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
@ -30,11 +28,12 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.ChatMessage; import org.linphone.core.ChatMessage;
public class ChatMessageOldViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public class ChatMessageOldViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
public String messageId; public String messageId;
public Context mContext; public Context mContext;
public ChatMessage message; public ChatMessage message;
@ -66,7 +65,8 @@ public class ChatMessageOldViewHolder extends RecyclerView.ViewHolder implements
public CheckBox delete; public CheckBox delete;
private ChatMessageViewHolderClickListener mListener; private ChatMessageViewHolderClickListener mListener;
public ChatMessageOldViewHolder(Context context, View view, ChatMessageViewHolderClickListener listener) { public ChatMessageOldViewHolder(
Context context, View view, ChatMessageViewHolderClickListener listener) {
this(view); this(view);
mContext = context; mContext = context;
mListener = listener; mListener = listener;
@ -76,7 +76,7 @@ public class ChatMessageOldViewHolder extends RecyclerView.ViewHolder implements
public ChatMessageOldViewHolder(View view) { public ChatMessageOldViewHolder(View view) {
super(view); super(view);
eventLayout = view.findViewById(R.id.event); eventLayout = view.findViewById(R.id.event);
//eventTime = view.findViewById(R.id.event_date); // eventTime = view.findViewById(R.id.event_date);
eventMessage = view.findViewById(R.id.event_text); eventMessage = view.findViewById(R.id.event_text);
bubbleLayout = view.findViewById(R.id.bubble); bubbleLayout = view.findViewById(R.id.bubble);
@ -110,4 +110,4 @@ public class ChatMessageOldViewHolder extends RecyclerView.ViewHolder implements
mListener.onItemClicked(getAdapterPosition()); mListener.onItemClicked(getAdapterPosition());
} }
} }
} }

View file

@ -19,12 +19,10 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import android.Manifest; import android.Manifest;
import android.content.Context; import android.content.Context;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -42,16 +40,18 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.flexbox.FlexboxLayout; import com.google.android.flexbox.FlexboxLayout;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.R; import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.ChatMessage; import org.linphone.core.ChatMessage;
import org.linphone.core.ChatMessageListenerStub;
import org.linphone.core.Content; import org.linphone.core.Content;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.utils.FileUtils; import org.linphone.utils.FileUtils;
@ -60,12 +60,6 @@ import org.linphone.views.AsyncBitmap;
import org.linphone.views.BitmapWorkerTask; import org.linphone.views.BitmapWorkerTask;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private Context mContext; private Context mContext;
@ -93,7 +87,8 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
public CheckBox deleteMessage; public CheckBox deleteMessage;
private ChatMessageViewHolderClickListener mListener; private ChatMessageViewHolderClickListener mListener;
public ChatMessageViewHolder(Context context, View view, ChatMessageViewHolderClickListener listener) { public ChatMessageViewHolder(
Context context, View view, ChatMessageViewHolderClickListener listener) {
this(view); this(view);
mContext = context; mContext = context;
mListener = listener; mListener = listener;
@ -147,7 +142,9 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
ChatMessage.State status = message.getState(); ChatMessage.State status = message.getState();
Address remoteSender = message.getFromAddress(); Address remoteSender = message.getFromAddress();
String displayName; String displayName;
String time = LinphoneUtils.timestampToHumanDate(mContext, message.getTime(), R.string.messages_date_format); String time =
LinphoneUtils.timestampToHumanDate(
mContext, message.getTime(), R.string.messages_date_format);
if (message.isOutgoing()) { if (message.isOutgoing()) {
outgoingImdn.setVisibility(View.INVISIBLE); // For anchoring purposes outgoingImdn.setVisibility(View.INVISIBLE); // For anchoring purposes
@ -215,14 +212,24 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
if (fileContents.size() > 0) { if (fileContents.size() > 0) {
pictures.setVisibility(View.VISIBLE); pictures.setVisibility(View.VISIBLE);
for (Content c : fileContents) { for (Content c : fileContents) {
View content = LayoutInflater.from(mContext).inflate(R.layout.chat_bubble_content, null, false); View content =
LayoutInflater.from(mContext)
.inflate(R.layout.chat_bubble_content, null, false);
if (c.isFile() || (c.isFileTransfer() && message.isOutgoing())) { // If message is outgoing, even if content is file transfer we have the file available if (c.isFile()
|| (c.isFileTransfer()
&& message
.isOutgoing())) { // If message is outgoing, even if content
// is file transfer we have the file
// available
String filePath = c.getFilePath(); String filePath = c.getFilePath();
View v; View v;
if (FileUtils.isExtensionImage(filePath)) { if (FileUtils.isExtensionImage(filePath)) {
if (fileContents.size() == 1 && mContext.getResources().getBoolean(R.bool.use_big_pictures_to_preview_images_file_transfers)) { if (fileContents.size() == 1
&& mContext.getResources()
.getBoolean(
R.bool.use_big_pictures_to_preview_images_file_transfers)) {
v = content.findViewById(R.id.bigImage); v = content.findViewById(R.id.bigImage);
loadBitmap(c.getFilePath(), ((ImageView) v)); loadBitmap(c.getFilePath(), ((ImageView) v));
} else { } else {
@ -231,42 +238,56 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
} }
} else { } else {
v = content.findViewById(R.id.file); v = content.findViewById(R.id.file);
((TextView)v).setText(FileUtils.getNameFromFilePath(filePath)); ((TextView) v).setText(FileUtils.getNameFromFilePath(filePath));
} }
v.setVisibility(View.VISIBLE); v.setVisibility(View.VISIBLE);
v.setTag(c.getFilePath()); v.setTag(c.getFilePath());
v.setOnClickListener(new View.OnClickListener() { v.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
openFile((String) v.getTag()); public void onClick(View v) {
} openFile((String) v.getTag());
}); }
});
} else { } else {
Button download = content.findViewById(R.id.download); Button download = content.findViewById(R.id.download);
download.setVisibility(View.VISIBLE); download.setVisibility(View.VISIBLE);
if (mContext.getPackageManager().checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED) { if (mContext.getPackageManager()
.checkPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
mContext.getPackageName())
== PackageManager.PERMISSION_GRANTED) {
String filename = c.getName(); String filename = c.getName();
File file = new File(FileUtils.getStorageDirectory(mContext), filename); File file = new File(FileUtils.getStorageDirectory(mContext), filename);
int prefix = 1; int prefix = 1;
while (file.exists()) { while (file.exists()) {
file = new File(FileUtils.getStorageDirectory(mContext), prefix + "_" + filename); file =
Log.w("File with that name already exists, renamed to " + prefix + "_" + filename); new File(
FileUtils.getStorageDirectory(mContext),
prefix + "_" + filename);
Log.w(
"File with that name already exists, renamed to "
+ prefix
+ "_"
+ filename);
prefix += 1; prefix += 1;
} }
download.setTag(c); download.setTag(c);
c.setFilePath(file.getPath()); c.setFilePath(file.getPath());
download.setOnClickListener(new View.OnClickListener() { download.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
Content c = (Content) v.getTag(); public void onClick(View v) {
message.downloadContent(c); Content c = (Content) v.getTag();
} message.downloadContent(c);
}); }
});
} else { } else {
Log.w("WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file"); Log.w(
"WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file");
LinphoneActivity.instance().checkAndRequestExternalStoragePermission(); LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
} }
} }
@ -283,13 +304,21 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
if (path.startsWith("file://")) { if (path.startsWith("file://")) {
path = path.substring("file://".length()); path = path.substring("file://".length());
file = new File(path); file = new File(path);
contentUri = FileProvider.getUriForFile(mContext, mContext.getResources().getString(R.string.file_provider), file); contentUri =
FileProvider.getUriForFile(
mContext,
mContext.getResources().getString(R.string.file_provider),
file);
} else if (path.startsWith("content://")) { } else if (path.startsWith("content://")) {
contentUri = Uri.parse(path); contentUri = Uri.parse(path);
} else { } else {
file = new File(path); file = new File(path);
try { try {
contentUri = FileProvider.getUriForFile(mContext, mContext.getResources().getString(R.string.file_provider), file); contentUri =
FileProvider.getUriForFile(
mContext,
mContext.getResources().getString(R.string.file_provider),
file);
} catch (Exception e) { } catch (Exception e) {
contentUri = Uri.parse(path); contentUri = Uri.parse(path);
} }
@ -311,9 +340,11 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
private void loadBitmap(String path, ImageView imageView) { private void loadBitmap(String path, ImageView imageView) {
if (cancelPotentialWork(path, imageView)) { if (cancelPotentialWork(path, imageView)) {
Bitmap defaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_file); Bitmap defaultBitmap =
BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_file);
BitmapWorkerTask task = new BitmapWorkerTask(mContext, imageView, defaultBitmap); BitmapWorkerTask task = new BitmapWorkerTask(mContext, imageView, defaultBitmap);
final AsyncBitmap asyncBitmap = new AsyncBitmap(mContext.getResources(), defaultBitmap, task); final AsyncBitmap asyncBitmap =
new AsyncBitmap(mContext.getResources(), defaultBitmap, task);
imageView.setImageDrawable(asyncBitmap); imageView.setImageDrawable(asyncBitmap);
task.execute(path); task.execute(path);
} }
@ -336,5 +367,4 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
// No task associated with the ImageView, or an existing task was cancelled // No task associated with the ImageView, or an existing task was cancelled
return true; return true;
} }
}
}

View file

@ -20,13 +20,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull;
import org.linphone.mediastream.Log; import java.util.ArrayList;
import org.linphone.utils.LinphoneUtils; import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.linphone.R; import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
@ -34,15 +35,12 @@ import org.linphone.core.Address;
import org.linphone.core.ChatMessage; import org.linphone.core.ChatMessage;
import org.linphone.core.ChatMessageListenerStub; import org.linphone.core.ChatMessageListenerStub;
import org.linphone.core.EventLog; import org.linphone.core.EventLog;
import org.linphone.utils.LinphoneUtils;
import org.linphone.utils.SelectableAdapter; import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper; import org.linphone.utils.SelectableHelper;
import java.util.ArrayList; public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder>
import java.util.Arrays; implements ChatMessagesGenericAdapter {
import java.util.Collections;
import java.util.List;
public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder> implements ChatMessagesGenericAdapter {
public static int MAX_TIME_TO_GROUP_MESSAGES = 60; public static int MAX_TIME_TO_GROUP_MESSAGES = 60;
private Context mContext; private Context mContext;
@ -55,7 +53,13 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
private ChatMessageViewHolderClickListener mClickListener; private ChatMessageViewHolderClickListener mClickListener;
public ChatMessagesAdapter(ChatMessagesFragment fragment, SelectableHelper helper, int itemResource, EventLog[] history, ArrayList<LinphoneContact> participants, ChatMessageViewHolderClickListener clickListener) { public ChatMessagesAdapter(
ChatMessagesFragment fragment,
SelectableHelper helper,
int itemResource,
EventLog[] history,
ArrayList<LinphoneContact> participants,
ChatMessageViewHolderClickListener clickListener) {
super(helper); super(helper);
mFragment = fragment; mFragment = fragment;
mContext = mFragment.getActivity(); mContext = mFragment.getActivity();
@ -69,11 +73,10 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
@Override @Override
public ChatMessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ChatMessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()) View v = LayoutInflater.from(parent.getContext()).inflate(mItemResource, parent, false);
.inflate(mItemResource, parent, false);
ChatMessageViewHolder VH = new ChatMessageViewHolder(mContext, v, mClickListener); ChatMessageViewHolder VH = new ChatMessageViewHolder(mContext, v, mClickListener);
//Allows onLongClick ContextMenu on bubbles // Allows onLongClick ContextMenu on bubbles
mFragment.registerForContextMenu(v); mFragment.registerForContextMenu(v);
v.setTag(VH); v.setTag(VH);
return VH; return VH;
@ -100,26 +103,32 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
holder.deleteMessage.setTag(position); holder.deleteMessage.setTag(position);
} }
if ((message.isOutgoing() && message.getState() != ChatMessage.State.Displayed) || (!message.isOutgoing() && message.isFileTransfer())) { if ((message.isOutgoing() && message.getState() != ChatMessage.State.Displayed)
|| (!message.isOutgoing() && message.isFileTransfer())) {
if (!mTransientMessages.contains(message)) { if (!mTransientMessages.contains(message)) {
mTransientMessages.add(message); mTransientMessages.add(message);
} }
message.setUserData(holder); // This only works if JAVA object is kept, hence the transient list message.setUserData(
message.setListener(new ChatMessageListenerStub() { holder); // This only works if JAVA object is kept, hence the transient list
@Override message.setListener(
public void onMsgStateChanged(ChatMessage message, ChatMessage.State state) { new ChatMessageListenerStub() {
ChatMessageViewHolder holder = (ChatMessageViewHolder) message.getUserData(); @Override
if (holder != null) { public void onMsgStateChanged(
notifyItemChanged(holder.getAdapterPosition()); ChatMessage message, ChatMessage.State state) {
} else { ChatMessageViewHolder holder =
// Just in case, better to refresh the whole view than to miss an update (ChatMessageViewHolder) message.getUserData();
notifyDataSetChanged(); if (holder != null) {
} notifyItemChanged(holder.getAdapterPosition());
if (state == ChatMessage.State.Displayed) { } else {
mTransientMessages.remove(message); // Just in case, better to refresh the whole view than to miss
} // an update
} notifyDataSetChanged();
}); }
if (state == ChatMessage.State.Displayed) {
mTransientMessages.remove(message);
}
}
});
} }
LinphoneContact contact = null; LinphoneContact contact = null;
@ -147,7 +156,8 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
} }
String displayName = ""; String displayName = "";
if (address != null) { if (address != null) {
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(address);
if (contact != null) { if (contact != null) {
displayName = contact.getFullName(); displayName = contact.getFullName();
} else { } else {
@ -166,47 +176,65 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
break; break;
case ConferenceParticipantAdded: case ConferenceParticipantAdded:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.participant_added).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.participant_added)
.replace("%s", displayName));
break; break;
case ConferenceParticipantRemoved: case ConferenceParticipantRemoved:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.participant_removed).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.participant_removed)
.replace("%s", displayName));
break; break;
case ConferenceSubjectChanged: case ConferenceSubjectChanged:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.subject_changed).replace("%s", event.getSubject())); holder.eventMessage.setText(
mContext.getString(R.string.subject_changed)
.replace("%s", event.getSubject()));
break; break;
case ConferenceParticipantSetAdmin: case ConferenceParticipantSetAdmin:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.admin_set).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.admin_set).replace("%s", displayName));
break; break;
case ConferenceParticipantUnsetAdmin: case ConferenceParticipantUnsetAdmin:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.admin_unset).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.admin_unset).replace("%s", displayName));
break; break;
case ConferenceParticipantDeviceAdded: case ConferenceParticipantDeviceAdded:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.device_added).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.device_added).replace("%s", displayName));
break; break;
case ConferenceParticipantDeviceRemoved: case ConferenceParticipantDeviceRemoved:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.device_removed).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.device_removed).replace("%s", displayName));
break; break;
case ConferenceSecurityEvent: case ConferenceSecurityEvent:
holder.securityEventLayout.setVisibility(View.VISIBLE); holder.securityEventLayout.setVisibility(View.VISIBLE);
switch (event.getSecurityEventType()) { switch (event.getSecurityEventType()) {
case EncryptionIdentityKeyChanged: case EncryptionIdentityKeyChanged:
holder.securityEventMessage.setText(mContext.getString(R.string.lime_identity_key_changed).replace("%s", displayName)); holder.securityEventMessage.setText(
mContext.getString(R.string.lime_identity_key_changed)
.replace("%s", displayName));
break; break;
case ManInTheMiddleDetected: case ManInTheMiddleDetected:
holder.securityEventMessage.setText(mContext.getString(R.string.man_in_the_middle_detected).replace("%s", displayName)); holder.securityEventMessage.setText(
mContext.getString(R.string.man_in_the_middle_detected)
.replace("%s", displayName));
break; break;
case SecurityLevelDowngraded: case SecurityLevelDowngraded:
holder.securityEventMessage.setText(mContext.getString(R.string.security_level_downgraded).replace("%s", displayName)); holder.securityEventMessage.setText(
mContext.getString(R.string.security_level_downgraded)
.replace("%s", displayName));
break; break;
case ParticipantMaxDeviceCountExceeded: case ParticipantMaxDeviceCountExceeded:
holder.securityEventMessage.setText(mContext.getString(R.string.participant_max_count_exceeded).replace("%s", displayName)); holder.securityEventMessage.setText(
mContext.getString(R.string.participant_max_count_exceeded)
.replace("%s", displayName));
break; break;
case None: case None:
default: default:
@ -216,7 +244,10 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
case None: case None:
default: default:
holder.eventLayout.setVisibility(View.VISIBLE); holder.eventLayout.setVisibility(View.VISIBLE);
holder.eventMessage.setText(mContext.getString(R.string.unexpected_event).replace("%s", displayName).replace("%i", String.valueOf(event.getType().toInt()))); holder.eventMessage.setText(
mContext.getString(R.string.unexpected_event)
.replace("%s", displayName)
.replace("%i", String.valueOf(event.getType().toInt())));
break; break;
} }
} }
@ -274,22 +305,29 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
notifyItemRemoved(i); notifyItemRemoved(i);
} }
private void changeBackgroundDependingOnPreviousAndNextEvents(ChatMessage message, ChatMessageViewHolder holder, int position) { private void changeBackgroundDependingOnPreviousAndNextEvents(
ChatMessage message, ChatMessageViewHolder holder, int position) {
boolean hasPrevious = false, hasNext = false; boolean hasPrevious = false, hasNext = false;
// Do not forget history is reversed, so previous in order is next in list display and chronology ! // Do not forget history is reversed, so previous in order is next in list display and
if (position > 0 && mContext.getResources().getBoolean(R.bool.lower_space_between_chat_bubbles_if_same_person)) { // chronology !
if (position > 0
&& mContext.getResources()
.getBoolean(R.bool.lower_space_between_chat_bubbles_if_same_person)) {
EventLog previousEvent = (EventLog) getItem(position - 1); EventLog previousEvent = (EventLog) getItem(position - 1);
if (previousEvent.getType() == EventLog.Type.ConferenceChatMessage) { if (previousEvent.getType() == EventLog.Type.ConferenceChatMessage) {
ChatMessage previousMessage = previousEvent.getChatMessage(); ChatMessage previousMessage = previousEvent.getChatMessage();
if (previousMessage.getFromAddress().weakEqual(message.getFromAddress())) { if (previousMessage.getFromAddress().weakEqual(message.getFromAddress())) {
if (previousMessage.getTime() - message.getTime() < MAX_TIME_TO_GROUP_MESSAGES) { if (previousMessage.getTime() - message.getTime()
< MAX_TIME_TO_GROUP_MESSAGES) {
hasPrevious = true; hasPrevious = true;
} }
} }
} }
} }
if (position < mHistory.size() - 1 && mContext.getResources().getBoolean(R.bool.lower_space_between_chat_bubbles_if_same_person)) { if (position < mHistory.size() - 1
&& mContext.getResources()
.getBoolean(R.bool.lower_space_between_chat_bubbles_if_same_person)) {
EventLog nextEvent = (EventLog) getItem(position + 1); EventLog nextEvent = (EventLog) getItem(position + 1);
if (nextEvent.getType() == EventLog.Type.ConferenceChatMessage) { if (nextEvent.getType() == EventLog.Type.ConferenceChatMessage) {
ChatMessage nextMessage = nextEvent.getChatMessage(); ChatMessage nextMessage = nextEvent.getChatMessage();

File diff suppressed because it is too large Load diff

View file

@ -1,28 +1,27 @@
package org.linphone.chat; package org.linphone.chat;
/* /*
ChatMessagesGenericAdapter.java ChatMessagesGenericAdapter.java
Copyright (C) 2018 Belledonne Communications, Grenoble, France Copyright (C) 2018 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import org.linphone.contacts.LinphoneContact;
import org.linphone.core.EventLog;
import java.util.ArrayList; import java.util.ArrayList;
import org.linphone.contacts.LinphoneContact;
import org.linphone.core.EventLog;
public interface ChatMessagesGenericAdapter { public interface ChatMessagesGenericAdapter {
void addToHistory(EventLog log); void addToHistory(EventLog log);

View file

@ -19,22 +19,15 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import android.Manifest; import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -43,7 +36,13 @@ import android.view.ViewGroup;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
@ -65,18 +64,8 @@ import org.linphone.views.AsyncBitmap;
import org.linphone.views.BitmapWorkerTask; import org.linphone.views.BitmapWorkerTask;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
import java.io.File; public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldViewHolder>
import java.io.FileNotFoundException; implements ChatMessagesGenericAdapter {
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldViewHolder> implements ChatMessagesGenericAdapter {
private static int MARGIN_BETWEEN_MESSAGES = 10; private static int MARGIN_BETWEEN_MESSAGES = 10;
private static int SIDE_MARGIN = 100; private static int SIDE_MARGIN = 100;
@ -90,7 +79,13 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
private ChatMessageViewHolderClickListener mClickListener; private ChatMessageViewHolderClickListener mClickListener;
public ChatMessagesOldAdapter(ChatMessagesFragment fragment, SelectableHelper helper, int itemResource, EventLog[] history, ArrayList<LinphoneContact> participants, ChatMessageViewHolderClickListener clickListener) { public ChatMessagesOldAdapter(
ChatMessagesFragment fragment,
SelectableHelper helper,
int itemResource,
EventLog[] history,
ArrayList<LinphoneContact> participants,
ChatMessageViewHolderClickListener clickListener) {
super(helper); super(helper);
mFragment = fragment; mFragment = fragment;
mContext = mFragment.getActivity(); mContext = mFragment.getActivity();
@ -99,51 +94,55 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
Collections.reverse(mHistory); Collections.reverse(mHistory);
mParticipants = participants; mParticipants = participants;
mClickListener = clickListener; mClickListener = clickListener;
mListener = new ChatMessageListenerStub() { mListener =
@Override new ChatMessageListenerStub() {
public void onFileTransferProgressIndication(ChatMessage message, Content content, int offset, int total) { @Override
ChatMessageOldViewHolder holder = (ChatMessageOldViewHolder) message.getUserData(); public void onFileTransferProgressIndication(
if (holder == null) return; ChatMessage message, Content content, int offset, int total) {
ChatMessageOldViewHolder holder =
(ChatMessageOldViewHolder) message.getUserData();
if (holder == null) return;
if (offset == total) { if (offset == total) {
holder.fileTransferProgressBar.setVisibility(View.GONE); holder.fileTransferProgressBar.setVisibility(View.GONE);
holder.fileTransferAction.setVisibility(View.GONE); holder.fileTransferAction.setVisibility(View.GONE);
holder.fileTransferLayout.setVisibility(View.GONE); holder.fileTransferLayout.setVisibility(View.GONE);
displayAttachedFile(message, holder); displayAttachedFile(message, holder);
} else { } else {
holder.fileTransferProgressBar.setVisibility(View.VISIBLE); holder.fileTransferProgressBar.setVisibility(View.VISIBLE);
holder.fileTransferProgressBar.setProgress(offset * 100 / total); holder.fileTransferProgressBar.setProgress(offset * 100 / total);
} }
}
@Override
public void onMsgStateChanged(ChatMessage message, ChatMessage.State state) {
if (state == ChatMessage.State.FileTransferDone) {
if (!message.isOutgoing()) {
message.setAppdata(message.getFileTransferFilepath());
} }
message.setFileTransferFilepath(null); // Not needed anymore, will help differenciate between InProgress states for file transfer / message sending
}
for (int i = 0; i < mHistory.size(); i++) {
EventLog log = mHistory.get(i);
if (log.getType() == EventLog.Type.ConferenceChatMessage && log.getChatMessage() == message) {
notifyItemChanged(i);
break;
}
}
} @Override
}; public void onMsgStateChanged(ChatMessage message, ChatMessage.State state) {
if (state == ChatMessage.State.FileTransferDone) {
if (!message.isOutgoing()) {
message.setAppdata(message.getFileTransferFilepath());
}
message.setFileTransferFilepath(
null); // Not needed anymore, will help differenciate between
// InProgress states for file transfer / message sending
}
for (int i = 0; i < mHistory.size(); i++) {
EventLog log = mHistory.get(i);
if (log.getType() == EventLog.Type.ConferenceChatMessage
&& log.getChatMessage() == message) {
notifyItemChanged(i);
break;
}
}
}
};
} }
@Override @Override
public ChatMessageOldViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ChatMessageOldViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()) View v = LayoutInflater.from(parent.getContext()).inflate(mItemResource, parent, false);
.inflate(mItemResource, parent, false);
ChatMessageOldViewHolder VH = new ChatMessageOldViewHolder(mContext, v, mClickListener); ChatMessageOldViewHolder VH = new ChatMessageOldViewHolder(mContext, v, mClickListener);
//Allows onLongClick ContextMenu on bubbles // Allows onLongClick ContextMenu on bubbles
mFragment.registerForContextMenu(v); mFragment.registerForContextMenu(v);
v.setTag(VH); v.setTag(VH);
return VH; return VH;
@ -176,7 +175,9 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
holder.bubbleLayout.setVisibility(View.VISIBLE); holder.bubbleLayout.setVisibility(View.VISIBLE);
final ChatMessage message = event.getChatMessage(); final ChatMessage message = event.getChatMessage();
if (position > 0 && mContext.getResources().getBoolean(R.bool.lower_space_between_chat_bubbles_if_same_person)) { if (position > 0
&& mContext.getResources()
.getBoolean(R.bool.lower_space_between_chat_bubbles_if_same_person)) {
EventLog previousEvent = (EventLog) getItem(position - 1); EventLog previousEvent = (EventLog) getItem(position - 1);
if (previousEvent.getType() == EventLog.Type.ConferenceChatMessage) { if (previousEvent.getType() == EventLog.Type.ConferenceChatMessage) {
ChatMessage previousMessage = previousEvent.getChatMessage(); ChatMessage previousMessage = previousEvent.getChatMessage();
@ -192,7 +193,10 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
holder.messageId = message.getMessageId(); holder.messageId = message.getMessageId();
message.setUserData(holder); message.setUserData(holder);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
ChatMessage.State status = message.getState(); ChatMessage.State status = message.getState();
Address remoteSender = message.getFromAddress(); Address remoteSender = message.getFromAddress();
@ -206,7 +210,9 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
holder.messageSendingInProgress.setVisibility(View.VISIBLE); holder.messageSendingInProgress.setVisibility(View.VISIBLE);
} }
if (!message.isSecured() && LinphoneManager.getLc().limeEnabled() == LimeState.Mandatory && status != ChatMessage.State.InProgress) { if (!message.isSecured()
&& LinphoneManager.getLc().limeEnabled() == LimeState.Mandatory
&& status != ChatMessage.State.InProgress) {
holder.messageStatus.setVisibility(View.VISIBLE); holder.messageStatus.setVisibility(View.VISIBLE);
holder.messageStatus.setImageResource(R.drawable.chat_unsecure); holder.messageStatus.setImageResource(R.drawable.chat_unsecure);
} }
@ -233,20 +239,31 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
holder.imdmLabel.setTextColor(mContext.getResources().getColor(R.color.colorI)); holder.imdmLabel.setTextColor(mContext.getResources().getColor(R.color.colorI));
} }
//layoutParams allow bubbles alignment during selection mode // layoutParams allow bubbles alignment during selection mode
if (isEditionEnabled()) { if (isEditionEnabled()) {
layoutParams.addRule(RelativeLayout.LEFT_OF, holder.delete.getId()); layoutParams.addRule(RelativeLayout.LEFT_OF, holder.delete.getId());
layoutParams.setMargins(SIDE_MARGIN, MARGIN_BETWEEN_MESSAGES / 2, 0, MARGIN_BETWEEN_MESSAGES / 2); layoutParams.setMargins(
SIDE_MARGIN,
MARGIN_BETWEEN_MESSAGES / 2,
0,
MARGIN_BETWEEN_MESSAGES / 2);
} else { } else {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParams.setMargins(SIDE_MARGIN, MARGIN_BETWEEN_MESSAGES / 2, 0, MARGIN_BETWEEN_MESSAGES / 2); layoutParams.setMargins(
SIDE_MARGIN,
MARGIN_BETWEEN_MESSAGES / 2,
0,
MARGIN_BETWEEN_MESSAGES / 2);
} }
holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_outgoing); holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_outgoing);
Compatibility.setTextAppearance(holder.contactName, mContext, R.style.font3); Compatibility.setTextAppearance(holder.contactName, mContext, R.style.font3);
Compatibility.setTextAppearance(holder.fileTransferAction, mContext, R.style.font15); Compatibility.setTextAppearance(
holder.fileTransferAction.setBackgroundResource(R.drawable.resizable_confirm_delete_button); holder.fileTransferAction, mContext, R.style.font15);
ContactAvatar.setAvatarMask(holder.avatarLayout, R.drawable.avatar_chat_mask_outgoing); holder.fileTransferAction.setBackgroundResource(
R.drawable.resizable_confirm_delete_button);
ContactAvatar.setAvatarMask(
holder.avatarLayout, R.drawable.avatar_chat_mask_outgoing);
} else { } else {
for (LinphoneContact c : mParticipants) { for (LinphoneContact c : mParticipants) {
if (c != null && c.hasAddress(remoteSender.asStringUriOnly())) { if (c != null && c.hasAddress(remoteSender.asStringUriOnly())) {
@ -257,16 +274,25 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
if (isEditionEnabled()) { if (isEditionEnabled()) {
layoutParams.addRule(RelativeLayout.LEFT_OF, holder.delete.getId()); layoutParams.addRule(RelativeLayout.LEFT_OF, holder.delete.getId());
layoutParams.setMargins(SIDE_MARGIN, MARGIN_BETWEEN_MESSAGES / 2, 0, MARGIN_BETWEEN_MESSAGES / 2); layoutParams.setMargins(
SIDE_MARGIN,
MARGIN_BETWEEN_MESSAGES / 2,
0,
MARGIN_BETWEEN_MESSAGES / 2);
} else { } else {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.setMargins(0, MARGIN_BETWEEN_MESSAGES / 2, SIDE_MARGIN, MARGIN_BETWEEN_MESSAGES / 2); layoutParams.setMargins(
0,
MARGIN_BETWEEN_MESSAGES / 2,
SIDE_MARGIN,
MARGIN_BETWEEN_MESSAGES / 2);
} }
holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_incoming); holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_incoming);
Compatibility.setTextAppearance(holder.contactName, mContext, R.style.font9); Compatibility.setTextAppearance(holder.contactName, mContext, R.style.font9);
Compatibility.setTextAppearance(holder.fileTransferAction, mContext, R.style.font8); Compatibility.setTextAppearance(holder.fileTransferAction, mContext, R.style.font8);
holder.fileTransferAction.setBackgroundResource(R.drawable.resizable_assistant_button); holder.fileTransferAction.setBackgroundResource(
R.drawable.resizable_assistant_button);
ContactAvatar.setAvatarMask(holder.avatarLayout, R.drawable.avatar_chat_mask); ContactAvatar.setAvatarMask(holder.avatarLayout, R.drawable.avatar_chat_mask);
} }
@ -284,7 +310,11 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
displayName = LinphoneUtils.getAddressDisplayName(remoteSender); displayName = LinphoneUtils.getAddressDisplayName(remoteSender);
ContactAvatar.displayAvatar(displayName, holder.avatarLayout); ContactAvatar.displayAvatar(displayName, holder.avatarLayout);
} }
holder.contactName.setText(LinphoneUtils.timestampToHumanDate(mContext, message.getTime(), R.string.messages_date_format) + " - " + displayName); holder.contactName.setText(
LinphoneUtils.timestampToHumanDate(
mContext, message.getTime(), R.string.messages_date_format)
+ " - "
+ displayName);
if (message.hasTextContent()) { if (message.hasTextContent()) {
String msg = message.getTextContent(); String msg = message.getTextContent();
@ -320,42 +350,62 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
holder.fileTransferAction.setVisibility(View.GONE); holder.fileTransferAction.setVisibility(View.GONE);
} else { } else {
holder.fileTransferAction.setText(mContext.getString(R.string.accept)); holder.fileTransferAction.setText(mContext.getString(R.string.accept));
holder.fileTransferAction.setOnClickListener(new View.OnClickListener() { holder.fileTransferAction.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
if (mContext.getPackageManager().checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED) { public void onClick(View v) {
v.setEnabled(false); if (mContext.getPackageManager()
String filename = message.getFileTransferInformation().getName(); .checkPermission(
File file = new File(FileUtils.getStorageDirectory(mContext), filename); Manifest.permission
int prefix = 1; .WRITE_EXTERNAL_STORAGE,
while (file.exists()) { mContext.getPackageName())
file = new File(FileUtils.getStorageDirectory(mContext), prefix + "_" + filename); == PackageManager.PERMISSION_GRANTED) {
Log.w("File with that name already exists, renamed to " + prefix + "_" + filename); v.setEnabled(false);
prefix += 1; String filename =
} message.getFileTransferInformation().getName();
message.setListener(mListener); File file =
message.setFileTransferFilepath(file.getPath()); new File(
message.downloadFile(); FileUtils.getStorageDirectory(mContext),
filename);
int prefix = 1;
while (file.exists()) {
file =
new File(
FileUtils.getStorageDirectory(mContext),
prefix + "_" + filename);
Log.w(
"File with that name already exists, renamed to "
+ prefix
+ "_"
+ filename);
prefix += 1;
}
message.setListener(mListener);
message.setFileTransferFilepath(file.getPath());
message.downloadFile();
} else { } else {
Log.w("WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file"); Log.w(
LinphoneActivity.instance().checkAndRequestExternalStoragePermission(); "WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file");
} LinphoneActivity.instance()
} .checkAndRequestExternalStoragePermission();
}); }
}
});
} }
} else if (message.isFileTransferInProgress()) { // Outgoing file transfer in progress } else if (message.isFileTransferInProgress()) { // Outgoing file transfer in progress
message.setListener(mListener); // add the listener for file upload progress display message.setListener(mListener); // add the listener for file upload progress display
holder.messageSendingInProgress.setVisibility(View.GONE); holder.messageSendingInProgress.setVisibility(View.GONE);
holder.fileTransferLayout.setVisibility(View.VISIBLE); holder.fileTransferLayout.setVisibility(View.VISIBLE);
holder.fileTransferAction.setText(mContext.getString(R.string.cancel)); holder.fileTransferAction.setText(mContext.getString(R.string.cancel));
holder.fileTransferAction.setOnClickListener(new View.OnClickListener() { holder.fileTransferAction.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
message.cancelFileTransfer(); public void onClick(View v) {
notifyItemChanged(holder.getAdapterPosition()); message.cancelFileTransfer();
} notifyItemChanged(holder.getAdapterPosition());
}); }
});
} }
holder.bubbleLayout.setLayoutParams(layoutParams); holder.bubbleLayout.setLayoutParams(layoutParams);
@ -371,7 +421,8 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
} }
String displayName = ""; String displayName = "";
if (address != null) { if (address != null) {
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(address);
if (contact != null) { if (contact != null) {
displayName = contact.getFullName(); displayName = contact.getFullName();
} else { } else {
@ -387,43 +438,62 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
holder.eventMessage.setText(mContext.getString(R.string.conference_destroyed)); holder.eventMessage.setText(mContext.getString(R.string.conference_destroyed));
break; break;
case ConferenceParticipantAdded: case ConferenceParticipantAdded:
holder.eventMessage.setText(mContext.getString(R.string.participant_added).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.participant_added)
.replace("%s", displayName));
break; break;
case ConferenceParticipantRemoved: case ConferenceParticipantRemoved:
holder.eventMessage.setText(mContext.getString(R.string.participant_removed).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.participant_removed)
.replace("%s", displayName));
break; break;
case ConferenceSubjectChanged: case ConferenceSubjectChanged:
holder.eventMessage.setText(mContext.getString(R.string.subject_changed).replace("%s", event.getSubject())); holder.eventMessage.setText(
mContext.getString(R.string.subject_changed)
.replace("%s", event.getSubject()));
break; break;
case ConferenceParticipantSetAdmin: case ConferenceParticipantSetAdmin:
holder.eventMessage.setText(mContext.getString(R.string.admin_set).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.admin_set).replace("%s", displayName));
break; break;
case ConferenceParticipantUnsetAdmin: case ConferenceParticipantUnsetAdmin:
holder.eventMessage.setText(mContext.getString(R.string.admin_unset).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.admin_unset).replace("%s", displayName));
break; break;
case ConferenceParticipantDeviceAdded: case ConferenceParticipantDeviceAdded:
holder.eventMessage.setText(mContext.getString(R.string.device_added).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.device_added).replace("%s", displayName));
break; break;
case ConferenceParticipantDeviceRemoved: case ConferenceParticipantDeviceRemoved:
holder.eventMessage.setText(mContext.getString(R.string.device_removed).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.device_removed).replace("%s", displayName));
break; break;
case ConferenceSecurityEvent: case ConferenceSecurityEvent:
holder.eventMessage.setTextColor(mContext.getResources().getColor(R.color.colorI)); holder.eventMessage.setTextColor(
mContext.getResources().getColor(R.color.colorI));
holder.eventLayout.setBackgroundResource(R.drawable.event_decoration_red); holder.eventLayout.setBackgroundResource(R.drawable.event_decoration_red);
holder.eventLayout.setBackgroundResource(R.drawable.event_decoration_red); holder.eventLayout.setBackgroundResource(R.drawable.event_decoration_red);
switch (event.getSecurityEventType()) { switch (event.getSecurityEventType()) {
case EncryptionIdentityKeyChanged: case EncryptionIdentityKeyChanged:
holder.eventMessage.setText(mContext.getString(R.string.lime_identity_key_changed).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.lime_identity_key_changed)
.replace("%s", displayName));
break; break;
case ManInTheMiddleDetected: case ManInTheMiddleDetected:
holder.eventMessage.setText(mContext.getString(R.string.man_in_the_middle_detected).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.man_in_the_middle_detected)
.replace("%s", displayName));
break; break;
case SecurityLevelDowngraded: case SecurityLevelDowngraded:
holder.eventMessage.setText(mContext.getString(R.string.security_level_downgraded).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.security_level_downgraded)
.replace("%s", displayName));
break; break;
case ParticipantMaxDeviceCountExceeded: case ParticipantMaxDeviceCountExceeded:
holder.eventMessage.setText(mContext.getString(R.string.participant_max_count_exceeded).replace("%s", displayName)); holder.eventMessage.setText(
mContext.getString(R.string.participant_max_count_exceeded)
.replace("%s", displayName));
break; break;
case None: case None:
default: default:
@ -432,7 +502,10 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
break; break;
case None: case None:
default: default:
holder.eventMessage.setText(mContext.getString(R.string.unexpected_event).replace("%s", displayName).replace("%i", String.valueOf(event.getType().toInt()))); holder.eventMessage.setText(
mContext.getString(R.string.unexpected_event)
.replace("%s", displayName)
.replace("%i", String.valueOf(event.getType().toInt())));
break; break;
} }
} }
@ -490,9 +563,11 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
private void loadBitmap(String path, ImageView imageView) { private void loadBitmap(String path, ImageView imageView) {
if (cancelPotentialWork(path, imageView)) { if (cancelPotentialWork(path, imageView)) {
mDefaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_file); mDefaultBitmap =
BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_file);
BitmapWorkerTask task = new BitmapWorkerTask(mContext, imageView, mDefaultBitmap); BitmapWorkerTask task = new BitmapWorkerTask(mContext, imageView, mDefaultBitmap);
final AsyncBitmap asyncBitmap = new AsyncBitmap(mContext.getResources(), mDefaultBitmap, task); final AsyncBitmap asyncBitmap =
new AsyncBitmap(mContext.getResources(), mDefaultBitmap, task);
imageView.setImageDrawable(asyncBitmap); imageView.setImageDrawable(asyncBitmap);
task.execute(path); task.execute(path);
} }
@ -505,13 +580,21 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
if (path.startsWith("file://")) { if (path.startsWith("file://")) {
path = path.substring("file://".length()); path = path.substring("file://".length());
file = new File(path); file = new File(path);
contentUri = FileProvider.getUriForFile(mContext, mContext.getResources().getString(R.string.file_provider), file); contentUri =
FileProvider.getUriForFile(
mContext,
mContext.getResources().getString(R.string.file_provider),
file);
} else if (path.startsWith("content://")) { } else if (path.startsWith("content://")) {
contentUri = Uri.parse(path); contentUri = Uri.parse(path);
} else { } else {
file = new File(path); file = new File(path);
try { try {
contentUri = FileProvider.getUriForFile(mContext, mContext.getResources().getString(R.string.file_provider), file); contentUri =
FileProvider.getUriForFile(
mContext,
mContext.getResources().getString(R.string.file_provider),
file);
} catch (Exception e) { } catch (Exception e) {
contentUri = Uri.parse(path); contentUri = Uri.parse(path);
} }
@ -552,12 +635,13 @@ public class ChatMessagesOldAdapter extends SelectableAdapter<ChatMessageOldView
} else { } else {
holder.openFileButton.setVisibility(View.VISIBLE); holder.openFileButton.setVisibility(View.VISIBLE);
holder.openFileButton.setTag(appData); holder.openFileButton.setTag(appData);
holder.openFileButton.setOnClickListener(new View.OnClickListener() { holder.openFileButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
openFile((String) v.getTag()); public void onClick(View v) {
} openFile((String) v.getTag());
}); }
});
} }
} }
} }

View file

@ -19,11 +19,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.chat; package org.linphone.chat;
import static android.content.Context.INPUT_METHOD_SERVICE;
import android.app.Fragment; import android.app.Fragment;
import android.os.Bundle; import android.os.Bundle;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -36,11 +35,14 @@ import android.widget.RelativeLayout;
import android.widget.SearchView; import android.widget.SearchView;
import android.widget.Switch; import android.widget.Switch;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import org.linphone.LinphoneManager; import androidx.recyclerview.widget.LinearLayoutManager;
import org.linphone.settings.LinphonePreferences; import androidx.recyclerview.widget.RecyclerView;
import org.linphone.R; import java.util.ArrayList;
import java.util.List;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.contacts.ContactAddress; import org.linphone.contacts.ContactAddress;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.ContactsUpdatedListener; import org.linphone.contacts.ContactsUpdatedListener;
@ -52,14 +54,13 @@ import org.linphone.core.Core;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.views.ContactSelectView; import org.linphone.views.ContactSelectView;
import java.util.ArrayList; public class ChatRoomCreationFragment extends Fragment
import java.util.List; implements View.OnClickListener,
SearchContactsListAdapter.ViewHolder.ClickListener,
import static android.content.Context.INPUT_METHOD_SERVICE; ContactsUpdatedListener {
public class ChatRoomCreationFragment extends Fragment implements View.OnClickListener, SearchContactsListAdapter.ViewHolder.ClickListener, ContactsUpdatedListener {
private RecyclerView mContactsList; private RecyclerView mContactsList;
private LinearLayout mContactsSelectedLayout; private LinearLayout mContactsSelectedLayout;
private HorizontalScrollView mContactsSelectLayout; private HorizontalScrollView mContactsSelectLayout;
@ -81,7 +82,8 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
private boolean mChatRoomEncrypted; private boolean mChatRoomEncrypted;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.chat_create, container, false); View view = inflater.inflate(R.layout.chat_create, container, false);
@ -92,7 +94,9 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
if (getArguments() != null) { if (getArguments() != null) {
if (getArguments().getSerializable("selectedContacts") != null) { if (getArguments().getSerializable("selectedContacts") != null) {
mContactsSelected = (ArrayList<ContactAddress>) getArguments().getSerializable("selectedContacts"); mContactsSelected =
(ArrayList<ContactAddress>)
getArguments().getSerializable("selectedContacts");
} }
mChatRoomSubject = getArguments().getString("subject"); mChatRoomSubject = getArguments().getString("subject");
mChatRoomAddress = getArguments().getString("groupChatRoomAddress"); mChatRoomAddress = getArguments().getString("groupChatRoomAddress");
@ -127,21 +131,24 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
mContactsFetchInProgress = view.findViewById(R.id.contactsFetchInProgress); mContactsFetchInProgress = view.findViewById(R.id.contactsFetchInProgress);
mContactsFetchInProgress.setVisibility(View.VISIBLE); mContactsFetchInProgress.setVisibility(View.VISIBLE);
mSearchAdapter = new SearchContactsListAdapter(null, mContactsFetchInProgress, this, mCreateGroupChatRoom == false); mSearchAdapter =
new SearchContactsListAdapter(
null, mContactsFetchInProgress, this, mCreateGroupChatRoom == false);
mSearchField = view.findViewById(R.id.searchField); mSearchField = view.findViewById(R.id.searchField);
mSearchField.setOnQueryTextListener(new SearchView.OnQueryTextListener() { mSearchField.setOnQueryTextListener(
@Override new SearchView.OnQueryTextListener() {
public boolean onQueryTextSubmit(String query) { @Override
return true; public boolean onQueryTextSubmit(String query) {
} return true;
}
@Override @Override
public boolean onQueryTextChange(String newText) { public boolean onQueryTextChange(String newText) {
mSearchAdapter.searchContacts(newText, mContactsList); mSearchAdapter.searchContacts(newText, mContactsList);
return true; return true;
} }
}); });
mLinphoneContactsToggle = view.findViewById(R.id.layout_linphone_contacts); mLinphoneContactsToggle = view.findViewById(R.id.layout_linphone_contacts);
mAllContactsToggle = view.findViewById(R.id.layout_all_contacts); mAllContactsToggle = view.findViewById(R.id.layout_all_contacts);
@ -149,39 +156,49 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
mSecurityToggle = view.findViewById(R.id.security_toogle); mSecurityToggle = view.findViewById(R.id.security_toogle);
mSecurityToggleOn = view.findViewById(R.id.security_toogle_on); mSecurityToggleOn = view.findViewById(R.id.security_toogle_on);
mSecurityToggleOff = view.findViewById(R.id.security_toogle_off); mSecurityToggleOff = view.findViewById(R.id.security_toogle_off);
mSecurityToggleOn.setOnClickListener(new View.OnClickListener() { mSecurityToggleOn.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
mSecurityToggle.setChecked(true); public void onClick(View v) {
} mSecurityToggle.setChecked(true);
}); }
mSecurityToggleOff.setOnClickListener(new View.OnClickListener() { });
@Override mSecurityToggleOff.setOnClickListener(
public void onClick(View v) { new View.OnClickListener() {
mSecurityToggle.setChecked(false); @Override
} public void onClick(View v) {
}); mSecurityToggle.setChecked(false);
}
});
mSecurityToggle.setChecked(mChatRoomEncrypted); mSecurityToggle.setChecked(mChatRoomEncrypted);
ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
if ((mChatRoomSubject != null && mChatRoomAddress != null) || (lpc == null || lpc.getConferenceFactoryUri() == null)) { if ((mChatRoomSubject != null && mChatRoomAddress != null)
|| (lpc == null || lpc.getConferenceFactoryUri() == null)) {
mSecurityToggle.setVisibility(View.GONE); mSecurityToggle.setVisibility(View.GONE);
mSecurityToggleOn.setVisibility(View.GONE); mSecurityToggleOn.setVisibility(View.GONE);
mSecurityToggleOff.setVisibility(View.GONE); mSecurityToggleOff.setVisibility(View.GONE);
} }
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext()); LinearLayoutManager layoutManager =
new LinearLayoutManager(getActivity().getApplicationContext());
mContactsList.setAdapter(mSearchAdapter); mContactsList.setAdapter(mSearchAdapter);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mContactsList.getContext(), DividerItemDecoration dividerItemDecoration =
layoutManager.getOrientation()); new DividerItemDecoration(
dividerItemDecoration.setDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.divider)); mContactsList.getContext(), layoutManager.getOrientation());
dividerItemDecoration.setDrawable(
getActivity()
.getApplicationContext()
.getResources()
.getDrawable(R.drawable.divider));
mContactsList.addItemDecoration(dividerItemDecoration); mContactsList.addItemDecoration(dividerItemDecoration);
mContactsList.setLayoutManager(layoutManager); mContactsList.setLayoutManager(layoutManager);
if (savedInstanceState != null && savedInstanceState.getStringArrayList("mContactsSelected") != null) { if (savedInstanceState != null
&& savedInstanceState.getStringArrayList("mContactsSelected") != null) {
mContactsSelectedLayout.removeAllViews(); mContactsSelectedLayout.removeAllViews();
// We need to get all contacts not only sip // We need to get all contacts not only sip
for (String uri : savedInstanceState.getStringArrayList("mContactsSelected")) { for (String uri : savedInstanceState.getStringArrayList("mContactsSelected")) {
@ -197,7 +214,8 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
updateListSelected(); updateListSelected();
} }
mOnlyDisplayLinphoneContacts = ContactsManager.getInstance().getSIPContacts().size() > 0 ? true : false; mOnlyDisplayLinphoneContacts =
ContactsManager.getInstance().getSIPContacts().size() > 0 ? true : false;
if (savedInstanceState != null) { if (savedInstanceState != null) {
mOnlyDisplayLinphoneContacts = savedInstanceState.getBoolean("onlySipContact", true); mOnlyDisplayLinphoneContacts = savedInstanceState.getBoolean("onlySipContact", true);
} }
@ -206,34 +224,37 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
displayChatCreation(); displayChatCreation();
mChatRoomCreationListener = new ChatRoomListenerStub() { mChatRoomCreationListener =
@Override new ChatRoomListenerStub() {
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { @Override
if (newState == ChatRoom.State.Created) { public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
mWaitLayout.setVisibility(View.GONE); if (newState == ChatRoom.State.Created) {
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos); mWaitLayout.setVisibility(View.GONE);
} else if (newState == ChatRoom.State.CreationFailed) { LinphoneActivity.instance()
mWaitLayout.setVisibility(View.GONE); .goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos);
LinphoneActivity.instance().displayChatRoomError(); } else if (newState == ChatRoom.State.CreationFailed) {
Log.e("Group chat room for address " + cr.getPeerAddress() + " has failed !"); mWaitLayout.setVisibility(View.GONE);
} LinphoneActivity.instance().displayChatRoomError();
} Log.e(
}; "Group chat room for address "
+ cr.getPeerAddress()
+ " has failed !");
}
}
};
if (getArguments() != null) { if (getArguments() != null) {
String fileSharedUri = getArguments().getString("fileSharedUri"); String fileSharedUri = getArguments().getString("fileSharedUri");
String messageDraft = getArguments().getString("messageDraft"); String messageDraft = getArguments().getString("messageDraft");
if (fileSharedUri != null || messageDraft != null) if (fileSharedUri != null || messageDraft != null) mShareInfos = new Bundle();
mShareInfos = new Bundle();
if (fileSharedUri != null) { if (fileSharedUri != null) {
LinphoneActivity.instance().checkAndRequestPermissionsToSendImage(); LinphoneActivity.instance().checkAndRequestPermissionsToSendImage();
mShareInfos.putString("fileSharedUri", fileSharedUri); mShareInfos.putString("fileSharedUri", fileSharedUri);
} }
if (messageDraft != null) if (messageDraft != null) mShareInfos.putString("messageDraft", messageDraft);
mShareInfos.putString("messageDraft", messageDraft);
} }
return view; return view;
@ -248,9 +269,11 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CREATE_CHAT); LinphoneActivity.instance().selectMenu(FragmentsAvailable.CREATE_CHAT);
} }
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE); InputMethodManager inputMethodManager =
(InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE);
if (getActivity().getCurrentFocus() != null) { if (getActivity().getCurrentFocus() != null) {
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); inputMethodManager.hideSoftInputFromWindow(
getActivity().getCurrentFocus().getWindowToken(), 0);
} }
} }
@ -337,11 +360,12 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
private int getIndexOfCa(ContactAddress ca, List<ContactAddress> caList) { private int getIndexOfCa(ContactAddress ca, List<ContactAddress> caList) {
for (int i = 0; i < caList.size(); i++) { for (int i = 0; i < caList.size(); i++) {
if (ca.getAddress() != null && ca.getAddress().getUsername() != null) { if (ca.getAddress() != null && ca.getAddress().getUsername() != null) {
if (caList.get(i).getAddressAsDisplayableString().compareTo(ca.getAddressAsDisplayableString()) == 0) if (caList.get(i)
return i; .getAddressAsDisplayableString()
.compareTo(ca.getAddressAsDisplayableString())
== 0) return i;
} else if (ca.getPhoneNumber() != null && caList.get(i).getPhoneNumber() != null) { } else if (ca.getPhoneNumber() != null && caList.get(i).getPhoneNumber() != null) {
if (ca.getPhoneNumber().compareTo(caList.get(i).getPhoneNumber()) == 0) if (ca.getPhoneNumber().compareTo(caList.get(i).getPhoneNumber()) == 0) return i;
return i;
} }
} }
return -1; return -1;
@ -353,15 +377,21 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
} }
private void addSelectedContactAddress(ContactAddress ca) { private void addSelectedContactAddress(ContactAddress ca) {
View viewContact = LayoutInflater.from(LinphoneActivity.instance()).inflate(R.layout.contact_selected, null); View viewContact =
LayoutInflater.from(LinphoneActivity.instance())
.inflate(R.layout.contact_selected, null);
if (ca.getContact() != null) { if (ca.getContact() != null) {
String name = (ca.getContact().getFullName() != null && !ca.getContact().getFullName().isEmpty()) ? String name =
ca.getContact().getFullName() : (ca.getDisplayName() != null) ? (ca.getContact().getFullName() != null
ca.getDisplayName() : (ca.getUsername() != null) ? && !ca.getContact().getFullName().isEmpty())
ca.getUsername() : ""; ? ca.getContact().getFullName()
: (ca.getDisplayName() != null)
? ca.getDisplayName()
: (ca.getUsername() != null) ? ca.getUsername() : "";
((TextView) viewContact.findViewById(R.id.sipUri)).setText(name); ((TextView) viewContact.findViewById(R.id.sipUri)).setText(name);
} else { } else {
((TextView) viewContact.findViewById(R.id.sipUri)).setText(ca.getAddressAsDisplayableString()); ((TextView) viewContact.findViewById(R.id.sipUri))
.setText(ca.getAddressAsDisplayableString());
} }
View removeContact = viewContact.findViewById(R.id.contactChatDelete); View removeContact = viewContact.findViewById(R.id.contactChatDelete);
removeContact.setTag(ca); removeContact.setTag(ca);
@ -390,7 +420,6 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
} }
mSearchAdapter.setContactsSelectedList(mContactsSelected); mSearchAdapter.setContactsSelectedList(mContactsSelected);
mContactsSelectedLayout.invalidate(); mContactsSelectedLayout.invalidate();
} }
private void addOrRemoveContactFromSelection(ContactAddress ca) { private void addOrRemoveContactFromSelection(ContactAddress ca) {
@ -443,9 +472,25 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
} else if (id == R.id.next) { } else if (id == R.id.next) {
if (mChatRoomAddress == null && mChatRoomSubject == null) { if (mChatRoomAddress == null && mChatRoomSubject == null) {
mContactsSelectedLayout.removeAllViews(); mContactsSelectedLayout.removeAllViews();
LinphoneActivity.instance().goToChatGroupInfos(null, mContactsSelected, null, true, false, mShareInfos, mSecurityToggle.isChecked()); LinphoneActivity.instance()
.goToChatGroupInfos(
null,
mContactsSelected,
null,
true,
false,
mShareInfos,
mSecurityToggle.isChecked());
} else { } else {
LinphoneActivity.instance().goToChatGroupInfos(mChatRoomAddress, mContactsSelected, mChatRoomSubject, true, true, mShareInfos, mSecurityToggle.isChecked()); LinphoneActivity.instance()
.goToChatGroupInfos(
mChatRoomAddress,
mContactsSelected,
mChatRoomSubject,
true,
true,
mShareInfos,
mSecurityToggle.isChecked());
} }
} else if (id == R.id.clearSearchField) { } else if (id == R.id.clearSearchField) {
mSearchField.setQuery("", false); mSearchField.setQuery("", false);
@ -464,32 +509,47 @@ public class ChatRoomCreationFragment extends Fragment implements View.OnClickLi
boolean createEncryptedChatRoom = mSecurityToggle.isChecked(); boolean createEncryptedChatRoom = mSecurityToggle.isChecked();
if (lpc == null || lpc.getConferenceFactoryUri() == null || mCreateGroupChatRoom == false) { if (lpc == null || lpc.getConferenceFactoryUri() == null || mCreateGroupChatRoom == false) {
if (createEncryptedChatRoom && lpc != null && lpc.getConferenceFactoryUri() != null) { if (createEncryptedChatRoom && lpc != null && lpc.getConferenceFactoryUri() != null) {
mChatRoom = lc.findOneToOneChatRoom(lpc.getIdentityAddress(), ca.getAddress(), true); mChatRoom =
lc.findOneToOneChatRoom(lpc.getIdentityAddress(), ca.getAddress(), true);
if (mChatRoom != null) { if (mChatRoom != null) {
LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos); LinphoneActivity.instance()
.goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos);
} else { } else {
mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), !createEncryptedChatRoom, createEncryptedChatRoom); mChatRoom =
lc.createClientGroupChatRoom(
getString(R.string.dummy_group_chat_subject),
!createEncryptedChatRoom,
createEncryptedChatRoom);
mChatRoom.addListener(mChatRoomCreationListener); mChatRoom.addListener(mChatRoomCreationListener);
Address participants[] = new Address[1]; Address participants[] = new Address[1];
participants[0] = ca.getAddress(); participants[0] = ca.getAddress();
mChatRoom.addParticipants(participants); mChatRoom.addParticipants(participants);
} }
} else { } else {
if (lpc != null && lpc.getConferenceFactoryUri() != null && !LinphonePreferences.instance().useBasicChatRoomFor1To1()) { if (lpc != null
mChatRoom = lc.findOneToOneChatRoom(lpc.getIdentityAddress(), ca.getAddress(), false); && lpc.getConferenceFactoryUri() != null
&& !LinphonePreferences.instance().useBasicChatRoomFor1To1()) {
mChatRoom =
lc.findOneToOneChatRoom(
lpc.getIdentityAddress(), ca.getAddress(), false);
if (mChatRoom == null) { if (mChatRoom == null) {
mWaitLayout.setVisibility(View.VISIBLE); mWaitLayout.setVisibility(View.VISIBLE);
mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), true); mChatRoom =
lc.createClientGroupChatRoom(
getString(R.string.dummy_group_chat_subject), true);
mChatRoom.addListener(mChatRoomCreationListener); mChatRoom.addListener(mChatRoomCreationListener);
Address participants[] = new Address[1]; Address participants[] = new Address[1];
participants[0] = ca.getAddress(); participants[0] = ca.getAddress();
mChatRoom.addParticipants(participants); mChatRoom.addParticipants(participants);
} else { } else {
LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos); LinphoneActivity.instance()
.goToChat(
mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos);
} }
} else { } else {
ChatRoom chatRoom = lc.getChatRoom(ca.getAddress()); ChatRoom chatRoom = lc.getChatRoom(ca.getAddress());
LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos); LinphoneActivity.instance()
.goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos);
} }
} }
} else { } else {

View file

@ -20,16 +20,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.chat; package org.linphone.chat;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
@ -39,9 +34,11 @@ import org.linphone.core.ChatRoom;
import org.linphone.core.ChatRoomCapabilities; import org.linphone.core.ChatRoomCapabilities;
import org.linphone.core.Content; import org.linphone.core.Content;
import org.linphone.core.Participant; import org.linphone.core.Participant;
import org.linphone.utils.LinphoneUtils;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { public class ChatRoomViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
public TextView lastMessageView; public TextView lastMessageView;
public TextView date; public TextView date;
public TextView displayName; public TextView displayName;
@ -82,7 +79,11 @@ public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.
} }
} }
lastMessageView.setText(getSender(mRoom) + messageContent); lastMessageView.setText(getSender(mRoom) + messageContent);
date.setText(LinphoneUtils.timestampToHumanDate(mContext, mRoom.getLastUpdateTime(), R.string.messages_list_date_format)); date.setText(
LinphoneUtils.timestampToHumanDate(
mContext,
mRoom.getLastUpdateTime(),
R.string.messages_list_date_format));
} else { } else {
date.setText(""); date.setText("");
lastMessageView.setText(""); lastMessageView.setText("");
@ -108,18 +109,24 @@ public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.
public String getSender(ChatRoom mRoom) { public String getSender(ChatRoom mRoom) {
if (mRoom.getLastMessageInHistory() != null) { if (mRoom.getLastMessageInHistory() != null) {
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(mRoom.getLastMessageInHistory().getFromAddress()); LinphoneContact contact =
ContactsManager.getInstance()
.findContactFromAddress(
mRoom.getLastMessageInHistory().getFromAddress());
if (contact != null) { if (contact != null) {
return (contact.getFullName() + mContext.getString(R.string.separator)); return (contact.getFullName() + mContext.getString(R.string.separator));
} }
return (LinphoneUtils.getAddressDisplayName(mRoom.getLastMessageInHistory().getFromAddress()) + mContext.getString(R.string.separator)); return (LinphoneUtils.getAddressDisplayName(
mRoom.getLastMessageInHistory().getFromAddress())
+ mContext.getString(R.string.separator));
} }
return null; return null;
} }
public String getContact(ChatRoom mRoom) { public String getContact(ChatRoom mRoom) {
Address contactAddress = mRoom.getPeerAddress(); Address contactAddress = mRoom.getPeerAddress();
if (mRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt()) && mRoom.getParticipants().length > 0) { if (mRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())
&& mRoom.getParticipants().length > 0) {
contactAddress = mRoom.getParticipants()[0].getAddress(); contactAddress = mRoom.getParticipants()[0].getAddress();
} }
@ -138,11 +145,15 @@ public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.
if (mRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) { if (mRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) {
LinphoneContact contact = null; LinphoneContact contact = null;
if (mRoom.hasCapability(ChatRoomCapabilities.Basic.toInt())) { if (mRoom.hasCapability(ChatRoomCapabilities.Basic.toInt())) {
contact = ContactsManager.getInstance().findContactFromAddress(mRoom.getPeerAddress()); contact =
ContactsManager.getInstance()
.findContactFromAddress(mRoom.getPeerAddress());
} else { } else {
Participant[] participants = mRoom.getParticipants(); Participant[] participants = mRoom.getParticipants();
if (participants != null && participants.length > 0) { if (participants != null && participants.length > 0) {
contact = ContactsManager.getInstance().findContactFromAddress(participants[0].getAddress()); contact =
ContactsManager.getInstance()
.findContactFromAddress(participants[0].getAddress());
} }
} }
if (contact != null) { if (contact != null) {
@ -156,9 +167,9 @@ public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.
if (mRoom.hasCapability(ChatRoomCapabilities.Encrypted.toInt())) { if (mRoom.hasCapability(ChatRoomCapabilities.Encrypted.toInt())) {
Participant[] participants = mRoom.getParticipants(); Participant[] participants = mRoom.getParticipants();
if (participants.length > 0) { if (participants.length > 0) {
remoteAddr = participants[0].getAddress(); remoteAddr = participants[0].getAddress();
} else { } else {
//TODO: error // TODO: error
} }
} else { } else {
remoteAddr = mRoom.getPeerAddress(); remoteAddr = mRoom.getPeerAddress();
@ -185,4 +196,4 @@ public class ChatRoomViewHolder extends RecyclerView.ViewHolder implements View.
boolean onItemLongClicked(int position); boolean onItemLongClicked(int position);
} }
} }

View file

@ -23,17 +23,15 @@ import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.linphone.LinphoneManager;
import org.linphone.core.ChatRoom;
import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import org.linphone.LinphoneManager;
import org.linphone.core.ChatRoom;
import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper;
public class ChatRoomsAdapter extends SelectableAdapter<ChatRoomViewHolder> { public class ChatRoomsAdapter extends SelectableAdapter<ChatRoomViewHolder> {
private Context mContext; private Context mContext;
@ -41,7 +39,12 @@ public class ChatRoomsAdapter extends SelectableAdapter<ChatRoomViewHolder> {
private int mItemResource; private int mItemResource;
private ChatRoomViewHolder.ClickListener mClickListener; private ChatRoomViewHolder.ClickListener mClickListener;
public ChatRoomsAdapter(Context context, int itemResource, List<ChatRoom> rooms, ChatRoomViewHolder.ClickListener clickListener, SelectableHelper helper) { public ChatRoomsAdapter(
Context context,
int itemResource,
List<ChatRoom> rooms,
ChatRoomViewHolder.ClickListener clickListener,
SelectableHelper helper) {
super(helper); super(helper);
mClickListener = clickListener; mClickListener = clickListener;
mRooms = rooms; mRooms = rooms;
@ -51,8 +54,7 @@ public class ChatRoomsAdapter extends SelectableAdapter<ChatRoomViewHolder> {
@Override @Override
public ChatRoomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ChatRoomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext()).inflate(mItemResource, parent, false);
.inflate(mItemResource, parent, false);
return new ChatRoomViewHolder(mContext, view, mClickListener); return new ChatRoomViewHolder(mContext, view, mClickListener);
} }
@ -60,21 +62,26 @@ public class ChatRoomsAdapter extends SelectableAdapter<ChatRoomViewHolder> {
public void onBindViewHolder(ChatRoomViewHolder holder, int position) { public void onBindViewHolder(ChatRoomViewHolder holder, int position) {
ChatRoom room = mRooms.get(position); ChatRoom room = mRooms.get(position);
holder.delete.setVisibility(isEditionEnabled() ? View.VISIBLE : View.INVISIBLE); holder.delete.setVisibility(isEditionEnabled() ? View.VISIBLE : View.INVISIBLE);
holder.unreadMessages.setVisibility(isEditionEnabled() ? View.INVISIBLE : (room.getUnreadMessagesCount() > 0 ? View.VISIBLE : View.INVISIBLE)); holder.unreadMessages.setVisibility(
isEditionEnabled()
? View.INVISIBLE
: (room.getUnreadMessagesCount() > 0 ? View.VISIBLE : View.INVISIBLE));
holder.delete.setChecked(isSelected(position)); holder.delete.setChecked(isSelected(position));
holder.bindChatRoom(room); holder.bindChatRoom(room);
} }
public void refresh() { public void refresh() {
mRooms = new ArrayList<>(Arrays.asList(LinphoneManager.getLc().getChatRooms())); mRooms = new ArrayList<>(Arrays.asList(LinphoneManager.getLc().getChatRooms()));
Collections.sort(mRooms, new Comparator<ChatRoom>() { Collections.sort(
public int compare(ChatRoom cr1, ChatRoom cr2) { mRooms,
long timeDiff = cr1.getLastUpdateTime() - cr2.getLastUpdateTime(); new Comparator<ChatRoom>() {
if (timeDiff > 0) return -1; public int compare(ChatRoom cr1, ChatRoom cr2) {
else if (timeDiff == 0) return 0; long timeDiff = cr1.getLastUpdateTime() - cr2.getLastUpdateTime();
return 1; if (timeDiff > 0) return -1;
} else if (timeDiff == 0) return 0;
}); return 1;
}
});
notifyDataSetChanged(); notifyDataSetChanged();
} }
@ -83,10 +90,7 @@ public class ChatRoomsAdapter extends SelectableAdapter<ChatRoomViewHolder> {
notifyDataSetChanged(); notifyDataSetChanged();
} }
/** /** Adapter's methods */
* Adapter's methods
*/
@Override @Override
public int getItemCount() { public int getItemCount() {
return mRooms.size(); return mRooms.size();

View file

@ -19,22 +19,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.chat; package org.linphone.chat;
import static org.linphone.fragments.FragmentsAvailable.CHAT_LIST;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.ContactsUpdatedListener; import org.linphone.contacts.ContactsUpdatedListener;
import org.linphone.core.ChatMessage; import org.linphone.core.ChatMessage;
@ -47,14 +52,10 @@ import org.linphone.core.ProxyConfig;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.SelectableHelper; import org.linphone.utils.SelectableHelper;
import java.io.File; public class ChatRoomsFragment extends Fragment
import java.util.ArrayList; implements ContactsUpdatedListener,
import java.util.Arrays; ChatRoomViewHolder.ClickListener,
import java.util.List; SelectableHelper.DeleteListener {
import static org.linphone.fragments.FragmentsAvailable.CHAT_LIST;
public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListener, ChatRoomViewHolder.ClickListener, SelectableHelper.DeleteListener {
private RecyclerView mChatRoomsList; private RecyclerView mChatRoomsList;
private ImageView mNewDiscussionButton, mNewGroupDiscussionButton, mBackToCallButton; private ImageView mNewDiscussionButton, mNewGroupDiscussionButton, mBackToCallButton;
@ -69,7 +70,8 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
private TextView mNoChatHistory; private TextView mNoChatHistory;
@Override @Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mRooms = new ArrayList<>(Arrays.asList(LinphoneManager.getLc().getChatRooms())); mRooms = new ArrayList<>(Arrays.asList(LinphoneManager.getLc().getChatRooms()));
@ -85,7 +87,9 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
mNoChatHistory = view.findViewById(R.id.noChatHistory); mNoChatHistory = view.findViewById(R.id.noChatHistory);
mSelectionHelper = new SelectableHelper(view, this); mSelectionHelper = new SelectableHelper(view, this);
mChatRoomsAdapter = new ChatRoomsAdapter(mContext, R.layout.chatlist_cell, mRooms, this, mSelectionHelper); mChatRoomsAdapter =
new ChatRoomsAdapter(
mContext, R.layout.chatlist_cell, mRooms, this, mSelectionHelper);
mChatRoomsList.setAdapter(mChatRoomsAdapter); mChatRoomsList.setAdapter(mChatRoomsAdapter);
mSelectionHelper.setAdapter(mChatRoomsAdapter); mSelectionHelper.setAdapter(mChatRoomsAdapter);
@ -94,66 +98,81 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
mChatRoomsList.setLayoutManager(layoutManager); mChatRoomsList.setLayoutManager(layoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mChatRoomsList.getContext(), DividerItemDecoration dividerItemDecoration =
((LinearLayoutManager) layoutManager).getOrientation()); new DividerItemDecoration(
dividerItemDecoration.setDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.divider)); mChatRoomsList.getContext(),
((LinearLayoutManager) layoutManager).getOrientation());
dividerItemDecoration.setDrawable(
getActivity()
.getApplicationContext()
.getResources()
.getDrawable(R.drawable.divider));
mChatRoomsList.addItemDecoration(dividerItemDecoration); mChatRoomsList.addItemDecoration(dividerItemDecoration);
mWaitLayout.setVisibility(View.GONE); mWaitLayout.setVisibility(View.GONE);
mNewDiscussionButton.setOnClickListener(new View.OnClickListener() { mNewDiscussionButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
LinphoneActivity.instance().goToChatCreator(null, null, null, false, null, false, false); public void onClick(View v) {
} LinphoneActivity.instance()
}); .goToChatCreator(null, null, null, false, null, false, false);
mNewGroupDiscussionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinphoneActivity.instance().goToChatCreator(null, null, null, false, null, true, false);
}
});
mBackToCallButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LinphoneActivity.instance().resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
}
});
mListener = new CoreListenerStub() {
@Override
public void onMessageReceived(Core lc, ChatRoom cr, ChatMessage message) {
refreshChatRoomsList();
}
@Override
public void onChatRoomStateChanged(Core lc, ChatRoom cr, ChatRoom.State state) {
if (state == ChatRoom.State.Created) {
refreshChatRoomsList();
}
}
};
mChatRoomListener = new ChatRoomListenerStub() {
@Override
public void onStateChanged(ChatRoom room, ChatRoom.State state) {
super.onStateChanged(room, state);
if (state == ChatRoom.State.Deleted || state == ChatRoom.State.TerminationFailed) {
mChatRoomDeletionPendingCount -= 1;
if (state == ChatRoom.State.TerminationFailed) {
//TODO error message
} }
});
if (mChatRoomDeletionPendingCount == 0) { mNewGroupDiscussionButton.setOnClickListener(
mWaitLayout.setVisibility(View.GONE); new View.OnClickListener() {
@Override
public void onClick(View v) {
LinphoneActivity.instance()
.goToChatCreator(null, null, null, false, null, true, false);
}
});
mBackToCallButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
LinphoneActivity.instance()
.resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
}
});
mListener =
new CoreListenerStub() {
@Override
public void onMessageReceived(Core lc, ChatRoom cr, ChatMessage message) {
refreshChatRoomsList(); refreshChatRoomsList();
} }
}
} @Override
}; public void onChatRoomStateChanged(Core lc, ChatRoom cr, ChatRoom.State state) {
if (state == ChatRoom.State.Created) {
refreshChatRoomsList();
}
}
};
mChatRoomListener =
new ChatRoomListenerStub() {
@Override
public void onStateChanged(ChatRoom room, ChatRoom.State state) {
super.onStateChanged(room, state);
if (state == ChatRoom.State.Deleted
|| state == ChatRoom.State.TerminationFailed) {
mChatRoomDeletionPendingCount -= 1;
if (state == ChatRoom.State.TerminationFailed) {
// TODO error message
}
if (mChatRoomDeletionPendingCount == 0) {
mWaitLayout.setVisibility(View.GONE);
refreshChatRoomsList();
}
}
}
};
return view; return view;
} }
@ -178,7 +197,8 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
private void refreshChatRoomsList() { private void refreshChatRoomsList() {
mChatRoomsAdapter.refresh(); mChatRoomsAdapter.refresh();
mNoChatHistory.setVisibility(mChatRoomsAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE); mNoChatHistory.setVisibility(
mChatRoomsAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
} }
public void displayFirstChat() { public void displayFirstChat() {
@ -220,7 +240,8 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
refreshChatRoomsList(); refreshChatRoomsList();
ProxyConfig lpc = lc.getDefaultProxyConfig(); ProxyConfig lpc = lc.getDefaultProxyConfig();
mNewGroupDiscussionButton.setVisibility((lpc != null && lpc.getConferenceFactoryUri() != null) ? View.VISIBLE : View.GONE); mNewGroupDiscussionButton.setVisibility(
(lpc != null && lpc.getConferenceFactoryUri() != null) ? View.VISIBLE : View.GONE);
} }
@Override @Override
@ -247,7 +268,8 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
if (message.getAppdata() != null && !message.isOutgoing()) { if (message.getAppdata() != null && !message.isOutgoing()) {
File file = new File(message.getAppdata()); File file = new File(message.getAppdata());
if (file.exists()) { if (file.exists()) {
file.delete(); // Delete downloaded file from incoming message that will be deleted file.delete(); // Delete downloaded file from incoming message that
// will be deleted
} }
} }
} }
@ -259,17 +281,18 @@ public class ChatRoomsFragment extends Fragment implements ContactsUpdatedListen
if (mChatRoomDeletionPendingCount > 0) { if (mChatRoomDeletionPendingCount > 0) {
mWaitLayout.setVisibility(View.VISIBLE); mWaitLayout.setVisibility(View.VISIBLE);
} }
LinphoneActivity.instance().displayMissedChats(LinphoneManager.getInstance().getUnreadMessageCount()); LinphoneActivity.instance()
.displayMissedChats(LinphoneManager.getInstance().getUnreadMessageCount());
} }
@Override @Override
public void onContactsUpdated() { public void onContactsUpdated() {
if (!LinphoneActivity.isInstanciated() || LinphoneActivity.instance().getCurrentFragment() != CHAT_LIST) if (!LinphoneActivity.isInstanciated()
return; || LinphoneActivity.instance().getCurrentFragment() != CHAT_LIST) return;
ChatRoomsAdapter adapter = (ChatRoomsAdapter) mChatRoomsList.getAdapter(); ChatRoomsAdapter adapter = (ChatRoomsAdapter) mChatRoomsList.getAdapter();
if (adapter != null) { if (adapter != null) {
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} }
} }
} }

View file

@ -46,8 +46,7 @@ public abstract class ChatScrollListener extends RecyclerView.OnScrollListener {
for (int i = 0; i < lastVisibleItemPositions.length; i++) { for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) { if (i == 0) {
maxSize = lastVisibleItemPositions[i]; maxSize = lastVisibleItemPositions[i];
} } else if (lastVisibleItemPositions[i] > maxSize) {
else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i]; maxSize = lastVisibleItemPositions[i];
} }
} }

View file

@ -22,7 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.R; import org.linphone.R;
public class DeviceChildViewHolder { public class DeviceChildViewHolder {

View file

@ -23,7 +23,6 @@ import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.R; import org.linphone.R;
public class DeviceGroupViewHolder { public class DeviceGroupViewHolder {

View file

@ -24,8 +24,8 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter; import android.widget.BaseExpandableListAdapter;
import java.util.ArrayList;
import org.linphone.utils.LinphoneUtils; import java.util.List;
import org.linphone.R; import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
@ -33,11 +33,9 @@ import org.linphone.core.Address;
import org.linphone.core.ChatRoomSecurityLevel; import org.linphone.core.ChatRoomSecurityLevel;
import org.linphone.core.Participant; import org.linphone.core.Participant;
import org.linphone.core.ParticipantDevice; import org.linphone.core.ParticipantDevice;
import org.linphone.utils.LinphoneUtils;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
import java.util.ArrayList;
import java.util.List;
public class DevicesAdapter extends BaseExpandableListAdapter { public class DevicesAdapter extends BaseExpandableListAdapter {
private Context mContext; private Context mContext;
private List<Participant> mParticipants; private List<Participant> mParticipants;
@ -56,7 +54,8 @@ public class DevicesAdapter extends BaseExpandableListAdapter {
} }
@Override @Override
public View getGroupView(int groupPosition, boolean isExpanded, View view, ViewGroup viewGroup) { public View getGroupView(
int groupPosition, boolean isExpanded, View view, ViewGroup viewGroup) {
if (mOnlyDisplayChildsAsGroups) { if (mOnlyDisplayChildsAsGroups) {
ParticipantDevice device = (ParticipantDevice) getGroup(groupPosition); ParticipantDevice device = (ParticipantDevice) getGroup(groupPosition);
@ -76,7 +75,7 @@ public class DevicesAdapter extends BaseExpandableListAdapter {
} }
Address deviceAddress = device.getAddress(); Address deviceAddress = device.getAddress();
holder.deviceName.setText(deviceAddress.getUriParam("gr")); //TODO holder.deviceName.setText(deviceAddress.getUriParam("gr")); // TODO
ChatRoomSecurityLevel level = device.getSecurityLevel(); ChatRoomSecurityLevel level = device.getSecurityLevel();
switch (level) { switch (level) {
@ -111,24 +110,29 @@ public class DevicesAdapter extends BaseExpandableListAdapter {
} }
Address participantAddress = participant.getAddress(); Address participantAddress = participant.getAddress();
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(participantAddress); LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(participantAddress);
if (contact != null) { if (contact != null) {
ContactAvatar.displayAvatar(contact, participant.getSecurityLevel(), holder.avatarLayout); ContactAvatar.displayAvatar(
contact, participant.getSecurityLevel(), holder.avatarLayout);
holder.participantName.setText(contact.getFullName()); holder.participantName.setText(contact.getFullName());
} else { } else {
String displayName = LinphoneUtils.getAddressDisplayName(participantAddress); String displayName = LinphoneUtils.getAddressDisplayName(participantAddress);
ContactAvatar.displayAvatar(displayName, participant.getSecurityLevel(), holder.avatarLayout); ContactAvatar.displayAvatar(
displayName, participant.getSecurityLevel(), holder.avatarLayout);
holder.participantName.setText(displayName); holder.participantName.setText(displayName);
} }
holder.groupExpander.setImageResource(isExpanded ? R.drawable.chevron_list_open : R.drawable.chevron_list_close); holder.groupExpander.setImageResource(
isExpanded ? R.drawable.chevron_list_open : R.drawable.chevron_list_close);
} }
return view; return view;
} }
@Override @Override
public View getChildView(int groupPosition, int childPosition, boolean b, View view, ViewGroup viewGroup) { public View getChildView(
int groupPosition, int childPosition, boolean b, View view, ViewGroup viewGroup) {
ParticipantDevice device = (ParticipantDevice) getChild(groupPosition, childPosition); ParticipantDevice device = (ParticipantDevice) getChild(groupPosition, childPosition);
DeviceChildViewHolder holder = null; DeviceChildViewHolder holder = null;
@ -147,7 +151,7 @@ public class DevicesAdapter extends BaseExpandableListAdapter {
} }
Address deviceAddress = device.getAddress(); Address deviceAddress = device.getAddress();
holder.deviceName.setText(deviceAddress.getUriParam("gr")); //TODO holder.deviceName.setText(deviceAddress.getUriParam("gr")); // TODO
ChatRoomSecurityLevel level = device.getSecurityLevel(); ChatRoomSecurityLevel level = device.getSecurityLevel();
switch (level) { switch (level) {
@ -170,19 +174,25 @@ public class DevicesAdapter extends BaseExpandableListAdapter {
@Override @Override
public int getGroupCount() { public int getGroupCount() {
if (mParticipants.size() == 0) return 0; if (mParticipants.size() == 0) return 0;
return mOnlyDisplayChildsAsGroups ? mParticipants.get(0).getDevices().length : mParticipants.size(); return mOnlyDisplayChildsAsGroups
? mParticipants.get(0).getDevices().length
: mParticipants.size();
} }
@Override @Override
public int getChildrenCount(int groupPosition) { public int getChildrenCount(int groupPosition) {
if (mParticipants.size() == 0) return 0; if (mParticipants.size() == 0) return 0;
return mOnlyDisplayChildsAsGroups ? 0 : mParticipants.get(groupPosition).getDevices().length; return mOnlyDisplayChildsAsGroups
? 0
: mParticipants.get(groupPosition).getDevices().length;
} }
@Override @Override
public Object getGroup(int groupPosition) { public Object getGroup(int groupPosition) {
if (mParticipants.size() == 0) return null; if (mParticipants.size() == 0) return null;
return mOnlyDisplayChildsAsGroups ? mParticipants.get(0).getDevices()[groupPosition] : mParticipants.get(groupPosition); return mOnlyDisplayChildsAsGroups
? mParticipants.get(0).getDevices()[groupPosition]
: mParticipants.get(groupPosition);
} }
@Override @Override

View file

@ -21,18 +21,17 @@ package org.linphone.chat;
import android.app.Fragment; import android.app.Fragment;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable;
import org.linphone.LinphoneManager; import java.util.Arrays;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
@ -41,8 +40,7 @@ import org.linphone.core.ChatRoomCapabilities;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.ParticipantDevice; import org.linphone.core.ParticipantDevice;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.LinphoneUtils;
import java.util.Arrays;
public class DevicesFragment extends Fragment { public class DevicesFragment extends Fragment {
private LayoutInflater mInflater; private LayoutInflater mInflater;
@ -58,7 +56,8 @@ public class DevicesFragment extends Fragment {
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getArguments() != null) { if (getArguments() != null) {
@ -72,26 +71,39 @@ public class DevicesFragment extends Fragment {
mOnlyDisplayChilds = false; mOnlyDisplayChilds = false;
mExpandableList = view.findViewById(R.id.devices_list); mExpandableList = view.findViewById(R.id.devices_list);
mExpandableList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { mExpandableList.setOnChildClickListener(
@Override new ExpandableListView.OnChildClickListener() {
public boolean onChildClick(ExpandableListView expandableListView, View view, int groupPosition, int childPosition, long l) { @Override
ParticipantDevice device = (ParticipantDevice) mAdapter.getChild(groupPosition, childPosition); public boolean onChildClick(
LinphoneManager.getLc().inviteAddress(device.getAddress()); ExpandableListView expandableListView,
return false; View view,
} int groupPosition,
}); int childPosition,
mExpandableList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { long l) {
@Override ParticipantDevice device =
public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long l) { (ParticipantDevice) mAdapter.getChild(groupPosition, childPosition);
if (mOnlyDisplayChilds) { LinphoneManager.getLc().inviteAddress(device.getAddress());
// in this case groups are childs, so call on click return false;
ParticipantDevice device = (ParticipantDevice) mAdapter.getGroup(groupPosition); }
LinphoneManager.getLc().inviteAddress(device.getAddress()); });
return true; mExpandableList.setOnGroupClickListener(
} new ExpandableListView.OnGroupClickListener() {
return false; @Override
} public boolean onGroupClick(
}); ExpandableListView expandableListView,
View view,
int groupPosition,
long l) {
if (mOnlyDisplayChilds) {
// in this case groups are childs, so call on click
ParticipantDevice device =
(ParticipantDevice) mAdapter.getGroup(groupPosition);
LinphoneManager.getLc().inviteAddress(device.getAddress());
return true;
}
return false;
}
});
initChatRoom(); initChatRoom();
@ -99,16 +111,17 @@ public class DevicesFragment extends Fragment {
initHeader(); initHeader();
mBackButton = view.findViewById(R.id.back); mBackButton = view.findViewById(R.id.back);
mBackButton.setOnClickListener(new View.OnClickListener() { mBackButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (LinphoneActivity.instance().isTablet()) { public void onClick(View view) {
LinphoneActivity.instance().goToChat(mRoomUri, null); if (LinphoneActivity.instance().isTablet()) {
} else { LinphoneActivity.instance().goToChat(mRoomUri, null);
LinphoneActivity.instance().onBackPressed(); } else {
} LinphoneActivity.instance().onBackPressed();
} }
}); }
});
return view; return view;
} }
@ -135,7 +148,8 @@ public class DevicesFragment extends Fragment {
if (mRoom.getParticipants().length > 0) { if (mRoom.getParticipants().length > 0) {
remoteParticipantAddr = mRoom.getParticipants()[0].getAddress(); remoteParticipantAddr = mRoom.getParticipants()[0].getAddress();
} }
LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(remoteParticipantAddr); LinphoneContact c =
ContactsManager.getInstance().findContactFromAddress(remoteParticipantAddr);
String displayName; String displayName;
if (c != null) { if (c != null) {
displayName = c.getFullName(); displayName = c.getFullName();

View file

@ -19,8 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.chat; package org.linphone.chat;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -28,7 +26,10 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import org.linphone.R; import org.linphone.R;
import org.linphone.contacts.ContactAddress; import org.linphone.contacts.ContactAddress;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
@ -36,9 +37,6 @@ import org.linphone.core.ChatRoom;
import org.linphone.core.Participant; import org.linphone.core.Participant;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
import java.util.ArrayList;
import java.util.List;
public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.ViewHolder> { public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder { public static class ViewHolder extends RecyclerView.ViewHolder {
@ -63,7 +61,8 @@ public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.View
private boolean mHideAdminFeatures; private boolean mHideAdminFeatures;
private ChatRoom mChatRoom; private ChatRoom mChatRoom;
public GroupInfoAdapter(List<ContactAddress> items, boolean hideAdminFeatures, boolean isCreation) { public GroupInfoAdapter(
List<ContactAddress> items, boolean hideAdminFeatures, boolean isCreation) {
mItems = items; mItems = items;
mHideAdminFeatures = hideAdminFeatures || isCreation; mHideAdminFeatures = hideAdminFeatures || isCreation;
} }
@ -71,7 +70,9 @@ public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.View
@NonNull @NonNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_infos_cell, parent, false); View v =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_infos_cell, parent, false);
return new ViewHolder(v); return new ViewHolder(v);
} }
@ -80,8 +81,10 @@ public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.View
final ContactAddress ca = (ContactAddress) getItem(position); final ContactAddress ca = (ContactAddress) getItem(position);
LinphoneContact c = ca.getContact(); LinphoneContact c = ca.getContact();
holder.name.setText((c.getFullName() != null) ? c.getFullName() : holder.name.setText(
(ca.getDisplayName() != null) ? ca.getDisplayName() : ca.getUsername()); (c.getFullName() != null)
? c.getFullName()
: (ca.getDisplayName() != null) ? ca.getDisplayName() : ca.getUsername());
if (c != null) { if (c != null) {
ContactAvatar.displayAvatar(c, holder.avatarLayout); ContactAvatar.displayAvatar(c, holder.avatarLayout);
@ -89,42 +92,47 @@ public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.View
ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout); ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout);
} }
holder.delete.setOnClickListener(new View.OnClickListener() { holder.delete.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (mDeleteListener != null) { public void onClick(View view) {
mDeleteListener.onClick(view); if (mDeleteListener != null) {
} mDeleteListener.onClick(view);
} }
}); }
});
holder.delete.setTag(ca); holder.delete.setTag(ca);
holder.isAdmin.setVisibility(ca.isAdmin() ? View.VISIBLE : View.GONE); holder.isAdmin.setVisibility(ca.isAdmin() ? View.VISIBLE : View.GONE);
holder.isNotAdmin.setVisibility(ca.isAdmin() ? View.GONE : View.VISIBLE); holder.isNotAdmin.setVisibility(ca.isAdmin() ? View.GONE : View.VISIBLE);
holder.isAdmin.setOnClickListener(new View.OnClickListener() { holder.isAdmin.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
holder.isNotAdmin.setVisibility(View.VISIBLE); public void onClick(View view) {
holder.isAdmin.setVisibility(View.GONE); holder.isNotAdmin.setVisibility(View.VISIBLE);
ca.setAdmin(false); holder.isAdmin.setVisibility(View.GONE);
} ca.setAdmin(false);
}); }
});
holder.isNotAdmin.setOnClickListener(new View.OnClickListener() { holder.isNotAdmin.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
holder.isNotAdmin.setVisibility(View.GONE); public void onClick(View view) {
holder.isAdmin.setVisibility(View.VISIBLE); holder.isNotAdmin.setVisibility(View.GONE);
ca.setAdmin(true); holder.isAdmin.setVisibility(View.VISIBLE);
} ca.setAdmin(true);
}); }
});
holder.delete.setVisibility(View.VISIBLE); holder.delete.setVisibility(View.VISIBLE);
if (mHideAdminFeatures) { if (mHideAdminFeatures) {
holder.delete.setVisibility(View.INVISIBLE); holder.delete.setVisibility(View.INVISIBLE);
holder.isAdmin.setOnClickListener(null); // Do not allow not admin to remove it's rights but display admins holder.isAdmin.setOnClickListener(
holder.isNotAdmin.setVisibility(View.GONE); // Hide not admin button for not admin participants null); // Do not allow not admin to remove it's rights but display admins
holder.isNotAdmin.setVisibility(
View.GONE); // Hide not admin button for not admin participants
} else if (mChatRoom != null) { } else if (mChatRoom != null) {
boolean found = false; boolean found = false;
for (Participant p : mChatRoom.getParticipants()) { for (Participant p : mChatRoom.getParticipants()) {
@ -134,7 +142,9 @@ public class GroupInfoAdapter extends RecyclerView.Adapter<GroupInfoAdapter.View
} }
} }
if (!found) { if (!found) {
holder.isNotAdmin.setVisibility(View.GONE); // Hide not admin button for participant not yet added so even if user click it it won't have any effect holder.isNotAdmin.setVisibility(
View.GONE); // Hide not admin button for participant not yet added so
// even if user click it it won't have any effect
} }
} }
} }

View file

@ -19,13 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.chat; package org.linphone.chat;
import static android.content.Context.INPUT_METHOD_SERVICE;
import android.app.Dialog; import android.app.Dialog;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -37,11 +36,13 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import androidx.recyclerview.widget.DividerItemDecoration;
import org.linphone.LinphoneManager; import androidx.recyclerview.widget.LinearLayoutManager;
import org.linphone.utils.LinphoneUtils; import androidx.recyclerview.widget.RecyclerView;
import org.linphone.R; import java.util.ArrayList;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.contacts.ContactAddress; import org.linphone.contacts.ContactAddress;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
@ -54,10 +55,7 @@ import org.linphone.core.EventLog;
import org.linphone.core.Participant; import org.linphone.core.Participant;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.utils.LinphoneUtils;
import java.util.ArrayList;
import static android.content.Context.INPUT_METHOD_SERVICE;
public class GroupInfoFragment extends Fragment implements ChatRoomListener { public class GroupInfoFragment extends Fragment implements ChatRoomListener {
private ImageView mBackButton, mConfirmButton, mAddParticipantsButton; private ImageView mBackButton, mConfirmButton, mAddParticipantsButton;
@ -84,7 +82,8 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
private boolean mIsEncryptionEnabled; private boolean mIsEncryptionEnabled;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mInflater = inflater; mInflater = inflater;
View view = inflater.inflate(R.layout.chat_infos, container, false); View view = inflater.inflate(R.layout.chat_infos, container, false);
@ -93,7 +92,8 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
} }
mContext = getActivity().getApplicationContext(); mContext = getActivity().getApplicationContext();
mParticipants = (ArrayList<ContactAddress>) getArguments().getSerializable("ContactAddress"); mParticipants =
(ArrayList<ContactAddress>) getArguments().getSerializable("ContactAddress");
mGroupChatRoomAddress = null; mGroupChatRoomAddress = null;
mChatRoom = null; mChatRoom = null;
@ -119,213 +119,271 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
mParticipantsList = view.findViewById(R.id.chat_room_participants); mParticipantsList = view.findViewById(R.id.chat_room_participants);
mAdapter = new GroupInfoAdapter(mParticipants, !mIsEditionEnabled, !mIsAlreadyCreatedGroup); mAdapter = new GroupInfoAdapter(mParticipants, !mIsEditionEnabled, !mIsAlreadyCreatedGroup);
mAdapter.setOnDeleteClickListener(new View.OnClickListener() { mAdapter.setOnDeleteClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
ContactAddress ca = (ContactAddress) view.getTag(); public void onClick(View view) {
mParticipants.remove(ca); ContactAddress ca = (ContactAddress) view.getTag();
mAdapter.updateDataSet(mParticipants); mParticipants.remove(ca);
mParticipantsList.setAdapter(mAdapter); mAdapter.updateDataSet(mParticipants);
mConfirmButton.setEnabled(mSubjectField.getText().length() > 0 && mParticipants.size() > 0); mParticipantsList.setAdapter(mAdapter);
} mConfirmButton.setEnabled(
}); mSubjectField.getText().length() > 0 && mParticipants.size() > 0);
}
});
mParticipantsList.setAdapter(mAdapter); mParticipantsList.setAdapter(mAdapter);
mAdapter.setChatRoom(mChatRoom); mAdapter.setChatRoom(mChatRoom);
layoutManager = new LinearLayoutManager(mContext); layoutManager = new LinearLayoutManager(mContext);
mParticipantsList.setLayoutManager(layoutManager); mParticipantsList.setLayoutManager(layoutManager);
//Divider between items // Divider between items
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mParticipantsList.getContext(), DividerItemDecoration dividerItemDecoration =
layoutManager.getOrientation()); new DividerItemDecoration(
mParticipantsList.getContext(), layoutManager.getOrientation());
dividerItemDecoration.setDrawable(mContext.getResources().getDrawable(R.drawable.divider)); dividerItemDecoration.setDrawable(mContext.getResources().getDrawable(R.drawable.divider));
mParticipantsList.addItemDecoration(dividerItemDecoration); mParticipantsList.addItemDecoration(dividerItemDecoration);
String fileSharedUri = getArguments().getString("fileSharedUri"); String fileSharedUri = getArguments().getString("fileSharedUri");
String messageDraft = getArguments().getString("messageDraft"); String messageDraft = getArguments().getString("messageDraft");
if (fileSharedUri != null || messageDraft != null) if (fileSharedUri != null || messageDraft != null) mShareInfos = new Bundle();
mShareInfos = new Bundle();
if (fileSharedUri != null) if (fileSharedUri != null) mShareInfos.putString("fileSharedUri", fileSharedUri);
mShareInfos.putString("fileSharedUri", fileSharedUri);
if (messageDraft != null) if (messageDraft != null) mShareInfos.putString("messageDraft", messageDraft);
mShareInfos.putString("messageDraft", messageDraft);
mBackButton = view.findViewById(R.id.back); mBackButton = view.findViewById(R.id.back);
mBackButton.setOnClickListener(new View.OnClickListener() { mBackButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (mIsAlreadyCreatedGroup) { public void onClick(View view) {
if (LinphoneActivity.instance().isTablet()) { if (mIsAlreadyCreatedGroup) {
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asStringUriOnly(), mShareInfos); if (LinphoneActivity.instance().isTablet()) {
} else { LinphoneActivity.instance()
getFragmentManager().popBackStack(); .goToChat(
mGroupChatRoomAddress.asStringUriOnly(),
mShareInfos);
} else {
getFragmentManager().popBackStack();
}
} else {
LinphoneActivity.instance()
.goToChatCreator(
null,
mParticipants,
null,
true,
mShareInfos,
true,
mIsEncryptionEnabled);
}
} }
} else { });
LinphoneActivity.instance().goToChatCreator(null, mParticipants, null, true, mShareInfos, true, mIsEncryptionEnabled);
}
}
});
mConfirmButton = view.findViewById(R.id.confirm); mConfirmButton = view.findViewById(R.id.confirm);
mLeaveGroupButton = view.findViewById(R.id.leaveGroupLayout); mLeaveGroupButton = view.findViewById(R.id.leaveGroupLayout);
mLeaveGroupButton.setOnClickListener(new View.OnClickListener() { mLeaveGroupButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) {
final Dialog dialog = LinphoneActivity.instance().displayDialog(getString(R.string.chat_room_leave_dialog));
Button delete = dialog.findViewById(R.id.dialog_delete_button);
delete.setText(getString(R.string.chat_room_leave_button));
Button cancel = dialog.findViewById(R.id.dialog_cancel_button);
delete.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (mChatRoom != null) { final Dialog dialog =
mChatRoom.leave(); LinphoneActivity.instance()
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asString(), null); .displayDialog(getString(R.string.chat_room_leave_dialog));
} else { Button delete = dialog.findViewById(R.id.dialog_delete_button);
Log.e("Can't leave, chatRoom for address " + mGroupChatRoomAddress.asString() + " is null..."); delete.setText(getString(R.string.chat_room_leave_button));
} Button cancel = dialog.findViewById(R.id.dialog_cancel_button);
dialog.dismiss();
}
});
cancel.setOnClickListener(new View.OnClickListener() { delete.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
dialog.dismiss(); public void onClick(View view) {
if (mChatRoom != null) {
mChatRoom.leave();
LinphoneActivity.instance()
.goToChat(
mGroupChatRoomAddress.asString(), null);
} else {
Log.e(
"Can't leave, chatRoom for address "
+ mGroupChatRoomAddress.asString()
+ " is null...");
}
dialog.dismiss();
}
});
cancel.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.show();
} }
}); });
dialog.show(); mLeaveGroupButton.setVisibility(
} mIsAlreadyCreatedGroup && mChatRoom.hasBeenLeft()
}); ? View.GONE
mLeaveGroupButton.setVisibility(mIsAlreadyCreatedGroup && mChatRoom.hasBeenLeft() ? View.GONE : mIsAlreadyCreatedGroup ? View.VISIBLE : View.GONE); : mIsAlreadyCreatedGroup ? View.VISIBLE : View.GONE);
mAddParticipantsLayout = view.findViewById(R.id.addParticipantsLayout); mAddParticipantsLayout = view.findViewById(R.id.addParticipantsLayout);
mAddParticipantsLayout.setOnClickListener(new View.OnClickListener() { mAddParticipantsLayout.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (mIsEditionEnabled && mIsAlreadyCreatedGroup) { public void onClick(View view) {
LinphoneActivity.instance().goToChatCreator(mGroupChatRoomAddress != null ? mGroupChatRoomAddress.asString() : null, mParticipants, mSubject, !mIsAlreadyCreatedGroup, null, true, mIsEncryptionEnabled); if (mIsEditionEnabled && mIsAlreadyCreatedGroup) {
} LinphoneActivity.instance()
} .goToChatCreator(
}); mGroupChatRoomAddress != null
? mGroupChatRoomAddress.asString()
: null,
mParticipants,
mSubject,
!mIsAlreadyCreatedGroup,
null,
true,
mIsEncryptionEnabled);
}
}
});
mAddParticipantsButton = view.findViewById(R.id.addParticipants); mAddParticipantsButton = view.findViewById(R.id.addParticipants);
mAddParticipantsButton.setOnClickListener(new View.OnClickListener() { mAddParticipantsButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (mIsEditionEnabled && mIsAlreadyCreatedGroup) { public void onClick(View view) {
LinphoneActivity.instance().goToChatCreator(mGroupChatRoomAddress != null ? mGroupChatRoomAddress.asString() : null, mParticipants, mSubject, !mIsAlreadyCreatedGroup, null, true, mIsEncryptionEnabled); if (mIsEditionEnabled && mIsAlreadyCreatedGroup) {
} LinphoneActivity.instance()
} .goToChatCreator(
}); mGroupChatRoomAddress != null
? mGroupChatRoomAddress.asString()
: null,
mParticipants,
mSubject,
!mIsAlreadyCreatedGroup,
null,
true,
mIsEncryptionEnabled);
}
}
});
mAddParticipantsButton.setVisibility(mIsAlreadyCreatedGroup ? View.VISIBLE : View.GONE); mAddParticipantsButton.setVisibility(mIsAlreadyCreatedGroup ? View.VISIBLE : View.GONE);
mSubjectField = view.findViewById(R.id.subjectField); mSubjectField = view.findViewById(R.id.subjectField);
mSubjectField.addTextChangedListener(new TextWatcher() { mSubjectField.addTextChangedListener(
@Override new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { @Override
public void beforeTextChanged(
CharSequence charSequence, int i, int i1, int i2) {}
} @Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override @Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { public void afterTextChanged(Editable editable) {
mConfirmButton.setEnabled(
} mSubjectField.getText().length() > 0 && mParticipants.size() > 0);
}
@Override });
public void afterTextChanged(Editable editable) {
mConfirmButton.setEnabled(mSubjectField.getText().length() > 0 && mParticipants.size() > 0);
}
});
mSubjectField.setText(mSubject); mSubjectField.setText(mSubject);
mChatRoomCreationListener = new ChatRoomListenerStub() { mChatRoomCreationListener =
@Override new ChatRoomListenerStub() {
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { @Override
if (newState == ChatRoom.State.Created) { public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
mWaitLayout.setVisibility(View.GONE); if (newState == ChatRoom.State.Created) {
// This will remove both the creation fragment and the group info fragment from the back stack mWaitLayout.setVisibility(View.GONE);
getFragmentManager().popBackStack(); // This will remove both the creation fragment and the group info
getFragmentManager().popBackStack(); // fragment from the back stack
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos); getFragmentManager().popBackStack();
} else if (newState == ChatRoom.State.CreationFailed) { getFragmentManager().popBackStack();
mWaitLayout.setVisibility(View.GONE); LinphoneActivity.instance()
LinphoneActivity.instance().displayChatRoomError(); .goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos);
Log.e("Group chat room for address " + cr.getPeerAddress() + " has failed !"); } else if (newState == ChatRoom.State.CreationFailed) {
} mWaitLayout.setVisibility(View.GONE);
} LinphoneActivity.instance().displayChatRoomError();
}; Log.e(
"Group chat room for address "
mConfirmButton.setOnClickListener(new View.OnClickListener() { + cr.getPeerAddress()
@Override + " has failed !");
public void onClick(View view) { }
if (!mIsAlreadyCreatedGroup) {
mWaitLayout.setVisibility(View.VISIBLE);
mTempChatRoom = LinphoneManager.getLc().createClientGroupChatRoom(mSubjectField.getText().toString(), false, mIsEncryptionEnabled);
mTempChatRoom.addListener(mChatRoomCreationListener);
for (ContactAddress ca : mParticipants) {
mTempChatRoom.addParticipant(ca.getAddress());
}
} else {
// Subject
String newSubject = mSubjectField.getText().toString();
if (!newSubject.equals(mSubject)) {
mChatRoom.setSubject(newSubject);
} }
};
// Participants removed mConfirmButton.setOnClickListener(
ArrayList<Participant> toRemove = new ArrayList<>(); new View.OnClickListener() {
for (Participant p : mChatRoom.getParticipants()) { @Override
boolean found = false; public void onClick(View view) {
for (ContactAddress c : mParticipants) { if (!mIsAlreadyCreatedGroup) {
if (c.getAddress().weakEqual(p.getAddress())) { mWaitLayout.setVisibility(View.VISIBLE);
found = true; mTempChatRoom =
break; LinphoneManager.getLc()
.createClientGroupChatRoom(
mSubjectField.getText().toString(),
false,
mIsEncryptionEnabled);
mTempChatRoom.addListener(mChatRoomCreationListener);
for (ContactAddress ca : mParticipants) {
mTempChatRoom.addParticipant(ca.getAddress());
}
} else {
// Subject
String newSubject = mSubjectField.getText().toString();
if (!newSubject.equals(mSubject)) {
mChatRoom.setSubject(newSubject);
} }
}
if (!found) {
toRemove.add(p);
}
}
Participant[] participantsToRemove = new Participant[toRemove.size()];
toRemove.toArray(participantsToRemove);
mChatRoom.removeParticipants(participantsToRemove);
// Participants added // Participants removed
ArrayList<Address> toAdd = new ArrayList<>(); ArrayList<Participant> toRemove = new ArrayList<>();
for (ContactAddress c : mParticipants) { for (Participant p : mChatRoom.getParticipants()) {
boolean found = false; boolean found = false;
for (Participant p : mChatRoom.getParticipants()) { for (ContactAddress c : mParticipants) {
if (p.getAddress().weakEqual(c.getAddress())) { if (c.getAddress().weakEqual(p.getAddress())) {
// Admin rights found = true;
if (c.isAdmin() != p.isAdmin()) { break;
mChatRoom.setParticipantAdminStatus(p, c.isAdmin()); }
}
if (!found) {
toRemove.add(p);
} }
found = true;
break;
} }
} Participant[] participantsToRemove = new Participant[toRemove.size()];
if (!found) { toRemove.toArray(participantsToRemove);
Address addr = c.getAddress(); mChatRoom.removeParticipants(participantsToRemove);
if (addr != null) {
toAdd.add(addr); // Participants added
} else { ArrayList<Address> toAdd = new ArrayList<>();
//TODO error for (ContactAddress c : mParticipants) {
boolean found = false;
for (Participant p : mChatRoom.getParticipants()) {
if (p.getAddress().weakEqual(c.getAddress())) {
// Admin rights
if (c.isAdmin() != p.isAdmin()) {
mChatRoom.setParticipantAdminStatus(p, c.isAdmin());
}
found = true;
break;
}
}
if (!found) {
Address addr = c.getAddress();
if (addr != null) {
toAdd.add(addr);
} else {
// TODO error
}
}
} }
Address[] participantsToAdd = new Address[toAdd.size()];
toAdd.toArray(participantsToAdd);
mChatRoom.addParticipants(participantsToAdd);
LinphoneActivity.instance()
.goToChat(mGroupChatRoomAddress.asString(), null);
} }
} }
Address[] participantsToAdd = new Address[toAdd.size()]; });
toAdd.toArray(participantsToAdd);
mChatRoom.addParticipants(participantsToAdd);
LinphoneActivity.instance().goToChat(mGroupChatRoomAddress.asString(), null);
}
}
});
mConfirmButton.setEnabled(mSubjectField.getText().length() > 0 && mParticipants.size() > 0); mConfirmButton.setEnabled(mSubjectField.getText().length() > 0 && mParticipants.size() > 0);
if (!mIsEditionEnabled) { if (!mIsEditionEnabled) {
@ -352,9 +410,11 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.INFO_GROUP_CHAT); LinphoneActivity.instance().selectMenu(FragmentsAvailable.INFO_GROUP_CHAT);
} }
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE); InputMethodManager inputMethodManager =
(InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE);
if (getActivity().getCurrentFocus() != null) { if (getActivity().getCurrentFocus() != null) {
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); inputMethodManager.hideSoftInputFromWindow(
getActivity().getCurrentFocus().getWindowToken(), 0);
} }
} }
@ -404,16 +464,23 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
private void displayMeAdminStatusUpdated() { private void displayMeAdminStatusUpdated() {
if (mAdminStateChangedDialog != null) mAdminStateChangedDialog.dismiss(); if (mAdminStateChangedDialog != null) mAdminStateChangedDialog.dismiss();
mAdminStateChangedDialog = LinphoneActivity.instance().displayDialog(getString(mIsEditionEnabled ? R.string.chat_room_you_are_now_admin : R.string.chat_room_you_are_no_longer_admin)); mAdminStateChangedDialog =
LinphoneActivity.instance()
.displayDialog(
getString(
mIsEditionEnabled
? R.string.chat_room_you_are_now_admin
: R.string.chat_room_you_are_no_longer_admin));
Button cancel = mAdminStateChangedDialog.findViewById(R.id.dialog_cancel_button); Button cancel = mAdminStateChangedDialog.findViewById(R.id.dialog_cancel_button);
mAdminStateChangedDialog.findViewById(R.id.dialog_delete_button).setVisibility(View.GONE); mAdminStateChangedDialog.findViewById(R.id.dialog_delete_button).setVisibility(View.GONE);
cancel.setText(getString(R.string.ok)); cancel.setText(getString(R.string.ok));
cancel.setOnClickListener(new View.OnClickListener() { cancel.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
mAdminStateChangedDialog.dismiss(); public void onClick(View view) {
} mAdminStateChangedDialog.dismiss();
}); }
});
mAdminStateChangedDialog.show(); mAdminStateChangedDialog.show();
} }
@ -435,12 +502,10 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
} }
@Override @Override
public void onConferenceJoined(ChatRoom cr, EventLog event_log) { public void onConferenceJoined(ChatRoom cr, EventLog event_log) {}
}
@Override @Override
public void onConferenceLeft(ChatRoom cr, EventLog event_log) { public void onConferenceLeft(ChatRoom cr, EventLog event_log) {}
}
@Override @Override
public void onParticipantAdded(ChatRoom cr, EventLog event_log) { public void onParticipantAdded(ChatRoom cr, EventLog event_log) {
@ -453,49 +518,32 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
} }
@Override @Override
public void onChatMessageShouldBeStored(ChatRoom cr, ChatMessage msg) { public void onChatMessageShouldBeStored(ChatRoom cr, ChatMessage msg) {}
}
@Override @Override
public void onParticipantsCapabilitiesChecked(ChatRoom cr, Address deviceAddr, Address[] participantsAddr) { public void onParticipantsCapabilitiesChecked(
ChatRoom cr, Address deviceAddr, Address[] participantsAddr) {}
}
@Override @Override
public void onIsComposingReceived(ChatRoom cr, Address remoteAddr, boolean isComposing) { public void onIsComposingReceived(ChatRoom cr, Address remoteAddr, boolean isComposing) {}
}
@Override @Override
public void onChatMessageSent(ChatRoom cr, EventLog event_log) { public void onChatMessageSent(ChatRoom cr, EventLog event_log) {}
}
@Override @Override
public void onConferenceAddressGeneration(ChatRoom cr) { public void onConferenceAddressGeneration(ChatRoom cr) {}
}
@Override @Override
public void onChatMessageReceived(ChatRoom cr, EventLog event_log) { public void onChatMessageReceived(ChatRoom cr, EventLog event_log) {}
}
@Override @Override
public void onMessageReceived(ChatRoom cr, ChatMessage msg) { public void onMessageReceived(ChatRoom cr, ChatMessage msg) {}
}
@Override @Override
public void onParticipantDeviceRemoved(ChatRoom cr, EventLog event_log) { public void onParticipantDeviceRemoved(ChatRoom cr, EventLog event_log) {}
}
@Override @Override
public void onParticipantDeviceAdded(ChatRoom cr, EventLog event_log) { public void onParticipantDeviceAdded(ChatRoom cr, EventLog event_log) {}
}
@Override @Override
public void onSecurityEvent(ChatRoom cr, EventLog eventLog) { public void onSecurityEvent(ChatRoom cr, EventLog eventLog) {
@ -503,25 +551,19 @@ public class GroupInfoFragment extends Fragment implements ChatRoomListener {
} }
@Override @Override
public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage msg) { public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage msg) {}
}
@Override @Override
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {}
}
@Override @Override
public void onParticipantDeviceFetchRequested(ChatRoom cr, Address addr) { public void onParticipantDeviceFetchRequested(ChatRoom cr, Address addr) {}
}
@Override @Override
public void onParticipantRegistrationSubscriptionRequested(ChatRoom cr, Address participantAddr) { public void onParticipantRegistrationSubscriptionRequested(
} ChatRoom cr, Address participantAddr) {}
@Override @Override
public void onParticipantRegistrationUnsubscriptionRequested(ChatRoom cr, Address participantAddr) { public void onParticipantRegistrationUnsubscriptionRequested(
} ChatRoom cr, Address participantAddr) {}
} }

View file

@ -27,7 +27,7 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
@ -43,11 +43,16 @@ import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.LinphoneUtils; import org.linphone.utils.LinphoneUtils;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
import androidx.annotation.Nullable;
public class ImdnFragment extends Fragment { public class ImdnFragment extends Fragment {
private LayoutInflater mInflater; private LayoutInflater mInflater;
private LinearLayout mRead, mReadHeader, mDelivered, mDeliveredHeader, mSent, mSentHeader, mUndelivered, mUndeliveredHeader; private LinearLayout mRead,
mReadHeader,
mDelivered,
mDeliveredHeader,
mSent,
mSentHeader,
mUndelivered,
mUndeliveredHeader;
private ImageView mBackButton; private ImageView mBackButton;
private ChatMessageViewHolder mBubble; private ChatMessageViewHolder mBubble;
private ViewGroup mContainer; private ViewGroup mContainer;
@ -60,7 +65,8 @@ public class ImdnFragment extends Fragment {
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getArguments() != null) { if (getArguments() != null) {
@ -77,16 +83,17 @@ public class ImdnFragment extends Fragment {
View view = mInflater.inflate(R.layout.chat_imdn, container, false); View view = mInflater.inflate(R.layout.chat_imdn, container, false);
mBackButton = view.findViewById(R.id.back); mBackButton = view.findViewById(R.id.back);
mBackButton.setOnClickListener(new View.OnClickListener() { mBackButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (LinphoneActivity.instance().isTablet()) { public void onClick(View view) {
LinphoneActivity.instance().goToChat(mRoomUri, null); if (LinphoneActivity.instance().isTablet()) {
} else { LinphoneActivity.instance().goToChat(mRoomUri, null);
LinphoneActivity.instance().onBackPressed(); } else {
} LinphoneActivity.instance().onBackPressed();
} }
}); }
});
mRead = view.findViewById(R.id.read_layout); mRead = view.findViewById(R.id.read_layout);
mDelivered = view.findViewById(R.id.delivered_layout); mDelivered = view.findViewById(R.id.delivered_layout);
@ -100,12 +107,14 @@ public class ImdnFragment extends Fragment {
mBubble = new ChatMessageViewHolder(getActivity(), view.findViewById(R.id.bubble), null); mBubble = new ChatMessageViewHolder(getActivity(), view.findViewById(R.id.bubble), null);
mMessage = mRoom.findMessage(mMessageId); mMessage = mRoom.findMessage(mMessageId);
mListener = new ChatMessageListenerStub() { mListener =
@Override new ChatMessageListenerStub() {
public void onParticipantImdnStateChanged(ChatMessage msg, ParticipantImdnState state) { @Override
refreshInfo(); public void onParticipantImdnStateChanged(
} ChatMessage msg, ParticipantImdnState state) {
}; refreshInfo();
}
};
if (mMessage == null) return null; if (mMessage == null) return null;
mMessage.setListener(mListener); mMessage.setListener(mListener);
@ -121,12 +130,14 @@ public class ImdnFragment extends Fragment {
} }
refreshInfo(); refreshInfo();
mMessage.setListener(new ChatMessageListenerStub() { mMessage.setListener(
@Override new ChatMessageListenerStub() {
public void onParticipantImdnStateChanged(ChatMessage msg, ParticipantImdnState state) { @Override
refreshInfo(); public void onParticipantImdnStateChanged(
} ChatMessage msg, ParticipantImdnState state) {
}); refreshInfo();
}
});
} }
@Override @Override
@ -137,11 +148,12 @@ public class ImdnFragment extends Fragment {
private void refreshInfo() { private void refreshInfo() {
if (mMessage == null) { if (mMessage == null) {
//TODO: error // TODO: error
return; return;
} }
Address remoteSender = mMessage.getFromAddress(); Address remoteSender = mMessage.getFromAddress();
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(remoteSender); LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(remoteSender);
mBubble.deleteMessage.setVisibility(View.GONE); mBubble.deleteMessage.setVisibility(View.GONE);
mBubble.deleteEvent.setVisibility(View.GONE); mBubble.deleteEvent.setVisibility(View.GONE);
@ -156,23 +168,34 @@ public class ImdnFragment extends Fragment {
mSent.removeAllViews(); mSent.removeAllViews();
mUndelivered.removeAllViews(); mUndelivered.removeAllViews();
ParticipantImdnState[] participants = mMessage.getParticipantsByImdnState(ChatMessage.State.Displayed); ParticipantImdnState[] participants =
mMessage.getParticipantsByImdnState(ChatMessage.State.Displayed);
mReadHeader.setVisibility(participants.length == 0 ? View.GONE : View.VISIBLE); mReadHeader.setVisibility(participants.length == 0 ? View.GONE : View.VISIBLE);
boolean first = true; boolean first = true;
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
((TextView) v.findViewById(R.id.time)).setText(LinphoneUtils.timestampToHumanDate(getActivity(), participant.getStateChangeTime(), R.string.messages_date_format)); ((TextView) v.findViewById(R.id.time))
.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(),
participant.getStateChangeTime(),
R.string.messages_date_format));
((TextView) v.findViewById(R.id.name)).setText(participantDisplayName); ((TextView) v.findViewById(R.id.name)).setText(participantDisplayName);
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mRead.addView(v); mRead.addView(v);
@ -185,17 +208,27 @@ public class ImdnFragment extends Fragment {
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
((TextView) v.findViewById(R.id.time)).setText(LinphoneUtils.timestampToHumanDate(getActivity(), participant.getStateChangeTime(), R.string.messages_date_format)); ((TextView) v.findViewById(R.id.time))
.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(),
participant.getStateChangeTime(),
R.string.messages_date_format));
((TextView) v.findViewById(R.id.name)).setText(participantDisplayName); ((TextView) v.findViewById(R.id.name)).setText(participantDisplayName);
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mDelivered.addView(v); mDelivered.addView(v);
@ -208,17 +241,27 @@ public class ImdnFragment extends Fragment {
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
((TextView) v.findViewById(R.id.time)).setText(LinphoneUtils.timestampToHumanDate(getActivity(), participant.getStateChangeTime(), R.string.messages_date_format)); ((TextView) v.findViewById(R.id.time))
.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(),
participant.getStateChangeTime(),
R.string.messages_date_format));
((TextView) v.findViewById(R.id.name)).setText(participantDisplayName); ((TextView) v.findViewById(R.id.name)).setText(participantDisplayName);
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mSent.addView(v); mSent.addView(v);
@ -231,8 +274,12 @@ public class ImdnFragment extends Fragment {
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
@ -240,7 +287,8 @@ public class ImdnFragment extends Fragment {
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mUndelivered.addView(v); mUndelivered.addView(v);

View file

@ -21,7 +21,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.app.Fragment; import android.app.Fragment;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -31,12 +30,10 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable;
import org.linphone.LinphoneManager;
import org.linphone.utils.FileUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.compatibility.Compatibility; import org.linphone.compatibility.Compatibility;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
@ -47,11 +44,20 @@ import org.linphone.core.ChatRoom;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.ParticipantImdnState; import org.linphone.core.ParticipantImdnState;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.FileUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
public class ImdnOldFragment extends Fragment { public class ImdnOldFragment extends Fragment {
private LayoutInflater mInflater; private LayoutInflater mInflater;
private LinearLayout mRead, mReadHeader, mDelivered, mDeliveredHeader, mSent, mSentHeader, mUndelivered, mUndeliveredHeader; private LinearLayout mRead,
mReadHeader,
mDelivered,
mDeliveredHeader,
mSent,
mSentHeader,
mUndelivered,
mUndeliveredHeader;
private ImageView mBackButton; private ImageView mBackButton;
private ChatMessageOldViewHolder mBubble; private ChatMessageOldViewHolder mBubble;
private ViewGroup mContainer; private ViewGroup mContainer;
@ -64,7 +70,8 @@ public class ImdnOldFragment extends Fragment {
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (getArguments() != null) { if (getArguments() != null) {
@ -81,16 +88,17 @@ public class ImdnOldFragment extends Fragment {
View view = mInflater.inflate(R.layout.chat_imdn_old, container, false); View view = mInflater.inflate(R.layout.chat_imdn_old, container, false);
mBackButton = view.findViewById(R.id.back); mBackButton = view.findViewById(R.id.back);
mBackButton.setOnClickListener(new View.OnClickListener() { mBackButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View view) { @Override
if (LinphoneActivity.instance().isTablet()) { public void onClick(View view) {
LinphoneActivity.instance().goToChat(mRoomUri, null); if (LinphoneActivity.instance().isTablet()) {
} else { LinphoneActivity.instance().goToChat(mRoomUri, null);
LinphoneActivity.instance().onBackPressed(); } else {
} LinphoneActivity.instance().onBackPressed();
} }
}); }
});
mRead = view.findViewById(R.id.read_layout); mRead = view.findViewById(R.id.read_layout);
mDelivered = view.findViewById(R.id.delivered_layout); mDelivered = view.findViewById(R.id.delivered_layout);
@ -115,28 +123,36 @@ public class ImdnOldFragment extends Fragment {
mBubble.imdmLayout.setVisibility(View.INVISIBLE); mBubble.imdmLayout.setVisibility(View.INVISIBLE);
mMessage = mRoom.findMessage(mMessageId); mMessage = mRoom.findMessage(mMessageId);
mListener = new ChatMessageListenerStub() { mListener =
@Override new ChatMessageListenerStub() {
public void onParticipantImdnStateChanged(ChatMessage msg, ParticipantImdnState state) { @Override
refreshInfo(); public void onParticipantImdnStateChanged(
} ChatMessage msg, ParticipantImdnState state) {
}; refreshInfo();
}
};
if (mMessage == null) return null; if (mMessage == null) return null;
mMessage.setListener(mListener); mMessage.setListener(mListener);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParams.setMargins(100, 10, 10, 10); layoutParams.setMargins(100, 10, 10, 10);
if (mMessage.isOutgoing()) { if (mMessage.isOutgoing()) {
mBubble.background.setBackgroundResource(R.drawable.resizable_chat_bubble_outgoing); mBubble.background.setBackgroundResource(R.drawable.resizable_chat_bubble_outgoing);
Compatibility.setTextAppearance(mBubble.contactName, getActivity(), R.style.font3); Compatibility.setTextAppearance(mBubble.contactName, getActivity(), R.style.font3);
Compatibility.setTextAppearance(mBubble.fileTransferAction, getActivity(), R.style.font15); Compatibility.setTextAppearance(
mBubble.fileTransferAction.setBackgroundResource(R.drawable.resizable_confirm_delete_button); mBubble.fileTransferAction, getActivity(), R.style.font15);
mBubble.fileTransferAction.setBackgroundResource(
R.drawable.resizable_confirm_delete_button);
ContactAvatar.setAvatarMask(mBubble.avatarLayout, R.drawable.avatar_chat_mask_outgoing); ContactAvatar.setAvatarMask(mBubble.avatarLayout, R.drawable.avatar_chat_mask_outgoing);
} else { } else {
mBubble.background.setBackgroundResource(R.drawable.resizable_chat_bubble_incoming); mBubble.background.setBackgroundResource(R.drawable.resizable_chat_bubble_incoming);
Compatibility.setTextAppearance(mBubble.contactName, getActivity(), R.style.font9); Compatibility.setTextAppearance(mBubble.contactName, getActivity(), R.style.font9);
Compatibility.setTextAppearance(mBubble.fileTransferAction, getActivity(), R.style.font8); Compatibility.setTextAppearance(
mBubble.fileTransferAction, getActivity(), R.style.font8);
mBubble.fileTransferAction.setBackgroundResource(R.drawable.resizable_assistant_button); mBubble.fileTransferAction.setBackgroundResource(R.drawable.resizable_assistant_button);
ContactAvatar.setAvatarMask(mBubble.avatarLayout, R.drawable.avatar_chat_mask); ContactAvatar.setAvatarMask(mBubble.avatarLayout, R.drawable.avatar_chat_mask);
} }
@ -157,7 +173,8 @@ public class ImdnOldFragment extends Fragment {
private void refreshInfo() { private void refreshInfo() {
Address remoteSender = mMessage.getFromAddress(); Address remoteSender = mMessage.getFromAddress();
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(remoteSender); LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(remoteSender);
String displayName; String displayName;
if (contact != null) { if (contact != null) {
@ -172,7 +189,11 @@ public class ImdnOldFragment extends Fragment {
displayName = LinphoneUtils.getAddressDisplayName(remoteSender); displayName = LinphoneUtils.getAddressDisplayName(remoteSender);
ContactAvatar.displayAvatar(displayName, mBubble.avatarLayout); ContactAvatar.displayAvatar(displayName, mBubble.avatarLayout);
} }
mBubble.contactName.setText(LinphoneUtils.timestampToHumanDate(getActivity(), mMessage.getTime(), R.string.messages_date_format) + " - " + displayName); mBubble.contactName.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(), mMessage.getTime(), R.string.messages_date_format)
+ " - "
+ displayName);
if (mMessage.hasTextContent()) { if (mMessage.hasTextContent()) {
String msg = mMessage.getTextContent(); String msg = mMessage.getTextContent();
@ -194,23 +215,34 @@ public class ImdnOldFragment extends Fragment {
mSent.removeAllViews(); mSent.removeAllViews();
mUndelivered.removeAllViews(); mUndelivered.removeAllViews();
ParticipantImdnState[] participants = mMessage.getParticipantsByImdnState(ChatMessage.State.Displayed); ParticipantImdnState[] participants =
mMessage.getParticipantsByImdnState(ChatMessage.State.Displayed);
mReadHeader.setVisibility(participants.length == 0 ? View.GONE : View.VISIBLE); mReadHeader.setVisibility(participants.length == 0 ? View.GONE : View.VISIBLE);
boolean first = true; boolean first = true;
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
((TextView) v.findViewById(R.id.time)).setText(LinphoneUtils.timestampToHumanDate(getActivity(), participant.getStateChangeTime(), R.string.messages_date_format)); ((TextView) v.findViewById(R.id.time))
.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(),
participant.getStateChangeTime(),
R.string.messages_date_format));
((TextView) v.findViewById(R.id.name)).setText(participantDisplayName); ((TextView) v.findViewById(R.id.name)).setText(participantDisplayName);
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mRead.addView(v); mRead.addView(v);
@ -223,17 +255,27 @@ public class ImdnOldFragment extends Fragment {
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
((TextView) v.findViewById(R.id.time)).setText(LinphoneUtils.timestampToHumanDate(getActivity(), participant.getStateChangeTime(), R.string.messages_date_format)); ((TextView) v.findViewById(R.id.time))
.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(),
participant.getStateChangeTime(),
R.string.messages_date_format));
((TextView) v.findViewById(R.id.name)).setText(participantDisplayName); ((TextView) v.findViewById(R.id.name)).setText(participantDisplayName);
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mDelivered.addView(v); mDelivered.addView(v);
@ -246,17 +288,27 @@ public class ImdnOldFragment extends Fragment {
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
((TextView) v.findViewById(R.id.time)).setText(LinphoneUtils.timestampToHumanDate(getActivity(), participant.getStateChangeTime(), R.string.messages_date_format)); ((TextView) v.findViewById(R.id.time))
.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(),
participant.getStateChangeTime(),
R.string.messages_date_format));
((TextView) v.findViewById(R.id.name)).setText(participantDisplayName); ((TextView) v.findViewById(R.id.name)).setText(participantDisplayName);
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mSent.addView(v); mSent.addView(v);
@ -269,8 +321,12 @@ public class ImdnOldFragment extends Fragment {
for (ParticipantImdnState participant : participants) { for (ParticipantImdnState participant : participants) {
Address address = participant.getParticipant().getAddress(); Address address = participant.getParticipant().getAddress();
LinphoneContact participantContact = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact participantContact =
String participantDisplayName = participantContact != null ? participantContact.getFullName() : LinphoneUtils.getAddressDisplayName(address); ContactsManager.getInstance().findContactFromAddress(address);
String participantDisplayName =
participantContact != null
? participantContact.getFullName()
: LinphoneUtils.getAddressDisplayName(address);
View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false); View v = mInflater.inflate(R.layout.chat_imdn_cell, mContainer, false);
v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE); v.findViewById(R.id.separator).setVisibility(first ? View.GONE : View.VISIBLE);
@ -278,7 +334,8 @@ public class ImdnOldFragment extends Fragment {
if (participantContact != null) { if (participantContact != null) {
ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(participantContact, v.findViewById(R.id.avatar_layout));
} else { } else {
ContactAvatar.displayAvatar(participantDisplayName, v.findViewById(R.id.avatar_layout)); ContactAvatar.displayAvatar(
participantDisplayName, v.findViewById(R.id.avatar_layout));
} }
mUndelivered.addView(v); mUndelivered.addView(v);

View file

@ -19,6 +19,12 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP;
import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY;
import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID;
import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -28,48 +34,51 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.Icon; import android.graphics.drawable.Icon;
import android.net.Uri;
import org.linphone.R; import org.linphone.R;
import org.linphone.mediastream.Log;
import org.linphone.notifications.Notifiable; import org.linphone.notifications.Notifiable;
import org.linphone.notifications.NotifiableMessage; import org.linphone.notifications.NotifiableMessage;
import org.linphone.notifications.NotificationBroadcastReceiver; import org.linphone.notifications.NotificationBroadcastReceiver;
import org.linphone.utils.FileUtils;
import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP;
import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY;
import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID;
import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY;
@TargetApi(28) @TargetApi(28)
public class ApiTwentyEightPlus { public class ApiTwentyEightPlus {
public static Notification createMessageNotification(Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) { public static Notification createMessageNotification(
Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) {
String replyLabel = context.getResources().getString(R.string.notification_reply_label); String replyLabel = context.getResources().getString(R.string.notification_reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); RemoteInput remoteInput =
new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build();
Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class);
replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION);
replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId());
replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity());
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context, PendingIntent replyPendingIntent =
notif.getNotificationId(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context,
notif.getNotificationId(),
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over, Notification.Action action =
context.getString(R.string.notification_reply_label), replyPendingIntent) new Notification.Action.Builder(
.addRemoteInput(remoteInput) R.drawable.chat_send_over,
.setAllowGeneratedReplies(true) context.getString(R.string.notification_reply_label),
.build(); replyPendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
Person me = new Person.Builder().setName(notif.getMyself()).build(); Person me = new Person.Builder().setName(notif.getMyself()).build();
Notification.MessagingStyle style = new Notification.MessagingStyle(me); Notification.MessagingStyle style = new Notification.MessagingStyle(me);
for (NotifiableMessage message : notif.getMessages()) { for (NotifiableMessage message : notif.getMessages()) {
Icon userIcon = Icon.createWithBitmap(message.getSenderBitmap()); Icon userIcon = Icon.createWithBitmap(message.getSenderBitmap());
Person user = new Person.Builder().setName(message.getSender()).setIcon(userIcon).build(); Person user =
Notification.MessagingStyle.Message msg = new Notification.MessagingStyle.Message(message.getMessage(), message.getTime(), user); new Person.Builder().setName(message.getSender()).setIcon(userIcon).build();
if (message.getFilePath() != null) msg.setData(message.getFileMime(), message.getFilePath()); Notification.MessagingStyle.Message msg =
new Notification.MessagingStyle.Message(
message.getMessage(), message.getTime(), user);
if (message.getFilePath() != null)
msg.setData(message.getFileMime(), message.getFilePath());
style.addMessage(msg); style.addMessage(msg);
} }
if (notif.isGroup()) { if (notif.isGroup()) {
@ -77,22 +86,26 @@ public class ApiTwentyEightPlus {
} }
style.setGroupConversation(notif.isGroup()); style.setGroupConversation(notif.isGroup());
return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) return new Notification.Builder(
.setSmallIcon(R.drawable.topbar_chat_notification) context, context.getString(R.string.notification_channel_id))
.setAutoCancel(true) .setSmallIcon(R.drawable.topbar_chat_notification)
.setContentIntent(intent) .setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS) .setContentIntent(intent)
.setLargeIcon(contactIcon) .setDefaults(
.setCategory(Notification.CATEGORY_MESSAGE) Notification.DEFAULT_SOUND
.setGroup(CHAT_NOTIFICATIONS_GROUP) | Notification.DEFAULT_VIBRATE
.setVisibility(Notification.VISIBILITY_PRIVATE) | Notification.DEFAULT_LIGHTS)
.setPriority(Notification.PRIORITY_HIGH) .setLargeIcon(contactIcon)
.setNumber(notif.getMessages().size()) .setCategory(Notification.CATEGORY_MESSAGE)
.setWhen(System.currentTimeMillis()) .setGroup(CHAT_NOTIFICATIONS_GROUP)
.setShowWhen(true) .setVisibility(Notification.VISIBILITY_PRIVATE)
.setColor(context.getColor(R.color.notification_color_led)) .setPriority(Notification.PRIORITY_HIGH)
.setStyle(style) .setNumber(notif.getMessages().size())
.addAction(action) .setWhen(System.currentTimeMillis())
.build(); .setShowWhen(true)
.setColor(context.getColor(R.color.notification_color_led))
.setStyle(style)
.addAction(action)
.build();
} }
} }

View file

@ -19,22 +19,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import org.linphone.R;
import org.linphone.mediastream.Log;
import org.linphone.notifications.Notifiable;
import org.linphone.notifications.NotifiableMessage;
import org.linphone.notifications.NotificationBroadcastReceiver;
import org.linphone.utils.FileUtils;
import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP; import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP;
import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION; import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION; import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION;
@ -43,97 +27,141 @@ import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID;
import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION; import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY; import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import org.linphone.R;
import org.linphone.notifications.Notifiable;
import org.linphone.notifications.NotifiableMessage;
import org.linphone.notifications.NotificationBroadcastReceiver;
@TargetApi(24) @TargetApi(24)
public class ApiTwentyFourPlus { public class ApiTwentyFourPlus {
public static Notification createRepliedNotification(Context context, String reply) { public static Notification createRepliedNotification(Context context, String reply) {
return new Notification.Builder(context) return new Notification.Builder(context)
.setSmallIcon(R.drawable.topbar_chat_notification) .setSmallIcon(R.drawable.topbar_chat_notification)
.setContentText(context.getString(R.string.notification_replied_label).replace("%s", reply)) .setContentText(
.build(); context.getString(R.string.notification_replied_label).replace("%s", reply))
} .build();
}
public static Notification createMessageNotification(Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) { public static Notification createMessageNotification(
String replyLabel = context.getResources().getString(R.string.notification_reply_label); Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) {
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); String replyLabel = context.getResources().getString(R.string.notification_reply_label);
RemoteInput remoteInput =
new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build();
Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class);
replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION);
replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId());
replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity());
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context, PendingIntent replyPendingIntent =
notif.getNotificationId(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context,
notif.getNotificationId(),
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over, Notification.Action action =
context.getString(R.string.notification_reply_label), replyPendingIntent) new Notification.Action.Builder(
.addRemoteInput(remoteInput) R.drawable.chat_send_over,
.setAllowGeneratedReplies(true) context.getString(R.string.notification_reply_label),
.build(); replyPendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
Notification.MessagingStyle style = new Notification.MessagingStyle(notif.getMyself()); Notification.MessagingStyle style = new Notification.MessagingStyle(notif.getMyself());
for (NotifiableMessage message : notif.getMessages()) { for (NotifiableMessage message : notif.getMessages()) {
Notification.MessagingStyle.Message msg = new Notification.MessagingStyle.Message(message.getMessage(), message.getTime(), message.getSender()); Notification.MessagingStyle.Message msg =
if (message.getFilePath() != null) msg.setData(message.getFileMime(), message.getFilePath()); new Notification.MessagingStyle.Message(
message.getMessage(), message.getTime(), message.getSender());
if (message.getFilePath() != null)
msg.setData(message.getFileMime(), message.getFilePath());
style.addMessage(msg); style.addMessage(msg);
} }
if (notif.isGroup()) { if (notif.isGroup()) {
style.setConversationTitle(notif.getGroupTitle()); style.setConversationTitle(notif.getGroupTitle());
} }
return new Notification.Builder(context) return new Notification.Builder(context)
.setSmallIcon(R.drawable.topbar_chat_notification) .setSmallIcon(R.drawable.topbar_chat_notification)
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(intent) .setContentIntent(intent)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS) .setDefaults(
.setLargeIcon(contactIcon) Notification.DEFAULT_SOUND
.setCategory(Notification.CATEGORY_MESSAGE) | Notification.DEFAULT_VIBRATE
.setGroup(CHAT_NOTIFICATIONS_GROUP) | Notification.DEFAULT_LIGHTS)
.setVisibility(Notification.VISIBILITY_PRIVATE) .setLargeIcon(contactIcon)
.setPriority(Notification.PRIORITY_HIGH) .setCategory(Notification.CATEGORY_MESSAGE)
.setNumber(notif.getMessages().size()) .setGroup(CHAT_NOTIFICATIONS_GROUP)
.setWhen(System.currentTimeMillis()) .setVisibility(Notification.VISIBILITY_PRIVATE)
.setShowWhen(true) .setPriority(Notification.PRIORITY_HIGH)
.setColor(context.getColor(R.color.notification_color_led)) .setNumber(notif.getMessages().size())
.setStyle(style) .setWhen(System.currentTimeMillis())
.addAction(action) .setShowWhen(true)
.build(); .setColor(context.getColor(R.color.notification_color_led))
} .setStyle(style)
.addAction(action)
.build();
}
public static Notification createInCallNotification(Context context, public static Notification createInCallNotification(
int callId, boolean showAnswerAction, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { Context context,
int callId,
boolean showAnswerAction,
String msg,
int iconID,
Bitmap contactIcon,
String contactName,
PendingIntent intent) {
Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class);
hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION); hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION);
hangupIntent.putExtra(INTENT_NOTIF_ID, callId); hangupIntent.putExtra(INTENT_NOTIF_ID, callId);
PendingIntent hangupPendingIntent = PendingIntent.getBroadcast(context, PendingIntent hangupPendingIntent =
callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context, callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context) Notification.Builder builder =
.setContentTitle(contactName) new Notification.Builder(context)
.setContentText(msg) .setContentTitle(contactName)
.setSmallIcon(iconID) .setContentText(msg)
.setAutoCancel(false) .setSmallIcon(iconID)
.setContentIntent(intent) .setAutoCancel(false)
.setLargeIcon(contactIcon) .setContentIntent(intent)
.setCategory(Notification.CATEGORY_CALL) .setLargeIcon(contactIcon)
.setVisibility(Notification.VISIBILITY_PUBLIC) .setCategory(Notification.CATEGORY_CALL)
.setPriority(Notification.PRIORITY_HIGH) .setVisibility(Notification.VISIBILITY_PUBLIC)
.setWhen(System.currentTimeMillis()) .setPriority(Notification.PRIORITY_HIGH)
.setShowWhen(true) .setWhen(System.currentTimeMillis())
.setColor(context.getColor(R.color.notification_color_led)) .setShowWhen(true)
.addAction(R.drawable.call_hangup, context.getString(R.string.notification_call_hangup_label), hangupPendingIntent); .setColor(context.getColor(R.color.notification_color_led))
.addAction(
R.drawable.call_hangup,
context.getString(R.string.notification_call_hangup_label),
hangupPendingIntent);
if (showAnswerAction) { if (showAnswerAction) {
Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class);
answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION); answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION);
answerIntent.putExtra(INTENT_NOTIF_ID, callId); answerIntent.putExtra(INTENT_NOTIF_ID, callId);
PendingIntent answerPendingIntent = PendingIntent.getBroadcast(context, PendingIntent answerPendingIntent =
callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context, callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.call_audio_start, context.getString(R.string.notification_call_answer_label), answerPendingIntent); builder.addAction(
R.drawable.call_audio_start,
context.getString(R.string.notification_call_answer_label),
answerPendingIntent);
} }
return builder.build(); return builder.build();

View file

@ -25,148 +25,183 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import org.linphone.R; import org.linphone.R;
@TargetApi(21) @TargetApi(21)
public class ApiTwentyOnePlus { public class ApiTwentyOnePlus {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static Notification createMessageNotification(Context context, public static Notification createMessageNotification(
int msgCount, String msgSender, String msg, Bitmap contactIcon, Context context,
PendingIntent intent) { int msgCount,
String msgSender,
String msg,
Bitmap contactIcon,
PendingIntent intent) {
String title; String title;
if (msgCount == 1) { if (msgCount == 1) {
title = msgSender; title = msgSender;
} else { } else {
title = context.getString(R.string.unread_messages).replace("%i", String.valueOf(msgCount)); title =
context.getString(R.string.unread_messages)
.replace("%i", String.valueOf(msgCount));
} }
Notification notif = new Notification.Builder(context) Notification notif =
.setContentTitle(title) new Notification.Builder(context)
.setContentText(msg) .setContentTitle(title)
.setSmallIcon(R.drawable.topbar_chat_notification) .setContentText(msg)
.setAutoCancel(true) .setSmallIcon(R.drawable.topbar_chat_notification)
.setContentIntent(intent) .setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND .setContentIntent(intent)
| Notification.DEFAULT_VIBRATE .setDefaults(
| Notification.DEFAULT_LIGHTS) Notification.DEFAULT_SOUND
.setLargeIcon(contactIcon) | Notification.DEFAULT_VIBRATE
.setLights(ContextCompat.getColor(context, R.color.notification_color_led), | Notification.DEFAULT_LIGHTS)
context.getResources().getInteger(R.integer.notification_ms_on), .setLargeIcon(contactIcon)
context.getResources().getInteger(R.integer.notification_ms_off)) .setLights(
.setCategory(Notification.CATEGORY_MESSAGE) ContextCompat.getColor(context, R.color.notification_color_led),
.setVisibility(Notification.VISIBILITY_PRIVATE) context.getResources().getInteger(R.integer.notification_ms_on),
.setPriority(Notification.PRIORITY_HIGH) context.getResources().getInteger(R.integer.notification_ms_off))
.setNumber(msgCount) .setCategory(Notification.CATEGORY_MESSAGE)
.setWhen(System.currentTimeMillis()) .setVisibility(Notification.VISIBILITY_PRIVATE)
.setShowWhen(true) .setPriority(Notification.PRIORITY_HIGH)
.build(); .setNumber(msgCount)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();
return notif; return notif;
} }
public static Notification createInCallNotification(Context context, public static Notification createInCallNotification(
String title, String msg, int iconID, Bitmap contactIcon, Context context,
String contactName, PendingIntent intent) { String title,
String msg,
int iconID,
Bitmap contactIcon,
String contactName,
PendingIntent intent) {
Notification notif = new Notification.Builder(context).setContentTitle(contactName) Notification notif =
.setContentText(msg) new Notification.Builder(context)
.setSmallIcon(iconID) .setContentTitle(contactName)
.setAutoCancel(false) .setContentText(msg)
.setContentIntent(intent) .setSmallIcon(iconID)
.setLargeIcon(contactIcon) .setAutoCancel(false)
.setCategory(Notification.CATEGORY_CALL) .setContentIntent(intent)
.setVisibility(Notification.VISIBILITY_PUBLIC) .setLargeIcon(contactIcon)
.setPriority(Notification.PRIORITY_HIGH) .setCategory(Notification.CATEGORY_CALL)
.setLights(ContextCompat.getColor(context, R.color.notification_color_led), .setVisibility(Notification.VISIBILITY_PUBLIC)
context.getResources().getInteger(R.integer.notification_ms_on), .setPriority(Notification.PRIORITY_HIGH)
context.getResources().getInteger(R.integer.notification_ms_off)) .setLights(
.setShowWhen(true) ContextCompat.getColor(context, R.color.notification_color_led),
.build(); context.getResources().getInteger(R.integer.notification_ms_on),
context.getResources().getInteger(R.integer.notification_ms_off))
.setShowWhen(true)
.build();
return notif; return notif;
} }
public static Notification createNotification(Context context, String title, String message, int icon, int level, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent, int priority) { public static Notification createNotification(
Context context,
String title,
String message,
int icon,
int level,
Bitmap largeIcon,
PendingIntent intent,
boolean isOngoingEvent,
int priority) {
Notification notif; Notification notif;
if (largeIcon != null) { if (largeIcon != null) {
notif = new Notification.Builder(context) notif =
.setContentTitle(title) new Notification.Builder(context)
.setContentText(message) .setContentTitle(title)
.setSmallIcon(icon, level) .setContentText(message)
.setLargeIcon(largeIcon) .setSmallIcon(icon, level)
.setContentIntent(intent) .setLargeIcon(largeIcon)
.setCategory(Notification.CATEGORY_SERVICE) .setContentIntent(intent)
.setVisibility(Notification.VISIBILITY_SECRET) .setCategory(Notification.CATEGORY_SERVICE)
.setLights(ContextCompat.getColor(context, R.color.notification_color_led), .setVisibility(Notification.VISIBILITY_SECRET)
context.getResources().getInteger(R.integer.notification_ms_on), .setLights(
context.getResources().getInteger(R.integer.notification_ms_off)) ContextCompat.getColor(context, R.color.notification_color_led),
.setWhen(System.currentTimeMillis()) context.getResources().getInteger(R.integer.notification_ms_on),
.setPriority(priority) context.getResources()
.setShowWhen(true) .getInteger(R.integer.notification_ms_off))
.build(); .setWhen(System.currentTimeMillis())
.setPriority(priority)
.setShowWhen(true)
.build();
} else { } else {
notif = new Notification.Builder(context) notif =
.setContentTitle(title) new Notification.Builder(context)
.setContentText(message) .setContentTitle(title)
.setSmallIcon(icon, level) .setContentText(message)
.setContentIntent(intent) .setSmallIcon(icon, level)
.setCategory(Notification.CATEGORY_SERVICE) .setContentIntent(intent)
.setVisibility(Notification.VISIBILITY_SECRET) .setCategory(Notification.CATEGORY_SERVICE)
.setLights(ContextCompat.getColor(context, R.color.notification_color_led), .setVisibility(Notification.VISIBILITY_SECRET)
context.getResources().getInteger(R.integer.notification_ms_on), .setLights(
context.getResources().getInteger(R.integer.notification_ms_off)) ContextCompat.getColor(context, R.color.notification_color_led),
.setPriority(priority) context.getResources().getInteger(R.integer.notification_ms_on),
.setWhen(System.currentTimeMillis()) context.getResources()
.setShowWhen(true) .getInteger(R.integer.notification_ms_off))
.build(); .setPriority(priority)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();
} }
return notif; return notif;
} }
public static Notification createMissedCallNotification(Context context, String title, String text, PendingIntent intent) { public static Notification createMissedCallNotification(
Notification notif = new Notification.Builder(context) Context context, String title, String text, PendingIntent intent) {
.setContentTitle(title) Notification notif =
.setContentText(text) new Notification.Builder(context)
.setSmallIcon(R.drawable.call_status_missed) .setContentTitle(title)
.setAutoCancel(true) .setContentText(text)
.setContentIntent(intent) .setSmallIcon(R.drawable.call_status_missed)
.setDefaults(Notification.DEFAULT_SOUND .setAutoCancel(true)
| Notification.DEFAULT_VIBRATE) .setContentIntent(intent)
.setCategory(Notification.CATEGORY_EVENT) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setVisibility(Notification.VISIBILITY_PRIVATE) .setCategory(Notification.CATEGORY_EVENT)
.setLights(ContextCompat.getColor(context, R.color.notification_color_led), .setVisibility(Notification.VISIBILITY_PRIVATE)
context.getResources().getInteger(R.integer.notification_ms_on), .setLights(
context.getResources().getInteger(R.integer.notification_ms_off)) ContextCompat.getColor(context, R.color.notification_color_led),
.setPriority(Notification.PRIORITY_HIGH) context.getResources().getInteger(R.integer.notification_ms_on),
.setWhen(System.currentTimeMillis()) context.getResources().getInteger(R.integer.notification_ms_off))
.setShowWhen(true) .setPriority(Notification.PRIORITY_HIGH)
.build(); .setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();
return notif; return notif;
} }
public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) { public static Notification createSimpleNotification(
Notification notif = new Notification.Builder(context) Context context, String title, String text, PendingIntent intent) {
.setContentTitle(title) Notification notif =
.setContentText(text) new Notification.Builder(context)
.setSmallIcon(R.drawable.linphone_logo) .setContentTitle(title)
.setAutoCancel(true) .setContentText(text)
.setContentIntent(intent) .setSmallIcon(R.drawable.linphone_logo)
.setDefaults(Notification.DEFAULT_SOUND .setAutoCancel(true)
| Notification.DEFAULT_VIBRATE) .setContentIntent(intent)
.setCategory(Notification.CATEGORY_MESSAGE) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setVisibility(Notification.VISIBILITY_PRIVATE) .setCategory(Notification.CATEGORY_MESSAGE)
.setLights(ContextCompat.getColor(context, R.color.notification_color_led), .setVisibility(Notification.VISIBILITY_PRIVATE)
context.getResources().getInteger(R.integer.notification_ms_on), .setLights(
context.getResources().getInteger(R.integer.notification_ms_off)) ContextCompat.getColor(context, R.color.notification_color_led),
.setWhen(System.currentTimeMillis()) context.getResources().getInteger(R.integer.notification_ms_on),
.setPriority(Notification.PRIORITY_HIGH) context.getResources().getInteger(R.integer.notification_ms_off))
.setShowWhen(true) .setWhen(System.currentTimeMillis())
.build(); .setPriority(Notification.PRIORITY_HIGH)
.setShowWhen(true)
.build();
return notif; return notif;
} }

View file

@ -19,6 +19,14 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP;
import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY;
import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID;
import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.app.Notification; import android.app.Notification;
@ -29,45 +37,37 @@ import android.app.RemoteInput;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import org.linphone.R; import org.linphone.R;
import org.linphone.notifications.Notifiable; import org.linphone.notifications.Notifiable;
import org.linphone.notifications.NotifiableMessage; import org.linphone.notifications.NotifiableMessage;
import org.linphone.notifications.NotificationBroadcastReceiver; import org.linphone.notifications.NotificationBroadcastReceiver;
import org.linphone.utils.FileUtils;
import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP;
import static org.linphone.compatibility.Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY;
import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID;
import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION;
import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY;
@TargetApi(26) @TargetApi(26)
public class ApiTwentySixPlus { public class ApiTwentySixPlus {
public static Notification createRepliedNotification(Context context, String reply) { public static Notification createRepliedNotification(Context context, String reply) {
return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) return new Notification.Builder(
.setSmallIcon(R.drawable.topbar_chat_notification) context, context.getString(R.string.notification_channel_id))
.setContentText(context.getString(R.string.notification_replied_label).replace("%s", reply)) .setSmallIcon(R.drawable.topbar_chat_notification)
.build(); .setContentText(
} context.getString(R.string.notification_replied_label).replace("%s", reply))
.build();
}
public static void createServiceChannel(Context context) { public static void createServiceChannel(Context context) {
NotificationManager notificationManager = NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// Create service/call notification channel // Create service/call notification channel
String id = context.getString(R.string.notification_service_channel_id); String id = context.getString(R.string.notification_service_channel_id);
CharSequence name = context.getString(R.string.content_title_notification_service); CharSequence name = context.getString(R.string.content_title_notification_service);
String description = context.getString(R.string.content_title_notification_service); String description = context.getString(R.string.content_title_notification_service);
NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_NONE); NotificationChannel channel =
channel.setDescription(description); new NotificationChannel(id, name, NotificationManager.IMPORTANCE_NONE);
channel.enableVibration(false); channel.setDescription(description);
channel.enableLights(false); channel.enableVibration(false);
channel.enableLights(false);
channel.setShowBadge(false); channel.setShowBadge(false);
notificationManager.createNotificationChannel(channel); notificationManager.createNotificationChannel(channel);
} }
public static void createMessageChannel(Context context) { public static void createMessageChannel(Context context) {
NotificationManager notificationManager = NotificationManager notificationManager =
@ -76,7 +76,8 @@ public class ApiTwentySixPlus {
String id = context.getString(R.string.notification_channel_id); String id = context.getString(R.string.notification_channel_id);
String name = context.getString(R.string.content_title_notification); String name = context.getString(R.string.content_title_notification);
String description = context.getString(R.string.content_title_notification); String description = context.getString(R.string.content_title_notification);
NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel =
new NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(description); channel.setDescription(description);
channel.setLightColor(context.getColor(R.color.notification_color_led)); channel.setLightColor(context.getColor(R.color.notification_color_led));
channel.enableLights(true); channel.enableLights(true);
@ -85,166 +86,213 @@ public class ApiTwentySixPlus {
notificationManager.createNotificationChannel(channel); notificationManager.createNotificationChannel(channel);
} }
public static Notification createMessageNotification(Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) { public static Notification createMessageNotification(
String replyLabel = context.getResources().getString(R.string.notification_reply_label); Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) {
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build(); String replyLabel = context.getResources().getString(R.string.notification_reply_label);
RemoteInput remoteInput =
new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(replyLabel).build();
Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent replyIntent = new Intent(context, NotificationBroadcastReceiver.class);
replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION);
replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId());
replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity());
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context, PendingIntent replyPendingIntent =
notif.getNotificationId(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context,
notif.getNotificationId(),
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Action action = new Notification.Action.Builder(R.drawable.chat_send_over, Notification.Action action =
context.getString(R.string.notification_reply_label), replyPendingIntent) new Notification.Action.Builder(
.addRemoteInput(remoteInput) R.drawable.chat_send_over,
.setAllowGeneratedReplies(true) context.getString(R.string.notification_reply_label),
.build(); replyPendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
Notification.MessagingStyle style = new Notification.MessagingStyle(notif.getMyself()); Notification.MessagingStyle style = new Notification.MessagingStyle(notif.getMyself());
for (NotifiableMessage message : notif.getMessages()) { for (NotifiableMessage message : notif.getMessages()) {
Notification.MessagingStyle.Message msg = new Notification.MessagingStyle.Message(message.getMessage(), message.getTime(), message.getSender()); Notification.MessagingStyle.Message msg =
if (message.getFilePath() != null) msg.setData(message.getFileMime(), message.getFilePath()); new Notification.MessagingStyle.Message(
message.getMessage(), message.getTime(), message.getSender());
if (message.getFilePath() != null)
msg.setData(message.getFileMime(), message.getFilePath());
style.addMessage(msg); style.addMessage(msg);
} }
if (notif.isGroup()) { if (notif.isGroup()) {
style.setConversationTitle(notif.getGroupTitle()); style.setConversationTitle(notif.getGroupTitle());
} }
return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) return new Notification.Builder(
.setSmallIcon(R.drawable.topbar_chat_notification) context, context.getString(R.string.notification_channel_id))
.setAutoCancel(true) .setSmallIcon(R.drawable.topbar_chat_notification)
.setContentIntent(intent) .setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS) .setContentIntent(intent)
.setLargeIcon(contactIcon) .setDefaults(
.setCategory(Notification.CATEGORY_MESSAGE) Notification.DEFAULT_SOUND
.setGroup(CHAT_NOTIFICATIONS_GROUP) | Notification.DEFAULT_VIBRATE
.setVisibility(Notification.VISIBILITY_PRIVATE) | Notification.DEFAULT_LIGHTS)
.setPriority(Notification.PRIORITY_HIGH) .setLargeIcon(contactIcon)
.setNumber(notif.getMessages().size()) .setCategory(Notification.CATEGORY_MESSAGE)
.setWhen(System.currentTimeMillis()) .setGroup(CHAT_NOTIFICATIONS_GROUP)
.setShowWhen(true) .setVisibility(Notification.VISIBILITY_PRIVATE)
.setColor(context.getColor(R.color.notification_color_led)) .setPriority(Notification.PRIORITY_HIGH)
.setStyle(style) .setNumber(notif.getMessages().size())
.addAction(action) .setWhen(System.currentTimeMillis())
.build(); .setShowWhen(true)
} .setColor(context.getColor(R.color.notification_color_led))
.setStyle(style)
.addAction(action)
.build();
}
public static Notification createInCallNotification(Context context, public static Notification createInCallNotification(
int callId, boolean showAnswerAction, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { Context context,
int callId,
boolean showAnswerAction,
String msg,
int iconID,
Bitmap contactIcon,
String contactName,
PendingIntent intent) {
Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent hangupIntent = new Intent(context, NotificationBroadcastReceiver.class);
hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION); hangupIntent.setAction(INTENT_HANGUP_CALL_NOTIF_ACTION);
hangupIntent.putExtra(INTENT_NOTIF_ID, callId); hangupIntent.putExtra(INTENT_NOTIF_ID, callId);
PendingIntent hangupPendingIntent = PendingIntent.getBroadcast(context, PendingIntent hangupPendingIntent =
callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context, callId, hangupIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) Notification.Builder builder =
.setContentTitle(contactName) new Notification.Builder(
.setContentText(msg) context,
.setSmallIcon(iconID) context.getString(R.string.notification_service_channel_id))
.setAutoCancel(false) .setContentTitle(contactName)
.setContentIntent(intent) .setContentText(msg)
.setLargeIcon(contactIcon) .setSmallIcon(iconID)
.setCategory(Notification.CATEGORY_CALL) .setAutoCancel(false)
.setVisibility(Notification.VISIBILITY_PUBLIC) .setContentIntent(intent)
.setPriority(Notification.PRIORITY_HIGH) .setLargeIcon(contactIcon)
.setWhen(System.currentTimeMillis()) .setCategory(Notification.CATEGORY_CALL)
.setShowWhen(true) .setVisibility(Notification.VISIBILITY_PUBLIC)
.setColor(context.getColor(R.color.notification_color_led)) .setPriority(Notification.PRIORITY_HIGH)
.addAction(R.drawable.call_hangup, context.getString(R.string.notification_call_hangup_label), hangupPendingIntent); .setWhen(System.currentTimeMillis())
.setShowWhen(true)
.setColor(context.getColor(R.color.notification_color_led))
.addAction(
R.drawable.call_hangup,
context.getString(R.string.notification_call_hangup_label),
hangupPendingIntent);
if (showAnswerAction) { if (showAnswerAction) {
Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class); Intent answerIntent = new Intent(context, NotificationBroadcastReceiver.class);
answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION); answerIntent.setAction(INTENT_ANSWER_CALL_NOTIF_ACTION);
answerIntent.putExtra(INTENT_NOTIF_ID, callId); answerIntent.putExtra(INTENT_NOTIF_ID, callId);
PendingIntent answerPendingIntent = PendingIntent.getBroadcast(context, PendingIntent answerPendingIntent =
callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.getBroadcast(
context, callId, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.call_audio_start, context.getString(R.string.notification_call_answer_label), answerPendingIntent); builder.addAction(
R.drawable.call_audio_start,
context.getString(R.string.notification_call_answer_label),
answerPendingIntent);
} }
return builder.build(); return builder.build();
} }
public static Notification createNotification(Context context, String title, String message, int icon, int level, public static Notification createNotification(
Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent,int priority) { Context context,
String title,
String message,
int icon,
int level,
Bitmap largeIcon,
PendingIntent intent,
boolean isOngoingEvent,
int priority) {
if (largeIcon != null) { if (largeIcon != null) {
return new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) return new Notification.Builder(
.setContentTitle(title) context, context.getString(R.string.notification_service_channel_id))
.setContentText(message) .setContentTitle(title)
.setSmallIcon(icon, level) .setContentText(message)
.setLargeIcon(largeIcon) .setSmallIcon(icon, level)
.setContentIntent(intent) .setLargeIcon(largeIcon)
.setCategory(Notification.CATEGORY_SERVICE) .setContentIntent(intent)
.setVisibility(Notification.VISIBILITY_SECRET) .setCategory(Notification.CATEGORY_SERVICE)
.setPriority(priority) .setVisibility(Notification.VISIBILITY_SECRET)
.setWhen(System.currentTimeMillis()) .setPriority(priority)
.setShowWhen(true) .setWhen(System.currentTimeMillis())
.setColor(context.getColor(R.color.notification_color_led)) .setShowWhen(true)
.build(); .setColor(context.getColor(R.color.notification_color_led))
} else { .build();
return new Notification.Builder(context, context.getString(R.string.notification_service_channel_id)) } else {
.setContentTitle(title) return new Notification.Builder(
.setContentText(message) context, context.getString(R.string.notification_service_channel_id))
.setSmallIcon(icon, level) .setContentTitle(title)
.setContentIntent(intent) .setContentText(message)
.setCategory(Notification.CATEGORY_SERVICE) .setSmallIcon(icon, level)
.setVisibility(Notification.VISIBILITY_SECRET) .setContentIntent(intent)
.setPriority(priority) .setCategory(Notification.CATEGORY_SERVICE)
.setWhen(System.currentTimeMillis()) .setVisibility(Notification.VISIBILITY_SECRET)
.setShowWhen(true) .setPriority(priority)
.setColor(context.getColor(R.color.notification_color_led)) .setWhen(System.currentTimeMillis())
.build(); .setShowWhen(true)
} .setColor(context.getColor(R.color.notification_color_led))
} .build();
}
}
public static Notification createMissedCallNotification(Context context, String title, String text, PendingIntent intent) { public static Notification createMissedCallNotification(
return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) Context context, String title, String text, PendingIntent intent) {
.setContentTitle(title) return new Notification.Builder(
.setContentText(text) context, context.getString(R.string.notification_channel_id))
.setSmallIcon(R.drawable.call_status_missed) .setContentTitle(title)
.setAutoCancel(true) .setContentText(text)
.setContentIntent(intent) .setSmallIcon(R.drawable.call_status_missed)
.setDefaults(Notification.DEFAULT_SOUND .setAutoCancel(true)
| Notification.DEFAULT_VIBRATE) .setContentIntent(intent)
.setCategory(Notification.CATEGORY_EVENT) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setVisibility(Notification.VISIBILITY_PRIVATE) .setCategory(Notification.CATEGORY_EVENT)
.setPriority(Notification.PRIORITY_HIGH) .setVisibility(Notification.VISIBILITY_PRIVATE)
.setWhen(System.currentTimeMillis()) .setPriority(Notification.PRIORITY_HIGH)
.setShowWhen(true) .setWhen(System.currentTimeMillis())
.setColor(context.getColor(R.color.notification_color_led)) .setShowWhen(true)
.build(); .setColor(context.getColor(R.color.notification_color_led))
} .build();
}
public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) { public static Notification createSimpleNotification(
return new Notification.Builder(context, context.getString(R.string.notification_channel_id)) Context context, String title, String text, PendingIntent intent) {
.setContentTitle(title) return new Notification.Builder(
.setContentText(text) context, context.getString(R.string.notification_channel_id))
.setSmallIcon(R.drawable.linphone_logo) .setContentTitle(title)
.setAutoCancel(true) .setContentText(text)
.setContentIntent(intent) .setSmallIcon(R.drawable.linphone_logo)
.setDefaults(Notification.DEFAULT_SOUND .setAutoCancel(true)
| Notification.DEFAULT_VIBRATE) .setContentIntent(intent)
.setCategory(Notification.CATEGORY_MESSAGE) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setVisibility(Notification.VISIBILITY_PRIVATE) .setCategory(Notification.CATEGORY_MESSAGE)
.setPriority(Notification.PRIORITY_HIGH) .setVisibility(Notification.VISIBILITY_PRIVATE)
.setWhen(System.currentTimeMillis()) .setPriority(Notification.PRIORITY_HIGH)
.setShowWhen(true) .setWhen(System.currentTimeMillis())
.setColorized(true) .setShowWhen(true)
.setColor(context.getColor(R.color.notification_color_led)) .setColorized(true)
.build(); .setColor(context.getColor(R.color.notification_color_led))
} .build();
}
public static void startService(Context context, Intent intent) { public static void startService(Context context, Intent intent) {
context.startForegroundService(intent); context.startForegroundService(intent);
} }
public static void setFragmentTransactionReorderingAllowed(FragmentTransaction transaction, boolean allowed) { public static void setFragmentTransactionReorderingAllowed(
transaction.setReorderingAllowed(allowed); FragmentTransaction transaction, boolean allowed) {
} transaction.setReorderingAllowed(allowed);
}
} }

View file

@ -27,7 +27,6 @@ import android.graphics.Bitmap;
import android.os.Build; import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.mediastream.Version; import org.linphone.mediastream.Version;
import org.linphone.notifications.Notifiable; import org.linphone.notifications.Notifiable;
@ -47,29 +46,39 @@ public class Compatibility {
} }
} }
public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) { public static Notification createSimpleNotification(
Context context, String title, String text, PendingIntent intent) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createSimpleNotification(context, title, text, intent); return ApiTwentySixPlus.createSimpleNotification(context, title, text, intent);
} }
return ApiTwentyOnePlus.createSimpleNotification(context, title, text, intent); return ApiTwentyOnePlus.createSimpleNotification(context, title, text, intent);
} }
public static Notification createMissedCallNotification(Context context, String title, String text, PendingIntent intent) { public static Notification createMissedCallNotification(
Context context, String title, String text, PendingIntent intent) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createMissedCallNotification(context, title, text, intent); return ApiTwentySixPlus.createMissedCallNotification(context, title, text, intent);
} }
return ApiTwentyOnePlus.createMissedCallNotification(context, title, text, intent); return ApiTwentyOnePlus.createMissedCallNotification(context, title, text, intent);
} }
public static Notification createMessageNotification(Context context, Notifiable notif, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) { public static Notification createMessageNotification(
Context context,
Notifiable notif,
String msgSender,
String msg,
Bitmap contactIcon,
PendingIntent intent) {
if (Version.sdkAboveOrEqual(28)) { if (Version.sdkAboveOrEqual(28)) {
return ApiTwentyEightPlus.createMessageNotification(context, notif, contactIcon, intent); return ApiTwentyEightPlus.createMessageNotification(
context, notif, contactIcon, intent);
} else if (Version.sdkAboveOrEqual(Version.API26_O_80)) { } else if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createMessageNotification(context, notif, contactIcon, intent); return ApiTwentySixPlus.createMessageNotification(context, notif, contactIcon, intent);
} else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) {
return ApiTwentyFourPlus.createMessageNotification(context, notif, contactIcon, intent); return ApiTwentyFourPlus.createMessageNotification(context, notif, contactIcon, intent);
} }
return ApiTwentyOnePlus.createMessageNotification(context, notif.getMessages().size(), msgSender, msg, contactIcon, intent); return ApiTwentyOnePlus.createMessageNotification(
context, notif.getMessages().size(), msgSender, msg, contactIcon, intent);
} }
public static Notification createRepliedNotification(Context context, String reply) { public static Notification createRepliedNotification(Context context, String reply) {
@ -81,20 +90,73 @@ public class Compatibility {
return null; return null;
} }
public static Notification createInCallNotification(Context context, int callId, boolean showAnswerAction, String title, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) { public static Notification createInCallNotification(
Context context,
int callId,
boolean showAnswerAction,
String title,
String msg,
int iconID,
Bitmap contactIcon,
String contactName,
PendingIntent intent) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createInCallNotification(context, callId, showAnswerAction, msg, iconID, contactIcon, contactName, intent); return ApiTwentySixPlus.createInCallNotification(
context,
callId,
showAnswerAction,
msg,
iconID,
contactIcon,
contactName,
intent);
} else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) { } else if (Version.sdkAboveOrEqual(Version.API24_NOUGAT_70)) {
return ApiTwentyFourPlus.createInCallNotification(context, callId, showAnswerAction, msg, iconID, contactIcon, contactName, intent); return ApiTwentyFourPlus.createInCallNotification(
context,
callId,
showAnswerAction,
msg,
iconID,
contactIcon,
contactName,
intent);
} }
return ApiTwentyOnePlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent); return ApiTwentyOnePlus.createInCallNotification(
context, title, msg, iconID, contactIcon, contactName, intent);
} }
public static Notification createNotification(Context context, String title, String message, int icon, int iconLevel, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent, int priority) { public static Notification createNotification(
Context context,
String title,
String message,
int icon,
int iconLevel,
Bitmap largeIcon,
PendingIntent intent,
boolean isOngoingEvent,
int priority) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
return ApiTwentySixPlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent, priority); return ApiTwentySixPlus.createNotification(
context,
title,
message,
icon,
iconLevel,
largeIcon,
intent,
isOngoingEvent,
priority);
} }
return ApiTwentyOnePlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent, priority); return ApiTwentyOnePlus.createNotification(
context,
title,
message,
icon,
iconLevel,
largeIcon,
intent,
isOngoingEvent,
priority);
} }
public static boolean canDrawOverlays(Context context) { public static boolean canDrawOverlays(Context context) {
@ -120,7 +182,8 @@ public class Compatibility {
} }
} }
public static void setFragmentTransactionReorderingAllowed(FragmentTransaction transaction, boolean allowed) { public static void setFragmentTransactionReorderingAllowed(
FragmentTransaction transaction, boolean allowed) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
ApiTwentySixPlus.setFragmentTransactionReorderingAllowed(transaction, allowed); ApiTwentySixPlus.setFragmentTransactionReorderingAllowed(transaction, allowed);
} }

View file

@ -25,7 +25,8 @@ import android.view.MotionEvent;
import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector;
@TargetApi(8) @TargetApi(8)
public class CompatibilityScaleGestureDetector extends ScaleGestureDetector.SimpleOnScaleGestureListener { public class CompatibilityScaleGestureDetector
extends ScaleGestureDetector.SimpleOnScaleGestureListener {
private ScaleGestureDetector detector; private ScaleGestureDetector detector;
private CompatibilityScaleGestureListener listener; private CompatibilityScaleGestureListener listener;
@ -58,4 +59,4 @@ public class CompatibilityScaleGestureDetector extends ScaleGestureDetector.Simp
listener = null; listener = null;
detector = null; detector = null;
} }
} }

View file

@ -21,4 +21,4 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
public interface CompatibilityScaleGestureListener { public interface CompatibilityScaleGestureListener {
public boolean onScale(CompatibilityScaleGestureDetector detector); public boolean onScale(CompatibilityScaleGestureDetector detector);
} }

View file

@ -20,13 +20,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.view.View; import android.view.View;
import java.io.Serializable;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Factory; import org.linphone.core.Factory;
import org.linphone.core.SearchResult; import org.linphone.core.SearchResult;
import java.io.Serializable;
public class ContactAddress implements Serializable { public class ContactAddress implements Serializable {
private LinphoneContact contact; private LinphoneContact contact;
private SearchResult result; private SearchResult result;
@ -37,6 +35,15 @@ public class ContactAddress implements Serializable {
private boolean isAdmin = false; private boolean isAdmin = false;
private transient View view; private transient View view;
public ContactAddress(LinphoneContact c, String a, String pn, boolean isLC) {
init(c, a, pn, isLC);
}
public ContactAddress(LinphoneContact c, String a, String pn, boolean isLC, boolean isAdmin) {
init(c, a, pn, isLC);
this.isAdmin = isAdmin;
}
public boolean isAdmin() { public boolean isAdmin() {
return isAdmin; return isAdmin;
} }
@ -49,14 +56,18 @@ public class ContactAddress implements Serializable {
return isSelect; return isSelect;
} }
public void setView(View v) { public void setSelect(boolean select) {
view = v; isSelect = select;
} }
public View getView() { public View getView() {
return view; return view;
} }
public void setView(View v) {
view = v;
}
public LinphoneContact getContact() { public LinphoneContact getContact() {
return contact; return contact;
} }
@ -76,7 +87,9 @@ public class ContactAddress implements Serializable {
} }
public Address getAddress() { public Address getAddress() {
String presence = contact.getPresenceModelForUriOrTel((phoneNumber != null && !phoneNumber.isEmpty()) ? phoneNumber : address); String presence =
contact.getPresenceModelForUriOrTel(
(phoneNumber != null && !phoneNumber.isEmpty()) ? phoneNumber : address);
Address addr = Factory.instance().createAddress(presence != null ? presence : address); Address addr = Factory.instance().createAddress(presence != null ? presence : address);
// Remove the user=phone URI param if existing, it will break everything otherwise // Remove the user=phone URI param if existing, it will break everything otherwise
if (addr.hasUriParam("user")) { if (addr.hasUriParam("user")) {
@ -109,10 +122,6 @@ public class ContactAddress implements Serializable {
return phoneNumber; return phoneNumber;
} }
public void setSelect(boolean select) {
isSelect = select;
}
public boolean isLinphoneContact() { public boolean isLinphoneContact() {
return isLinphoneContact; return isLinphoneContact;
} }
@ -124,22 +133,13 @@ public class ContactAddress implements Serializable {
isLinphoneContact = isLC; isLinphoneContact = isLC;
} }
public ContactAddress(LinphoneContact c, String a, String pn, boolean isLC) {
init(c, a, pn, isLC);
}
public ContactAddress(LinphoneContact c, String a, String pn, boolean isLC, boolean isAdmin) {
init(c, a, pn, isLC);
this.isAdmin = isAdmin;
}
@Override @Override
public boolean equals(Object other) { public boolean equals(Object other) {
if (other == null) return false; if (other == null) return false;
if (other == this) return true; if (other == this) return true;
if (!(other instanceof ContactAddress)) return false; if (!(other instanceof ContactAddress)) return false;
if (((ContactAddress) other).getAddressAsDisplayableString() == this.getAddressAsDisplayableString()) if (((ContactAddress) other).getAddressAsDisplayableString()
return true; == this.getAddressAsDisplayableString()) return true;
return false; return false;
} }
} }

View file

@ -25,7 +25,6 @@ import android.app.Fragment;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -35,13 +34,9 @@ import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TableLayout; import android.widget.TableLayout;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.ChatRoom; import org.linphone.core.ChatRoom;
import org.linphone.core.ChatRoomListenerStub; import org.linphone.core.ChatRoomListenerStub;
@ -52,6 +47,9 @@ import org.linphone.core.PresenceModel;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
public class ContactDetailsFragment extends Fragment implements OnClickListener { public class ContactDetailsFragment extends Fragment implements OnClickListener {
private LinphoneContact contact; private LinphoneContact contact;
@ -64,49 +62,68 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
private ChatRoom mChatRoom; private ChatRoom mChatRoom;
private ChatRoomListenerStub mChatRoomCreationListener; private ChatRoomListenerStub mChatRoomCreationListener;
private OnClickListener dialListener = new OnClickListener() { private OnClickListener dialListener =
@Override new OnClickListener() {
public void onClick(View v) { @Override
if (LinphoneActivity.isInstanciated()) { public void onClick(View v) {
String tag = (String) v.getTag(); if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().setAddresGoToDialerAndCall(tag, contact.getFullName(), contact.getPhotoUri()); String tag = (String) v.getTag();
} LinphoneActivity.instance()
} .setAddresGoToDialerAndCall(
}; tag, contact.getFullName(), contact.getPhotoUri());
}
}
};
private OnClickListener chatListener = new OnClickListener() { private OnClickListener chatListener =
@Override new OnClickListener() {
public void onClick(View v) { @Override
if (LinphoneActivity.isInstanciated()) { public void onClick(View v) {
String tag = (String) v.getTag(); if (LinphoneActivity.isInstanciated()) {
Core lc = LinphoneManager.getLc(); String tag = (String) v.getTag();
Address participant = Factory.instance().createAddress(tag); Core lc = LinphoneManager.getLc();
ProxyConfig defaultProxyConfig = lc.getDefaultProxyConfig(); Address participant = Factory.instance().createAddress(tag);
boolean isSecured = v.getId() == R.id.contact_chat_secured; ProxyConfig defaultProxyConfig = lc.getDefaultProxyConfig();
boolean isSecured = v.getId() == R.id.contact_chat_secured;
if (defaultProxyConfig != null) { if (defaultProxyConfig != null) {
ChatRoom room = lc.findOneToOneChatRoom(defaultProxyConfig.getContact(), participant, isSecured); ChatRoom room =
if (room != null) { lc.findOneToOneChatRoom(
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null); defaultProxyConfig.getContact(),
} else { participant,
if (defaultProxyConfig.getConferenceFactoryUri() != null && (isSecured || !LinphonePreferences.instance().useBasicChatRoomFor1To1())) { isSecured);
mWaitLayout.setVisibility(View.VISIBLE); if (room != null) {
mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), !isSecured, isSecured); LinphoneActivity.instance()
mChatRoom.addListener(mChatRoomCreationListener); .goToChat(room.getPeerAddress().asStringUriOnly(), null);
Address participants[] = new Address[1]; } else {
participants[0] = participant; if (defaultProxyConfig.getConferenceFactoryUri() != null
mChatRoom.addParticipants(participants); && (isSecured
} else { || !LinphonePreferences.instance()
room = lc.getChatRoom(participant); .useBasicChatRoomFor1To1())) {
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null); mWaitLayout.setVisibility(View.VISIBLE);
mChatRoom =
lc.createClientGroupChatRoom(
getString(R.string.dummy_group_chat_subject),
!isSecured,
isSecured);
mChatRoom.addListener(mChatRoomCreationListener);
Address participants[] = new Address[1];
participants[0] = participant;
mChatRoom.addParticipants(participants);
} else {
room = lc.getChatRoom(participant);
LinphoneActivity.instance()
.goToChat(
room.getPeerAddress().asStringUriOnly(), null);
}
}
} }
} }
} }
} };
}
};
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
contact = (LinphoneContact) getArguments().getSerializable("Contact"); contact = (LinphoneContact) getArguments().getSerializable("Contact");
this.inflater = inflater; this.inflater = inflater;
@ -141,19 +158,24 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
back.setOnClickListener(this); back.setOnClickListener(this);
} }
mChatRoomCreationListener = new ChatRoomListenerStub() { mChatRoomCreationListener =
@Override new ChatRoomListenerStub() {
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { @Override
if (newState == ChatRoom.State.Created) { public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
mWaitLayout.setVisibility(View.GONE); if (newState == ChatRoom.State.Created) {
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), null); mWaitLayout.setVisibility(View.GONE);
} else if (newState == ChatRoom.State.CreationFailed) { LinphoneActivity.instance()
mWaitLayout.setVisibility(View.GONE); .goToChat(cr.getPeerAddress().asStringUriOnly(), null);
LinphoneActivity.instance().displayChatRoomError(); } else if (newState == ChatRoom.State.CreationFailed) {
Log.e("Group chat room for address " + cr.getPeerAddress() + " has failed !"); mWaitLayout.setVisibility(View.GONE);
} LinphoneActivity.instance().displayChatRoomError();
} Log.e(
}; "Group chat room for address "
+ cr.getPeerAddress()
+ " has failed !");
}
}
};
return view; return view;
} }
@ -175,7 +197,11 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
private void displayContact(LayoutInflater inflater, View view) { private void displayContact(LayoutInflater inflater, View view) {
ImageView contactPicture = view.findViewById(R.id.contact_picture); ImageView contactPicture = view.findViewById(R.id.contact_picture);
if (contact.hasPhoto()) { if (contact.hasPhoto()) {
ImageUtils.setImagePictureFromUri(getActivity(), contactPicture, contact.getPhotoUri(), contact.getThumbnailUri()); ImageUtils.setImagePictureFromUri(
getActivity(),
contactPicture,
contact.getPhotoUri(),
contact.getThumbnailUri());
} else { } else {
contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap()); contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap());
} }
@ -191,7 +217,8 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
View v = inflater.inflate(R.layout.contact_control_row, null); View v = inflater.inflate(R.layout.contact_control_row, null);
String value = noa.getValue(); String value = noa.getValue();
String displayednumberOrAddress = LinphoneUtils.getDisplayableUsernameFromAddress(value); String displayednumberOrAddress =
LinphoneUtils.getDisplayableUsernameFromAddress(value);
TextView label = v.findViewById(R.id.address_label); TextView label = v.findViewById(R.id.address_label);
if (noa.isSIPAddress()) { if (noa.isSIPAddress()) {
@ -206,7 +233,6 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
tv.setText(displayednumberOrAddress); tv.setText(displayednumberOrAddress);
tv.setSelected(true); tv.setSelected(true);
ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
if (lpc != null) { if (lpc != null) {
String username = lpc.normalizePhoneNumber(displayednumberOrAddress); String username = lpc.normalizePhoneNumber(displayednumberOrAddress);
@ -221,27 +247,32 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) { if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
v.findViewById(R.id.friendLinphone).setVisibility(View.VISIBLE); v.findViewById(R.id.friendLinphone).setVisibility(View.VISIBLE);
} else { } else {
if (getResources().getBoolean(R.bool.hide_numbers_and_addresses_without_presence)) { if (getResources()
.getBoolean(R.bool.hide_numbers_and_addresses_without_presence)) {
skip = true; skip = true;
} }
} }
} }
v.findViewById(R.id.inviteFriend).setVisibility(View.GONE); v.findViewById(R.id.inviteFriend).setVisibility(View.GONE);
if (!noa.isSIPAddress() && v.findViewById(R.id.friendLinphone).getVisibility() == View.GONE) { if (!noa.isSIPAddress()
&& v.findViewById(R.id.friendLinphone).getVisibility() == View.GONE) {
v.findViewById(R.id.inviteFriend).setVisibility(View.VISIBLE); v.findViewById(R.id.inviteFriend).setVisibility(View.VISIBLE);
v.findViewById(R.id.inviteFriend).setTag(noa.getNormalizedPhone()); v.findViewById(R.id.inviteFriend).setTag(noa.getNormalizedPhone());
v.findViewById(R.id.inviteFriend).setOnClickListener(new OnClickListener() { v.findViewById(R.id.inviteFriend)
@Override .setOnClickListener(
public void onClick(View v) { new OnClickListener() {
String number = (String)v.getTag(); @Override
Intent smsIntent = new Intent(Intent.ACTION_SENDTO); public void onClick(View v) {
smsIntent.putExtra("address", number); String number = (String) v.getTag();
smsIntent.setData(Uri.parse("smsto:" + number)); Intent smsIntent = new Intent(Intent.ACTION_SENDTO);
smsIntent.putExtra("sms_body", getString(R.string.invite_friend_text)); smsIntent.putExtra("address", number);
startActivity(smsIntent); smsIntent.setData(Uri.parse("smsto:" + number));
} smsIntent.putExtra(
}); "sms_body", getString(R.string.invite_friend_text));
startActivity(smsIntent);
}
});
} }
String contactAddress = contact.getPresenceModelForUriOrTel(noa.getValue()); String contactAddress = contact.getPresenceModelForUriOrTel(noa.getValue());
@ -266,8 +297,8 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
v.findViewById(R.id.contact_chat_secured).setTag(value); v.findViewById(R.id.contact_chat_secured).setTag(value);
} }
if (v.findViewById(R.id.friendLinphone).getVisibility()
if (v.findViewById(R.id.friendLinphone).getVisibility() == View.VISIBLE /* TODO Does contact have LIME capability ?*/ == View.VISIBLE /* TODO Does contact have LIME capability ?*/
&& lpc.getConferenceFactoryUri() != null) { && lpc.getConferenceFactoryUri() != null) {
v.findViewById(R.id.contact_chat_secured).setVisibility(View.VISIBLE); v.findViewById(R.id.contact_chat_secured).setVisibility(View.VISIBLE);
} else { } else {
@ -303,26 +334,28 @@ public class ContactDetailsFragment extends Fragment implements OnClickListener
if (id == R.id.editContact) { if (id == R.id.editContact) {
ContactsManager.getInstance().editContact(getActivity(), contact, null); ContactsManager.getInstance().editContact(getActivity(), contact, null);
} else if (id == R.id.deleteContact) { } else if (id == R.id.deleteContact) {
final Dialog dialog = LinphoneActivity.instance().displayDialog(getString(R.string.delete_text)); final Dialog dialog =
LinphoneActivity.instance().displayDialog(getString(R.string.delete_text));
Button delete = dialog.findViewById(R.id.dialog_delete_button); Button delete = dialog.findViewById(R.id.dialog_delete_button);
Button cancel = dialog.findViewById(R.id.dialog_cancel_button); Button cancel = dialog.findViewById(R.id.dialog_cancel_button);
delete.setOnClickListener(new OnClickListener() { delete.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
contact.delete(); public void onClick(View view) {
LinphoneActivity.instance().displayContacts(false); contact.delete();
dialog.dismiss(); LinphoneActivity.instance().displayContacts(false);
} dialog.dismiss();
}); }
});
cancel.setOnClickListener(new OnClickListener() { cancel.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
dialog.dismiss(); public void onClick(View view) {
dialog.dismiss();
} }
}); });
dialog.show(); dialog.show();
} else if (id == R.id.back) { } else if (id == R.id.back) {
getFragmentManager().popBackStackImmediate(); getFragmentManager().popBackStackImmediate();

View file

@ -1,23 +1,23 @@
package org.linphone.contacts; package org.linphone.contacts;
/* /*
ContactEditorFragment.java ContactEditorFragment.java
Copyright (C) 2017 Belledonne Communications, Grenoble, France Copyright (C) 2017 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
@ -46,34 +46,30 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import org.linphone.LinphoneManager;
import org.linphone.utils.FileUtils;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version;
import org.linphone.utils.FileUtils;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
public class ContactEditorFragment extends Fragment { public class ContactEditorFragment extends Fragment {
private static final int ADD_PHOTO = 1337;
private static final int PHOTO_SIZE = 128;
private View view; private View view;
private ImageView cancel, deleteContact, ok; private ImageView cancel, deleteContact, ok;
private ImageView addNumber, addSipAddress, contactPicture; private ImageView addNumber, addSipAddress, contactPicture;
private LinearLayout phoneNumbersSection, sipAddressesSection; private LinearLayout phoneNumbersSection, sipAddressesSection;
private EditText firstName, lastName, organization; private EditText firstName, lastName, organization;
private LayoutInflater inflater; private LayoutInflater inflater;
private static final int ADD_PHOTO = 1337;
private static final int PHOTO_SIZE = 128;
private boolean isNewContact; private boolean isNewContact;
private LinphoneContact contact; private LinphoneContact contact;
private List<LinphoneNumberOrAddress> numbersAndAddresses; private List<LinphoneNumberOrAddress> numbersAndAddresses;
@ -83,7 +79,8 @@ public class ContactEditorFragment extends Fragment {
private Uri pickedPhotoForContactUri; private Uri pickedPhotoForContactUri;
private byte[] photoToAdd; private byte[] photoToAdd;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.inflater = inflater; this.inflater = inflater;
contact = null; contact = null;
@ -111,8 +108,9 @@ public class ContactEditorFragment extends Fragment {
view = inflater.inflate(R.layout.contact_edit, container, false); view = inflater.inflate(R.layout.contact_edit, container, false);
phoneNumbersSection = view.findViewById(R.id.phone_numbers); phoneNumbersSection = view.findViewById(R.id.phone_numbers);
if (getResources().getBoolean(R.bool.hide_phone_numbers_in_editor) || !ContactsManager.getInstance().hasContactsAccess()) { if (getResources().getBoolean(R.bool.hide_phone_numbers_in_editor)
//Currently linphone friends don't support phone numbers, so hide them || !ContactsManager.getInstance().hasContactsAccess()) {
// Currently linphone friends don't support phone numbers, so hide them
phoneNumbersSection.setVisibility(View.GONE); phoneNumbersSection.setVisibility(View.GONE);
} }
@ -124,97 +122,106 @@ public class ContactEditorFragment extends Fragment {
deleteContact = view.findViewById(R.id.delete_contact); deleteContact = view.findViewById(R.id.delete_contact);
cancel = view.findViewById(R.id.cancel); cancel = view.findViewById(R.id.cancel);
cancel.setOnClickListener(new OnClickListener() { cancel.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
getFragmentManager().popBackStackImmediate(); public void onClick(View v) {
} getFragmentManager().popBackStackImmediate();
}); }
});
ok = view.findViewById(R.id.ok); ok = view.findViewById(R.id.ok);
ok.setOnClickListener(new OnClickListener() { ok.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
if (isNewContact) { public void onClick(View v) {
boolean areAllFielsEmpty = true; if (isNewContact) {
for (LinphoneNumberOrAddress nounoa : numbersAndAddresses) { boolean areAllFielsEmpty = true;
if (nounoa.getValue() != null && !nounoa.getValue().equals("")) { for (LinphoneNumberOrAddress nounoa : numbersAndAddresses) {
areAllFielsEmpty = false; if (nounoa.getValue() != null && !nounoa.getValue().equals("")) {
break; areAllFielsEmpty = false;
break;
}
}
if (areAllFielsEmpty) {
getFragmentManager().popBackStackImmediate();
return;
}
contact = LinphoneContact.createContact();
} }
} contact.setFirstNameAndLastName(
if (areAllFielsEmpty) { firstName.getText().toString(),
lastName.getText().toString(),
true);
if (photoToAdd != null) {
contact.setPhoto(photoToAdd);
}
for (LinphoneNumberOrAddress noa : numbersAndAddresses) {
if (noa.isSIPAddress() && noa.getValue() != null) {
noa.setValue(
LinphoneUtils.getFullAddressFromUsername(noa.getValue()));
}
contact.addOrUpdateNumberOrAddress(noa);
}
contact.setOrganization(organization.getText().toString(), true);
contact.save();
getFragmentManager().popBackStackImmediate(); getFragmentManager().popBackStackImmediate();
return;
} }
contact = LinphoneContact.createContact(); });
}
contact.setFirstNameAndLastName(firstName.getText().toString(), lastName.getText().toString(), true);
if (photoToAdd != null) {
contact.setPhoto(photoToAdd);
}
for (LinphoneNumberOrAddress noa : numbersAndAddresses) {
if (noa.isSIPAddress() && noa.getValue() != null) {
noa.setValue(LinphoneUtils.getFullAddressFromUsername(noa.getValue()));
}
contact.addOrUpdateNumberOrAddress(noa);
}
contact.setOrganization(organization.getText().toString(), true);
contact.save();
getFragmentManager().popBackStackImmediate();
}
});
lastName = view.findViewById(R.id.contactLastName); lastName = view.findViewById(R.id.contactLastName);
// Hack to display keyboard when touching focused edittext on Nexus One // Hack to display keyboard when touching focused edittext on Nexus One
if (Version.sdkStrictlyBelow(Version.API11_HONEYCOMB_30)) { if (Version.sdkStrictlyBelow(Version.API11_HONEYCOMB_30)) {
lastName.setOnClickListener(new OnClickListener() { lastName.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
InputMethodManager imm = (InputMethodManager) LinphoneActivity.instance().getSystemService(Context.INPUT_METHOD_SERVICE); public void onClick(View v) {
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); InputMethodManager imm =
} (InputMethodManager)
}); LinphoneActivity.instance()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
});
} }
lastName.addTextChangedListener(new TextWatcher() { lastName.addTextChangedListener(
@Override new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) { @Override
if (lastName.getText().length() > 0 || firstName.getText().length() > 0) { public void onTextChanged(CharSequence s, int start, int before, int count) {
ok.setEnabled(true); if (lastName.getText().length() > 0 || firstName.getText().length() > 0) {
} else { ok.setEnabled(true);
ok.setEnabled(false); } else {
} ok.setEnabled(false);
} }
}
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
} });
});
firstName = view.findViewById(R.id.contactFirstName); firstName = view.findViewById(R.id.contactFirstName);
firstName.addTextChangedListener(new TextWatcher() { firstName.addTextChangedListener(
@Override new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) { @Override
if (firstName.getText().length() > 0 || lastName.getText().length() > 0) { public void onTextChanged(CharSequence s, int start, int before, int count) {
ok.setEnabled(true); if (firstName.getText().length() > 0 || lastName.getText().length() > 0) {
} else { ok.setEnabled(true);
ok.setEnabled(false); } else {
} ok.setEnabled(false);
} }
}
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
@Override
public void afterTextChanged(Editable s) {
}
});
@Override
public void afterTextChanged(Editable s) {}
});
organization = view.findViewById(R.id.contactOrganization); organization = view.findViewById(R.id.contactOrganization);
boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization); boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization);
@ -238,50 +245,59 @@ public class ContactEditorFragment extends Fragment {
firstName.setText(""); firstName.setText("");
} }
deleteContact.setOnClickListener(new OnClickListener() { deleteContact.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) {
final Dialog dialog = LinphoneActivity.instance().displayDialog(getString(R.string.delete_text));
Button delete = dialog.findViewById(R.id.dialog_delete_button);
Button cancel = dialog.findViewById(R.id.dialog_cancel_button);
delete.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View v) {
contact.delete(); final Dialog dialog =
LinphoneActivity.instance().displayContacts(false); LinphoneActivity.instance()
dialog.dismiss(); .displayDialog(getString(R.string.delete_text));
Button delete = dialog.findViewById(R.id.dialog_delete_button);
Button cancel = dialog.findViewById(R.id.dialog_cancel_button);
delete.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View view) {
contact.delete();
LinphoneActivity.instance().displayContacts(false);
dialog.dismiss();
}
});
cancel.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.show();
} }
}); });
cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.show();
}
});
} else { } else {
deleteContact.setVisibility(View.INVISIBLE); deleteContact.setVisibility(View.INVISIBLE);
} }
contactPicture = view.findViewById(R.id.contact_picture); contactPicture = view.findViewById(R.id.contact_picture);
if (contact != null) { if (contact != null) {
ImageUtils.setImagePictureFromUri(getActivity(), contactPicture, contact.getPhotoUri(), contact.getThumbnailUri()); ImageUtils.setImagePictureFromUri(
getActivity(),
contactPicture,
contact.getPhotoUri(),
contact.getThumbnailUri());
} else { } else {
contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap()); contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap());
} }
contactPicture.setOnClickListener(new OnClickListener() { contactPicture.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
pickImage(); public void onClick(View view) {
LinphoneActivity.instance().checkAndRequestCameraPermission(); pickImage();
} LinphoneActivity.instance().checkAndRequestCameraPermission();
}); }
});
numbersAndAddresses = new ArrayList<>(); numbersAndAddresses = new ArrayList<>();
sipAddresses = initSipAddressFields(contact); sipAddresses = initSipAddressFields(contact);
@ -291,23 +307,25 @@ public class ContactEditorFragment extends Fragment {
if (getResources().getBoolean(R.bool.allow_only_one_sip_address)) { if (getResources().getBoolean(R.bool.allow_only_one_sip_address)) {
addSipAddress.setVisibility(View.GONE); addSipAddress.setVisibility(View.GONE);
} }
addSipAddress.setOnClickListener(new OnClickListener() { addSipAddress.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
addEmptyRowToAllowNewNumberOrAddress(sipAddresses, true); public void onClick(View view) {
} addEmptyRowToAllowNewNumberOrAddress(sipAddresses, true);
}); }
});
addNumber = view.findViewById(R.id.add_number_field); addNumber = view.findViewById(R.id.add_number_field);
if (getResources().getBoolean(R.bool.allow_only_one_phone_number)) { if (getResources().getBoolean(R.bool.allow_only_one_phone_number)) {
addNumber.setVisibility(View.GONE); addNumber.setVisibility(View.GONE);
} }
addNumber.setOnClickListener(new OnClickListener() { addNumber.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
addEmptyRowToAllowNewNumberOrAddress(numbers, false); public void onClick(View view) {
} addEmptyRowToAllowNewNumberOrAddress(numbers, false);
}); }
});
lastName.requestFocus(); lastName.requestFocus();
@ -318,17 +336,21 @@ public class ContactEditorFragment extends Fragment {
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (LinphoneActivity.isInstanciated()) { if (LinphoneActivity.isInstanciated()) {}
}
// Force hide keyboard // Force hide keyboard
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); getActivity()
.getWindow()
.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
} }
@Override @Override
public void onPause() { public void onPause() {
// Force hide keyboard // Force hide keyboard
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm =
(InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
View view = getActivity().getCurrentFocus(); View view = getActivity().getCurrentFocus();
if (imm != null && view != null) { if (imm != null && view != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0); imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
@ -341,7 +363,10 @@ public class ContactEditorFragment extends Fragment {
pickedPhotoForContactUri = null; pickedPhotoForContactUri = null;
final List<Intent> cameraIntents = new ArrayList<>(); final List<Intent> cameraIntents = new ArrayList<>();
final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(FileUtils.getStorageDirectory(LinphoneActivity.instance()), getString(R.string.temp_photo_name)); File file =
new File(
FileUtils.getStorageDirectory(LinphoneActivity.instance()),
getString(R.string.temp_photo_name));
pickedPhotoForContactUri = Uri.fromFile(file); pickedPhotoForContactUri = Uri.fromFile(file);
captureIntent.putExtra("outputX", PHOTO_SIZE); captureIntent.putExtra("outputX", PHOTO_SIZE);
captureIntent.putExtra("outputY", PHOTO_SIZE); captureIntent.putExtra("outputY", PHOTO_SIZE);
@ -356,8 +381,10 @@ public class ContactEditorFragment extends Fragment {
galleryIntent.setType("image/*"); galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT); galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.image_picker_title)); final Intent chooserIntent =
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); Intent.createChooser(galleryIntent, getString(R.string.image_picker_title));
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {}));
startActivityForResult(chooserIntent, ADD_PHOTO); startActivityForResult(chooserIntent, ADD_PHOTO);
} }
@ -371,8 +398,12 @@ public class ContactEditorFragment extends Fragment {
} else if (data != null && data.getData() != null) { } else if (data != null && data.getData() != null) {
Uri selectedImageUri = data.getData(); Uri selectedImageUri = data.getData();
try { try {
Bitmap selectedImage = MediaStore.Images.Media.getBitmap(LinphoneManager.getInstance().getContext().getContentResolver(), selectedImageUri); Bitmap selectedImage =
selectedImage = Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false); MediaStore.Images.Media.getBitmap(
LinphoneManager.getInstance().getContext().getContentResolver(),
selectedImageUri);
selectedImage =
Bitmap.createScaledBitmap(selectedImage, PHOTO_SIZE, PHOTO_SIZE, false);
editContactPicture(null, selectedImage); editContactPicture(null, selectedImage);
} catch (IOException e) { } catch (IOException e) {
Log.e(e); Log.e(e);
@ -381,7 +412,10 @@ public class ContactEditorFragment extends Fragment {
String filePath = pickedPhotoForContactUri.getPath(); String filePath = pickedPhotoForContactUri.getPath();
editContactPicture(filePath, null); editContactPicture(filePath, null);
} else { } else {
File file = new File(FileUtils.getStorageDirectory(LinphoneActivity.instance()), getString(R.string.temp_photo_name)); File file =
new File(
FileUtils.getStorageDirectory(LinphoneActivity.instance()),
getString(R.string.temp_photo_name));
if (file.exists()) { if (file.exists()) {
pickedPhotoForContactUri = Uri.fromFile(file); pickedPhotoForContactUri = Uri.fromFile(file);
String filePath = pickedPhotoForContactUri.getPath(); String filePath = pickedPhotoForContactUri.getPath();
@ -415,7 +449,15 @@ public class ContactEditorFragment extends Fragment {
private int getThumbnailSize() { private int getThumbnailSize() {
int value = -1; int value = -1;
Cursor c = LinphoneActivity.instance().getContentResolver().query(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI, new String[]{DisplayPhoto.THUMBNAIL_MAX_DIM}, null, null, null); Cursor c =
LinphoneActivity.instance()
.getContentResolver()
.query(
DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
new String[] {DisplayPhoto.THUMBNAIL_MAX_DIM},
null,
null,
null);
try { try {
c.moveToFirst(); c.moveToFirst();
value = c.getInt(0); value = c.getInt(0);
@ -433,25 +475,24 @@ public class ContactEditorFragment extends Fragment {
for (LinphoneNumberOrAddress numberOrAddress : contact.getNumbersOrAddresses()) { for (LinphoneNumberOrAddress numberOrAddress : contact.getNumbersOrAddresses()) {
if (!numberOrAddress.isSIPAddress()) { if (!numberOrAddress.isSIPAddress()) {
View view = displayNumberOrAddress(controls, numberOrAddress.getValue(), false); View view = displayNumberOrAddress(controls, numberOrAddress.getValue(), false);
if (view != null) if (view != null) controls.addView(view);
controls.addView(view);
} }
} }
} }
if (newSipOrNumberToAdd != null) { if (newSipOrNumberToAdd != null) {
boolean isSip = LinphoneUtils.isStrictSipAddress(newSipOrNumberToAdd) || !LinphoneUtils.isNumberAddress(newSipOrNumberToAdd); boolean isSip =
LinphoneUtils.isStrictSipAddress(newSipOrNumberToAdd)
|| !LinphoneUtils.isNumberAddress(newSipOrNumberToAdd);
if (!isSip) { if (!isSip) {
View view = displayNumberOrAddress(controls, newSipOrNumberToAdd, false); View view = displayNumberOrAddress(controls, newSipOrNumberToAdd, false);
if (view != null) if (view != null) controls.addView(view);
controls.addView(view);
} }
} }
if (newDisplayName != null) { if (newDisplayName != null) {
EditText lastNameEditText = view.findViewById(R.id.contactLastName); EditText lastNameEditText = view.findViewById(R.id.contactLastName);
if (view != null) if (view != null) lastNameEditText.setText(newDisplayName);
lastNameEditText.setText(newDisplayName);
} }
if (controls.getChildCount() == 0) { if (controls.getChildCount() == 0) {
@ -469,18 +510,18 @@ public class ContactEditorFragment extends Fragment {
for (LinphoneNumberOrAddress numberOrAddress : contact.getNumbersOrAddresses()) { for (LinphoneNumberOrAddress numberOrAddress : contact.getNumbersOrAddresses()) {
if (numberOrAddress.isSIPAddress()) { if (numberOrAddress.isSIPAddress()) {
View view = displayNumberOrAddress(controls, numberOrAddress.getValue(), true); View view = displayNumberOrAddress(controls, numberOrAddress.getValue(), true);
if (view != null) if (view != null) controls.addView(view);
controls.addView(view);
} }
} }
} }
if (newSipOrNumberToAdd != null) { if (newSipOrNumberToAdd != null) {
boolean isSip = LinphoneUtils.isStrictSipAddress(newSipOrNumberToAdd) || !LinphoneUtils.isNumberAddress(newSipOrNumberToAdd); boolean isSip =
LinphoneUtils.isStrictSipAddress(newSipOrNumberToAdd)
|| !LinphoneUtils.isNumberAddress(newSipOrNumberToAdd);
if (isSip) { if (isSip) {
View view = displayNumberOrAddress(controls, newSipOrNumberToAdd, true); View view = displayNumberOrAddress(controls, newSipOrNumberToAdd, true);
if (view != null) if (view != null) controls.addView(view);
controls.addView(view);
} }
} }
@ -491,24 +532,31 @@ public class ContactEditorFragment extends Fragment {
return controls; return controls;
} }
private View displayNumberOrAddress(final LinearLayout controls, String numberOrAddress, boolean isSIP) { private View displayNumberOrAddress(
final LinearLayout controls, String numberOrAddress, boolean isSIP) {
return displayNumberOrAddress(controls, numberOrAddress, isSIP, false); return displayNumberOrAddress(controls, numberOrAddress, isSIP, false);
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
private View displayNumberOrAddress(final LinearLayout controls, String numberOrAddress, boolean isSIP, boolean forceAddNumber) { private View displayNumberOrAddress(
final LinearLayout controls,
String numberOrAddress,
boolean isSIP,
boolean forceAddNumber) {
String displayNumberOrAddress = numberOrAddress; String displayNumberOrAddress = numberOrAddress;
if (isSIP) { if (isSIP) {
if (firstSipAddressIndex == -1) { if (firstSipAddressIndex == -1) {
firstSipAddressIndex = controls.getChildCount(); firstSipAddressIndex = controls.getChildCount();
} }
displayNumberOrAddress = LinphoneUtils.getDisplayableUsernameFromAddress(numberOrAddress); displayNumberOrAddress =
LinphoneUtils.getDisplayableUsernameFromAddress(numberOrAddress);
} }
if ((getResources().getBoolean(R.bool.hide_phone_numbers_in_editor) && !isSIP) || (getResources().getBoolean(R.bool.hide_sip_addresses_in_editor) && isSIP)) { if ((getResources().getBoolean(R.bool.hide_phone_numbers_in_editor) && !isSIP)
|| (getResources().getBoolean(R.bool.hide_sip_addresses_in_editor) && isSIP)) {
if (forceAddNumber) if (forceAddNumber)
isSIP = !isSIP; // If number can't be displayed because we hide a sort of number, change that category isSIP = !isSIP; // If number can't be displayed because we hide a sort of number,
else // change that category
return null; else return null;
} }
LinphoneNumberOrAddress tempNounoa; LinphoneNumberOrAddress tempNounoa;
@ -531,44 +579,46 @@ public class ContactEditorFragment extends Fragment {
noa.setInputType(InputType.TYPE_CLASS_PHONE); noa.setInputType(InputType.TYPE_CLASS_PHONE);
} }
noa.setText(displayNumberOrAddress); noa.setText(displayNumberOrAddress);
noa.addTextChangedListener(new TextWatcher() { noa.addTextChangedListener(
@Override new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) { @Override
nounoa.setValue(noa.getText().toString()); public void onTextChanged(CharSequence s, int start, int before, int count) {
} nounoa.setValue(noa.getText().toString());
}
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
} });
});
if (forceAddNumber) { if (forceAddNumber) {
nounoa.setValue(noa.getText().toString()); nounoa.setValue(noa.getText().toString());
} }
ImageView delete = view.findViewById(R.id.delete_field); ImageView delete = view.findViewById(R.id.delete_field);
if ((getResources().getBoolean(R.bool.allow_only_one_phone_number) && !isSIP) || (getResources().getBoolean(R.bool.allow_only_one_sip_address) && isSIP)) { if ((getResources().getBoolean(R.bool.allow_only_one_phone_number) && !isSIP)
|| (getResources().getBoolean(R.bool.allow_only_one_sip_address) && isSIP)) {
delete.setVisibility(View.GONE); delete.setVisibility(View.GONE);
} }
delete.setOnClickListener(new OnClickListener() { delete.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
if (contact != null) { public void onClick(View v) {
contact.removeNumberOrAddress(nounoa); if (contact != null) {
} contact.removeNumberOrAddress(nounoa);
numbersAndAddresses.remove(nounoa); }
view.setVisibility(View.GONE); numbersAndAddresses.remove(nounoa);
view.setVisibility(View.GONE);
} }
}); });
return view; return view;
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
private void addEmptyRowToAllowNewNumberOrAddress(final LinearLayout controls, final boolean isSip) { private void addEmptyRowToAllowNewNumberOrAddress(
final LinearLayout controls, final boolean isSip) {
final View view = inflater.inflate(R.layout.contact_edit_row, null); final View view = inflater.inflate(R.layout.contact_edit_row, null);
final LinphoneNumberOrAddress nounoa = new LinphoneNumberOrAddress(null, isSip); final LinphoneNumberOrAddress nounoa = new LinphoneNumberOrAddress(null, isSip);
@ -579,33 +629,35 @@ public class ContactEditorFragment extends Fragment {
noa.setInputType(InputType.TYPE_CLASS_PHONE); noa.setInputType(InputType.TYPE_CLASS_PHONE);
} }
noa.requestFocus(); noa.requestFocus();
noa.addTextChangedListener(new TextWatcher() { noa.addTextChangedListener(
@Override new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) { @Override
nounoa.setValue(noa.getText().toString()); public void onTextChanged(CharSequence s, int start, int before, int count) {
} nounoa.setValue(noa.getText().toString());
}
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(
} CharSequence s, int start, int count, int after) {}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
} });
});
final ImageView delete = view.findViewById(R.id.delete_field); final ImageView delete = view.findViewById(R.id.delete_field);
if ((getResources().getBoolean(R.bool.allow_only_one_phone_number) && !isSip) || (getResources().getBoolean(R.bool.allow_only_one_sip_address) && isSip)) { if ((getResources().getBoolean(R.bool.allow_only_one_phone_number) && !isSip)
|| (getResources().getBoolean(R.bool.allow_only_one_sip_address) && isSip)) {
delete.setVisibility(View.GONE); delete.setVisibility(View.GONE);
} }
delete.setOnClickListener(new OnClickListener() { delete.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
numbersAndAddresses.remove(nounoa); public void onClick(View v) {
view.setVisibility(View.GONE); numbersAndAddresses.remove(nounoa);
} view.setVisibility(View.GONE);
}); }
});
controls.addView(view); controls.addView(view);
} }
} }

View file

@ -1,21 +1,21 @@
/* /*
ContactPicked.java ContactPicked.java
Copyright (C) 2017 Belledonne Communications, Grenoble, France Copyright (C) 2017 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
package org.linphone.contacts; package org.linphone.contacts;
@ -23,4 +23,4 @@ import android.net.Uri;
public interface ContactPicked { public interface ContactPicked {
void setAddresGoToDialerAndCall(String number, String name, Uri photo); void setAddresGoToDialerAndCall(String number, String name, Uri photo);
} }

View file

@ -1,27 +1,25 @@
package org.linphone.contacts; package org.linphone.contacts;
/* /*
ContactsListAdapter.java ContactsListAdapter.java
Copyright (C) 2018 Belledonne Communications, Grenoble, France Copyright (C) 2018 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -31,67 +29,20 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.SectionIndexer; import android.widget.SectionIndexer;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import org.linphone.R; import androidx.recyclerview.widget.RecyclerView;
import org.linphone.views.ContactAvatar;
import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.linphone.R;
import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper;
import org.linphone.views.ContactAvatar;
public class ContactsListAdapter extends SelectableAdapter<ContactsListAdapter.ViewHolder> implements SectionIndexer { public class ContactsListAdapter extends SelectableAdapter<ContactsListAdapter.ViewHolder>
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { implements SectionIndexer {
public CheckBox delete;
public ImageView linphoneFriend;
public TextView name;
public LinearLayout separator;
public TextView separatorText;
public RelativeLayout avatarLayout;
public TextView organization;
//public ImageView friendStatus;
private ClickListener mListener;
private ViewHolder(View view, ClickListener listener) {
super(view);
delete = view.findViewById(R.id.delete);
linphoneFriend = view.findViewById(R.id.friendLinphone);
name = view.findViewById(R.id.name);
separator = view.findViewById(R.id.separator);
separatorText = view.findViewById(R.id.separator_text);
avatarLayout = view.findViewById(R.id.avatar_layout);
organization = view.findViewById(R.id.contactOrganization);
//friendStatus = view.findViewById(R.id.friendStatus);
mListener = listener;
view.setOnClickListener(this);
view.setOnLongClickListener(this);
}
@Override
public void onClick(View view) {
if (mListener != null) {
mListener.onItemClicked(getAdapterPosition());
}
}
public boolean onLongClick(View v) {
if (mListener != null) {
return mListener.onItemLongClicked(getAdapterPosition());
}
return false;
}
public interface ClickListener {
void onItemClicked(int position);
boolean onItemLongClicked(int position);
}
}
private List<LinphoneContact> mContacts; private List<LinphoneContact> mContacts;
private String[] mSections; private String[] mSections;
private ArrayList<String> mSectionsList; private ArrayList<String> mSectionsList;
@ -100,7 +51,11 @@ public class ContactsListAdapter extends SelectableAdapter<ContactsListAdapter.V
private Context mContext; private Context mContext;
private boolean mIsSearchMode; private boolean mIsSearchMode;
ContactsListAdapter(Context context, List<LinphoneContact> contactsList, ViewHolder.ClickListener clickListener, SelectableHelper helper) { ContactsListAdapter(
Context context,
List<LinphoneContact> contactsList,
ViewHolder.ClickListener clickListener,
SelectableHelper helper) {
super(helper); super(helper);
mContext = context; mContext = context;
updateDataSet(contactsList); updateDataSet(contactsList);
@ -110,7 +65,9 @@ public class ContactsListAdapter extends SelectableAdapter<ContactsListAdapter.V
@NonNull @NonNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.contact_cell, parent, false); View v =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.contact_cell, parent, false);
return new ViewHolder(v, mClickListener); return new ViewHolder(v, mClickListener);
} }
@ -126,12 +83,19 @@ public class ContactsListAdapter extends SelectableAdapter<ContactsListAdapter.V
holder.separatorText.setText(String.valueOf(fullName.charAt(0))); holder.separatorText.setText(String.valueOf(fullName.charAt(0)));
} }
} }
holder.separator.setVisibility(mIsSearchMode || (!mIsSearchMode && getPositionForSection(getSectionForPosition(position)) != position) ? View.GONE : View.VISIBLE); holder.separator.setVisibility(
mIsSearchMode
|| (!mIsSearchMode
&& getPositionForSection(getSectionForPosition(position))
!= position)
? View.GONE
: View.VISIBLE);
holder.linphoneFriend.setVisibility(contact.isInFriendList() ? View.VISIBLE : View.GONE); holder.linphoneFriend.setVisibility(contact.isInFriendList() ? View.VISIBLE : View.GONE);
ContactAvatar.displayAvatar(contact, holder.avatarLayout); ContactAvatar.displayAvatar(contact, holder.avatarLayout);
boolean isOrgVisible = mContext.getResources().getBoolean(R.bool.display_contact_organization); boolean isOrgVisible =
mContext.getResources().getBoolean(R.bool.display_contact_organization);
String org = contact.getOrganization(); String org = contact.getOrganization();
if (org != null && !org.isEmpty() && isOrgVisible) { if (org != null && !org.isEmpty() && isOrgVisible) {
holder.organization.setText(org); holder.organization.setText(org);
@ -212,4 +176,53 @@ public class ContactsListAdapter extends SelectableAdapter<ContactsListAdapter.V
String letter = fullName.substring(0, 1).toUpperCase(Locale.getDefault()); String letter = fullName.substring(0, 1).toUpperCase(Locale.getDefault());
return mSectionsList.indexOf(letter); return mSectionsList.indexOf(letter);
} }
}
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
public CheckBox delete;
public ImageView linphoneFriend;
public TextView name;
public LinearLayout separator;
public TextView separatorText;
public RelativeLayout avatarLayout;
public TextView organization;
// public ImageView friendStatus;
private ClickListener mListener;
private ViewHolder(View view, ClickListener listener) {
super(view);
delete = view.findViewById(R.id.delete);
linphoneFriend = view.findViewById(R.id.friendLinphone);
name = view.findViewById(R.id.name);
separator = view.findViewById(R.id.separator);
separatorText = view.findViewById(R.id.separator_text);
avatarLayout = view.findViewById(R.id.avatar_layout);
organization = view.findViewById(R.id.contactOrganization);
// friendStatus = view.findViewById(R.id.friendStatus);
mListener = listener;
view.setOnClickListener(this);
view.setOnLongClickListener(this);
}
@Override
public void onClick(View view) {
if (mListener != null) {
mListener.onItemClicked(getAdapterPosition());
}
}
public boolean onLongClick(View v) {
if (mListener != null) {
return mListener.onItemLongClicked(getAdapterPosition());
}
return false;
}
public interface ClickListener {
void onItemClicked(int position);
boolean onItemLongClicked(int position);
}
}
}

View file

@ -19,17 +19,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.provider.ContactsContract;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -39,17 +31,22 @@ import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.SearchView; import android.widget.SearchView;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.SelectableHelper; import org.linphone.utils.SelectableHelper;
import java.util.ArrayList; public class ContactsListFragment extends Fragment
import java.util.List; implements OnItemClickListener,
ContactsUpdatedListener,
public class ContactsListFragment extends Fragment implements OnItemClickListener, ContactsUpdatedListener, ContactsListAdapter.ViewHolder.ClickListener, SelectableHelper.DeleteListener { ContactsListAdapter.ViewHolder.ClickListener,
SelectableHelper.DeleteListener {
private RecyclerView contactsList; private RecyclerView contactsList;
private TextView noSipContact, noContact; private TextView noSipContact, noContact;
private ImageView allContacts, linphoneContacts, newContact; private ImageView allContacts, linphoneContacts, newContact;
@ -66,7 +63,8 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
private ContactsListAdapter mContactAdapter; private ContactsListAdapter mContactAdapter;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.contacts_list, container, false); View view = inflater.inflate(R.layout.contacts_list, container, false);
mContext = getActivity().getApplicationContext(); mContext = getActivity().getApplicationContext();
mSelectionHelper = new SelectableHelper(view, this); mSelectionHelper = new SelectableHelper(view, this);
@ -91,37 +89,41 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
contactsFetchInProgress = view.findViewById(R.id.contactsFetchInProgress); contactsFetchInProgress = view.findViewById(R.id.contactsFetchInProgress);
newContact = view.findViewById(R.id.newContact); newContact = view.findViewById(R.id.newContact);
allContacts.setOnClickListener(new View.OnClickListener() { allContacts.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
onlyDisplayLinphoneContacts = false; public void onClick(View v) {
allContactsSelected.setVisibility(View.VISIBLE); onlyDisplayLinphoneContacts = false;
allContacts.setEnabled(false); allContactsSelected.setVisibility(View.VISIBLE);
linphoneContacts.setEnabled(true); allContacts.setEnabled(false);
linphoneContactsSelected.setVisibility(View.INVISIBLE); linphoneContacts.setEnabled(true);
changeContactsAdapter(); linphoneContactsSelected.setVisibility(View.INVISIBLE);
} changeContactsAdapter();
}); }
});
linphoneContacts.setOnClickListener(new View.OnClickListener() { linphoneContacts.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
allContactsSelected.setVisibility(View.INVISIBLE); public void onClick(View v) {
linphoneContactsSelected.setVisibility(View.VISIBLE); allContactsSelected.setVisibility(View.INVISIBLE);
linphoneContacts.setEnabled(false); linphoneContactsSelected.setVisibility(View.VISIBLE);
allContacts.setEnabled(true); linphoneContacts.setEnabled(false);
onlyDisplayLinphoneContacts = true; allContacts.setEnabled(true);
changeContactsAdapter(); onlyDisplayLinphoneContacts = true;
} changeContactsAdapter();
}); }
});
newContact.setOnClickListener(new View.OnClickListener() { newContact.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
editConsumed = true; public void onClick(View v) {
ContactsManager.getInstance().createContact(getActivity(), displayName, sipAddressToAdd); editConsumed = true;
} ContactsManager.getInstance()
}); .createContact(getActivity(), displayName, sipAddressToAdd);
}
});
if (getResources().getBoolean(R.bool.hide_non_linphone_contacts)) { if (getResources().getBoolean(R.bool.hide_non_linphone_contacts)) {
allContacts.setEnabled(false); allContacts.setEnabled(false);
@ -140,40 +142,47 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
if (!ContactsManager.getInstance().contactsFetchedOnce()) { if (!ContactsManager.getInstance().contactsFetchedOnce()) {
contactsFetchInProgress.setVisibility(View.VISIBLE); contactsFetchInProgress.setVisibility(View.VISIBLE);
} else { } else {
if (!onlyDisplayLinphoneContacts && ContactsManager.getInstance().getContacts().size() == 0) { if (!onlyDisplayLinphoneContacts
&& ContactsManager.getInstance().getContacts().size() == 0) {
noContact.setVisibility(View.VISIBLE); noContact.setVisibility(View.VISIBLE);
} else if (onlyDisplayLinphoneContacts && ContactsManager.getInstance().getSIPContacts().size() == 0) { } else if (onlyDisplayLinphoneContacts
&& ContactsManager.getInstance().getSIPContacts().size() == 0) {
noSipContact.setVisibility(View.VISIBLE); noSipContact.setVisibility(View.VISIBLE);
} }
} }
mSearchView = view.findViewById(R.id.searchField); mSearchView = view.findViewById(R.id.searchField);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { mSearchView.setOnQueryTextListener(
@Override new SearchView.OnQueryTextListener() {
public boolean onQueryTextSubmit(String query) { @Override
return true; public boolean onQueryTextSubmit(String query) {
} return true;
}
@Override @Override
public boolean onQueryTextChange(String newText) { public boolean onQueryTextChange(String newText) {
searchContacts(newText); searchContacts(newText);
return true; return true;
} }
}); });
layoutManager = new LinearLayoutManager(mContext); layoutManager = new LinearLayoutManager(mContext);
contactsList.setLayoutManager(layoutManager); contactsList.setLayoutManager(layoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(contactsList.getContext(), DividerItemDecoration dividerItemDecoration =
layoutManager.getOrientation()); new DividerItemDecoration(
dividerItemDecoration.setDrawable(getActivity().getResources().getDrawable(R.drawable.divider)); contactsList.getContext(), layoutManager.getOrientation());
dividerItemDecoration.setDrawable(
getActivity().getResources().getDrawable(R.drawable.divider));
contactsList.addItemDecoration(dividerItemDecoration); contactsList.addItemDecoration(dividerItemDecoration);
return view; return view;
} }
public void displayFirstContact() { public void displayFirstContact() {
if (contactsList != null && contactsList.getAdapter() != null && contactsList.getAdapter().getItemCount() > 0) { if (contactsList != null
&& contactsList.getAdapter() != null
&& contactsList.getAdapter().getItemCount() > 0) {
ContactsListAdapter mAdapt = (ContactsListAdapter) contactsList.getAdapter(); ContactsListAdapter mAdapt = (ContactsListAdapter) contactsList.getAdapter();
LinphoneActivity.instance().displayContact((LinphoneContact) mAdapt.getItem(0), false); LinphoneActivity.instance().displayContact((LinphoneContact) mAdapt.getItem(0), false);
} else { } else {
@ -203,7 +212,7 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
mContactAdapter = new ContactsListAdapter(mContext, listContact, this, mSelectionHelper); mContactAdapter = new ContactsListAdapter(mContext, listContact, this, mSelectionHelper);
// contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); // contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
mSelectionHelper.setAdapter(mContactAdapter); mSelectionHelper.setAdapter(mContactAdapter);
if (isEditionEnabled) { if (isEditionEnabled) {
mSelectionHelper.enterEditionMode(); mSelectionHelper.enterEditionMode();
@ -211,7 +220,6 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
contactsList.setAdapter(mContactAdapter); contactsList.setAdapter(mContactAdapter);
} }
private void changeContactsAdapter() { private void changeContactsAdapter() {
changeContactsToggle(); changeContactsToggle();
List<LinphoneContact> listContact; List<LinphoneContact> listContact;
@ -228,9 +236,13 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
} }
} else { } else {
if (onlyDisplayLinphoneContacts) { if (onlyDisplayLinphoneContacts) {
listContact = ContactsManager.getInstance().getSIPContacts(mSearchView.getQuery().toString()); listContact =
ContactsManager.getInstance()
.getSIPContacts(mSearchView.getQuery().toString());
} else { } else {
listContact = ContactsManager.getInstance().getContacts(mSearchView.getQuery().toString()); listContact =
ContactsManager.getInstance()
.getContacts(mSearchView.getQuery().toString());
} }
} }
@ -257,7 +269,8 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
} }
private void changeContactsToggle() { private void changeContactsToggle() {
if (onlyDisplayLinphoneContacts && !getResources().getBoolean(R.bool.hide_non_linphone_contacts)) { if (onlyDisplayLinphoneContacts
&& !getResources().getBoolean(R.bool.hide_non_linphone_contacts)) {
allContacts.setEnabled(true); allContacts.setEnabled(true);
allContactsSelected.setVisibility(View.INVISIBLE); allContactsSelected.setVisibility(View.INVISIBLE);
linphoneContacts.setEnabled(false); linphoneContacts.setEnabled(false);
@ -319,7 +332,9 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
if (LinphoneActivity.isInstanciated()) { if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CONTACTS_LIST); LinphoneActivity.instance().selectMenu(FragmentsAvailable.CONTACTS_LIST);
onlyDisplayLinphoneContacts = ContactsManager.getInstance().isLinphoneContactsPrefered() || getResources().getBoolean(R.bool.hide_non_linphone_contacts); onlyDisplayLinphoneContacts =
ContactsManager.getInstance().isLinphoneContactsPrefered()
|| getResources().getBoolean(R.bool.hide_non_linphone_contacts);
} }
changeContactsToggle(); changeContactsToggle();
invalidate(); invalidate();
@ -333,10 +348,14 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
@Override @Override
public void onContactsUpdated() { public void onContactsUpdated() {
if (!LinphoneActivity.isInstanciated() || LinphoneActivity.instance().getCurrentFragment() != FragmentsAvailable.CONTACTS_LIST) if (!LinphoneActivity.isInstanciated()
return; || LinphoneActivity.instance().getCurrentFragment()
!= FragmentsAvailable.CONTACTS_LIST) return;
if (mContactAdapter != null) { if (mContactAdapter != null) {
mContactAdapter.updateDataSet(onlyDisplayLinphoneContacts ? ContactsManager.getInstance().getSIPContacts() : ContactsManager.getInstance().getContacts()); mContactAdapter.updateDataSet(
onlyDisplayLinphoneContacts
? ContactsManager.getInstance().getSIPContacts()
: ContactsManager.getInstance().getContacts());
mContactAdapter.notifyDataSetChanged(); mContactAdapter.notifyDataSetChanged();
if (mContactAdapter.getItemCount() > 0) { if (mContactAdapter.getItemCount() > 0) {
@ -345,7 +364,6 @@ public class ContactsListFragment extends Fragment implements OnItemClickListene
} }
} }
contactsFetchInProgress.setVisibility(View.GONE); contactsFetchInProgress.setVisibility(View.GONE);
} }
public void invalidate() { public void invalidate() {

View file

@ -19,13 +19,14 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -37,12 +38,14 @@ import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Data;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Core; import org.linphone.core.Core;
@ -54,18 +57,24 @@ import org.linphone.core.PresenceBasicStatus;
import org.linphone.core.PresenceModel; import org.linphone.core.PresenceModel;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import java.util.ArrayList; import org.linphone.utils.LinphoneUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
public class ContactsManager extends ContentObserver implements FriendListListener { public class ContactsManager extends ContentObserver implements FriendListListener {
private static ContactsManager instance; @SuppressLint("InlinedApi")
private static final String[] PROJECTION = {
Data.CONTACT_ID,
ContactsContract.Contacts.LOOKUP_KEY,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
Data.MIMETYPE,
"data1", // Company, Phone or SIP Address
"data2", // ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
"data3", // ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
"data4", // Normalized phone number
};
private static ContactsManager instance;
private static ArrayList<ContactsUpdatedListener> contactsUpdatedListeners;
private List<LinphoneContact> mContacts, mSipContacts; private List<LinphoneContact> mContacts, mSipContacts;
private MagicSearch magicSearch; private MagicSearch magicSearch;
private Bitmap defaultAvatar; private Bitmap defaultAvatar;
@ -73,7 +82,18 @@ public class ContactsManager extends ContentObserver implements FriendListListen
private Context mContext; private Context mContext;
private AsyncContactsLoader mLoadContactTask; private AsyncContactsLoader mLoadContactTask;
private static ArrayList<ContactsUpdatedListener> contactsUpdatedListeners; private ContactsManager() {
super(LinphoneService.instance().mHandler);
defaultAvatar =
BitmapFactory.decodeResource(
LinphoneService.instance().getResources(), R.drawable.avatar);
contactsUpdatedListeners = new ArrayList<>();
mContacts = new ArrayList<>();
mSipContacts = new ArrayList<>();
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
magicSearch = LinphoneManager.getLcIfManagerNotDestroyedOrNull().createMagicSearch();
}
}
public static void addContactsListener(ContactsUpdatedListener listener) { public static void addContactsListener(ContactsUpdatedListener listener) {
contactsUpdatedListeners.add(listener); contactsUpdatedListeners.add(listener);
@ -83,15 +103,39 @@ public class ContactsManager extends ContentObserver implements FriendListListen
contactsUpdatedListeners.remove(listener); contactsUpdatedListeners.remove(listener);
} }
private ContactsManager() { public static final ContactsManager getInstance() {
super(LinphoneService.instance().mHandler); if (instance == null) instance = new ContactsManager();
defaultAvatar = BitmapFactory.decodeResource(LinphoneService.instance().getResources(), R.drawable.avatar); return instance;
contactsUpdatedListeners = new ArrayList<>(); }
mContacts = new ArrayList<>();
mSipContacts = new ArrayList<>(); public static String getAddressOrNumberForAndroidContact(
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) { ContentResolver resolver, Uri contactUri) {
magicSearch = LinphoneManager.getLcIfManagerNotDestroyedOrNull().createMagicSearch(); // Phone Numbers
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
while (c.moveToNext()) {
int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = c.getString(numberIndex);
c.close();
return number;
}
} }
// SIP addresses
projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
while (c.moveToNext()) {
int numberIndex =
c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
String address = c.getString(numberIndex);
c.close();
return address;
}
c.close();
}
return null;
} }
public void destroy() { public void destroy() {
@ -122,17 +166,11 @@ public class ContactsManager extends ContentObserver implements FriendListListen
onChange(selfChange, null); onChange(selfChange, null);
} }
@Override @Override
public void onChange(boolean selfChange, Uri uri) { public void onChange(boolean selfChange, Uri uri) {
fetchContactsAsync(); fetchContactsAsync();
} }
public static final ContactsManager getInstance() {
if (instance == null) instance = new ContactsManager();
return instance;
}
public synchronized boolean hasContacts() { public synchronized boolean hasContacts() {
return mContacts.size() > 0; return mContacts.size() > 0;
} }
@ -143,6 +181,12 @@ public class ContactsManager extends ContentObserver implements FriendListListen
} }
} }
public void setContacts(List<LinphoneContact> c) {
synchronized (mContacts) {
mContacts = c;
}
}
public List<LinphoneContact> getSIPContacts() { public List<LinphoneContact> getSIPContacts() {
synchronized (mSipContacts) { synchronized (mSipContacts) {
return mSipContacts; return mSipContacts;
@ -157,7 +201,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (contact.getFullName() != null) { if (contact.getFullName() != null) {
if (contact.getFullName().toLowerCase(Locale.getDefault()).startsWith(search)) { if (contact.getFullName().toLowerCase(Locale.getDefault()).startsWith(search)) {
searchContactsBegin.add(contact); searchContactsBegin.add(contact);
} else if (contact.getFullName().toLowerCase(Locale.getDefault()).contains(search)) { } else if (contact.getFullName()
.toLowerCase(Locale.getDefault())
.contains(search)) {
searchContactsContain.add(contact); searchContactsContain.add(contact);
} }
} }
@ -174,7 +220,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (contact.getFullName() != null) { if (contact.getFullName() != null) {
if (contact.getFullName().toLowerCase(Locale.getDefault()).startsWith(search)) { if (contact.getFullName().toLowerCase(Locale.getDefault()).startsWith(search)) {
searchContactsBegin.add(contact); searchContactsBegin.add(contact);
} else if (contact.getFullName().toLowerCase(Locale.getDefault()).contains(search)) { } else if (contact.getFullName()
.toLowerCase(Locale.getDefault())
.contains(search)) {
searchContactsContain.add(contact); searchContactsContain.add(contact);
} }
} }
@ -198,14 +246,21 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (mContext == null) { if (mContext == null) {
return false; return false;
} }
boolean contactsR = (PackageManager.PERMISSION_GRANTED == boolean contactsR =
mContext.getPackageManager().checkPermission(android.Manifest.permission.READ_CONTACTS, mContext.getPackageName())); (PackageManager.PERMISSION_GRANTED
return contactsR && !mContext.getResources().getBoolean(R.bool.force_use_of_linphone_friends); == mContext.getPackageManager()
.checkPermission(
android.Manifest.permission.READ_CONTACTS,
mContext.getPackageName()));
return contactsR
&& !mContext.getResources().getBoolean(R.bool.force_use_of_linphone_friends);
} }
public boolean isLinphoneContactsPrefered() { public boolean isLinphoneContactsPrefered() {
ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); ProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
if (lpc != null && lpc.getIdentityAddress().getDomain().equals(getString(R.string.default_domain))) return true; if (lpc != null
&& lpc.getIdentityAddress().getDomain().equals(getString(R.string.default_domain)))
return true;
return false; return false;
} }
@ -219,12 +274,14 @@ public class ContactsManager extends ContentObserver implements FriendListListen
public void initializeSyncAccount(Activity activity) { public void initializeSyncAccount(Activity activity) {
initializeContactManager(activity); initializeContactManager(activity);
AccountManager accountManager = (AccountManager) activity.getSystemService(Context.ACCOUNT_SERVICE); AccountManager accountManager =
(AccountManager) activity.getSystemService(Context.ACCOUNT_SERVICE);
Account[] accounts = accountManager.getAccountsByType(activity.getPackageName()); Account[] accounts = accountManager.getAccountsByType(activity.getPackageName());
if (accounts != null && accounts.length == 0) { if (accounts != null && accounts.length == 0) {
Account newAccount = new Account(getString(R.string.sync_account_name), activity.getPackageName()); Account newAccount =
new Account(getString(R.string.sync_account_name), activity.getPackageName());
try { try {
accountManager.addAccountExplicitly(newAccount, null, null); accountManager.addAccountExplicitly(newAccount, null, null);
} catch (Exception e) { } catch (Exception e) {
@ -259,7 +316,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
return null; return null;
} }
addr.setUriParam("user", "phone"); addr.setUriParam("user", "phone");
Friend lf = lc.findFriend(addr); // Without this, the hashmap inside liblinphone won't find it... Friend lf =
lc.findFriend(
addr); // Without this, the hashmap inside liblinphone won't find it...
if (lf != null) { if (lf != null) {
LinphoneContact contact = (LinphoneContact) lf.getUserData(); LinphoneContact contact = (LinphoneContact) lf.getUserData();
return contact; return contact;
@ -276,34 +335,6 @@ public class ContactsManager extends ContentObserver implements FriendListListen
return false; return false;
} }
public static String getAddressOrNumberForAndroidContact(ContentResolver resolver, Uri contactUri) {
// Phone Numbers
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
while (c.moveToNext()) {
int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = c.getString(numberIndex);
c.close();
return number;
}
}
// SIP addresses
projection = new String[]{ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
c = resolver.query(contactUri, projection, null, null, null);
if (c != null) {
while (c.moveToNext()) {
int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
String address = c.getString(numberIndex);
c.close();
return address;
}
c.close();
}
return null;
}
public void delete(String id) { public void delete(String id) {
ArrayList<String> ids = new ArrayList<>(); ArrayList<String> ids = new ArrayList<>();
ids.add(id); ids.add(id);
@ -315,8 +346,11 @@ public class ContactsManager extends ContentObserver implements FriendListListen
ArrayList<ContentProviderOperation> ops = new ArrayList<>(); ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (String id : ids) { for (String id : ids) {
String[] args = new String[]{id}; String[] args = new String[] {id};
ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI).withSelection(select, args).build()); ops.add(
ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
.withSelection(select, args)
.build());
} }
try { try {
@ -332,24 +366,16 @@ public class ContactsManager extends ContentObserver implements FriendListListen
} }
@Override @Override
public void onContactCreated(FriendList list, Friend lf) { public void onContactCreated(FriendList list, Friend lf) {}
}
@Override @Override
public void onContactDeleted(FriendList list, Friend lf) { public void onContactDeleted(FriendList list, Friend lf) {}
}
@Override @Override
public void onContactUpdated(FriendList list, Friend newFriend, Friend oldFriend) { public void onContactUpdated(FriendList list, Friend newFriend, Friend oldFriend) {}
}
@Override @Override
public void onSyncStatusChanged(FriendList list, FriendList.SyncStatus status, String msg) { public void onSyncStatusChanged(FriendList list, FriendList.SyncStatus status, String msg) {}
}
@Override @Override
public void onPresenceReceived(FriendList list, Friend[] friends) { public void onPresenceReceived(FriendList list, Friend[] friends) {
@ -371,18 +397,47 @@ public class ContactsManager extends ContentObserver implements FriendListListen
mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR); mLoadContactTask.executeOnExecutor(THREAD_POOL_EXECUTOR);
} }
@SuppressLint("InlinedApi") public synchronized void setSipContacts(List<LinphoneContact> c) {
private static final String[] PROJECTION = synchronized (mSipContacts) {
{ mSipContacts = c;
Data.CONTACT_ID, }
ContactsContract.Contacts.LOOKUP_KEY, }
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
Data.MIMETYPE, public void editContact(Context context, LinphoneContact contact, String valueToAdd) {
"data1", //Company, Phone or SIP Address if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
"data2", //ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME Intent intent = new Intent(Intent.ACTION_EDIT);
"data3", //ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME Uri contactUri =
"data4", //Normalized phone number ContactsContract.Contacts.getLookupUri(
}; Long.parseLong(contact.getAndroidId()), contact.getAndroidLookupKey());
intent.setDataAndType(contactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);
intent.putExtra(
"finishActivityOnSaveCompleted", true); // So after save will go back here
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().editContact(contact);
}
}
public void createContact(Context context, String name, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
intent.putExtra(
"finishActivityOnSaveCompleted", true); // So after save will go back here
if (name != null) {
intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
}
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().addContact(name, valueToAdd);
}
}
class AsyncContactsData { class AsyncContactsData {
List<LinphoneContact> contacts; List<LinphoneContact> contacts;
@ -402,10 +457,13 @@ public class ContactsManager extends ContentObserver implements FriendListListen
mAndroidContactsCache = new HashMap<>(); mAndroidContactsCache = new HashMap<>();
mContactsFetchedOnce = true; mContactsFetchedOnce = true;
if (LinphonePreferences.instance() != null && LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) { if (LinphonePreferences.instance() != null
&& LinphonePreferences.instance().isFriendlistsubscriptionEnabled()) {
String rls = getString(R.string.rls_uri); String rls = getString(R.string.rls_uri);
for (FriendList list : LinphoneManager.getLc().getFriendsLists()) { for (FriendList list : LinphoneManager.getLc().getFriendsLists()) {
if (rls != null && (list.getRlsAddress() == null || !list.getRlsAddress().asStringUriOnly().equals(rls))) { if (rls != null
&& (list.getRlsAddress() == null
|| !list.getRlsAddress().asStringUriOnly().equals(rls))) {
list.setRlsUri(rls); list.setRlsUri(rls);
} }
list.setListener(ContactsManager.this); list.setListener(ContactsManager.this);
@ -415,7 +473,14 @@ public class ContactsManager extends ContentObserver implements FriendListListen
@Override @Override
protected AsyncContactsData doInBackground(Void... params) { protected AsyncContactsData doInBackground(Void... params) {
Cursor c = mContext.getContentResolver().query(ContactsContract.Data.CONTENT_URI, PROJECTION, Data.IN_VISIBLE_GROUP + " == 1", null, null); Cursor c =
mContext.getContentResolver()
.query(
ContactsContract.Data.CONTENT_URI,
PROJECTION,
Data.IN_VISIBLE_GROUP + " == 1",
null,
null);
AsyncContactsData data = new AsyncContactsData(); AsyncContactsData data = new AsyncContactsData();
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
@ -432,7 +497,9 @@ public class ContactsManager extends ContentObserver implements FriendListListen
} }
} else { } else {
if (friend.getRefKey() != null) { if (friend.getRefKey() != null) {
// Friend has a refkey and but no LinphoneContact => represents a native contact stored in db from a previous version of Linphone, remove it // Friend has a refkey and but no LinphoneContact => represents a
// native contact stored in db from a previous version of Linphone,
// remove it
list.removeFriend(friend); list.removeFriend(friend);
} else { } else {
// No refkey so it's a standalone contact // No refkey so it's a standalone contact
@ -458,7 +525,8 @@ public class ContactsManager extends ContentObserver implements FriendListListen
String data2 = c.getString(c.getColumnIndex("data2")); String data2 = c.getString(c.getColumnIndex("data2"));
String data3 = c.getString(c.getColumnIndex("data3")); String data3 = c.getString(c.getColumnIndex("data3"));
String data4 = c.getString(c.getColumnIndex("data4")); String data4 = c.getString(c.getColumnIndex("data4"));
String lookupKey = c.getString(c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); String lookupKey =
c.getString(c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
LinphoneContact contact = mAndroidContactsCache.get(id); LinphoneContact contact = mAndroidContactsCache.get(id);
if (contact == null) { if (contact == null) {
@ -475,11 +543,15 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) { if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mime)) {
contact.addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4)); contact.addNumberOrAddress(new LinphoneNumberOrAddress(data1, data4));
} else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(mime) || getInstance().getString(R.string.sync_mimetype).equals(mime)) { } else if (ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE.equals(
mime)
|| getInstance().getString(R.string.sync_mimetype).equals(mime)) {
contact.addNumberOrAddress(new LinphoneNumberOrAddress(data1, true)); contact.addNumberOrAddress(new LinphoneNumberOrAddress(data1, true));
} else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mime)) { } else if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE
.equals(mime)) {
contact.setOrganization(data1, false); contact.setOrganization(data1, false);
} else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(mime)) { } else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
.equals(mime)) {
contact.setFirstNameAndLastName(data2, data3, false); contact.setFirstNameAndLastName(data2, data3, false);
} }
} }
@ -504,13 +576,19 @@ public class ContactsManager extends ContentObserver implements FriendListListen
for (LinphoneContact contact : mAndroidContactsCache.values()) { for (LinphoneContact contact : mAndroidContactsCache.values()) {
if (isCancelled()) return data; if (isCancelled()) return data;
boolean hideContactsWithoutPresence = mContext.getResources().getBoolean(R.bool.hide_sip_contacts_without_presence); boolean hideContactsWithoutPresence =
mContext.getResources()
.getBoolean(R.bool.hide_sip_contacts_without_presence);
if (contact.hasAddress()) { if (contact.hasAddress()) {
if (contact.getFullName() == null) { if (contact.getFullName() == null) {
for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) { for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) {
if (noa.isSIPAddress()) { if (noa.isSIPAddress()) {
contact.setFullName(LinphoneUtils.getAddressDisplayName(noa.getValue())); contact.setFullName(
Log.w("[Contacts Manager] Couldn't find a display name for contact " + contact.getFullName() + ", used SIP address display name / username instead..."); LinphoneUtils.getAddressDisplayName(noa.getValue()));
Log.w(
"[Contacts Manager] Couldn't find a display name for contact "
+ contact.getFullName()
+ ", used SIP address display name / username instead...");
break; break;
} }
} }
@ -518,8 +596,11 @@ public class ContactsManager extends ContentObserver implements FriendListListen
if (hideContactsWithoutPresence) { if (hideContactsWithoutPresence) {
if (contact.getFriend() != null) { if (contact.getFriend() != null) {
for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) { for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) {
PresenceModel pm = contact.getFriend().getPresenceModelForUriOrTel(noa.getValue()); PresenceModel pm =
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) { contact.getFriend()
.getPresenceModelForUriOrTel(noa.getValue());
if (pm != null
&& pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
data.sipContacts.add(contact); data.sipContacts.add(contact);
break; break;
} }
@ -552,48 +633,4 @@ public class ContactsManager extends ContentObserver implements FriendListListen
setSipContacts(data.sipContacts); setSipContacts(data.sipContacts);
} }
} }
public void setContacts(List<LinphoneContact> c) {
synchronized (mContacts) {
mContacts = c;
}
}
public synchronized void setSipContacts(List<LinphoneContact> c) {
synchronized (mSipContacts) {
mSipContacts = c;
}
}
public void editContact(Context context, LinphoneContact contact, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(Intent.ACTION_EDIT);
Uri contactUri = ContactsContract.Contacts.getLookupUri(Long.parseLong(contact.getAndroidId()), contact.getAndroidLookupKey());
intent.setDataAndType(contactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);
intent.putExtra("finishActivityOnSaveCompleted", true); // So after save will go back here
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().editContact(contact);
}
}
public void createContact(Context context, String name, String valueToAdd) {
if (context.getResources().getBoolean(R.bool.use_native_contact_editor)) {
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
intent.putExtra("finishActivityOnSaveCompleted", true); // So after save will go back here
if (name != null) {
intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
}
if (valueToAdd != null) {
intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, valueToAdd);
}
context.startActivity(intent);
} else {
LinphoneActivity.instance().addContact(name, valueToAdd);
}
}
} }

View file

@ -21,4 +21,4 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
public interface ContactsUpdatedListener { public interface ContactsUpdatedListener {
void onContactsUpdated(); void onContactsUpdated();
} }

File diff suppressed because it is too large Load diff

View file

@ -86,5 +86,7 @@ public class LinphoneNumberOrAddress implements Serializable, Comparable<Linphon
value = v; value = v;
} }
public String getNormalizedPhone() { return normalizedPhone != null ? normalizedPhone : value; } public String getNormalizedPhone() {
return normalizedPhone != null ? normalizedPhone : value;
}
} }

View file

@ -19,8 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.contacts; package org.linphone.contacts;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -28,10 +26,13 @@ import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Factory; import org.linphone.core.Factory;
import org.linphone.core.PresenceBasicStatus; import org.linphone.core.PresenceBasicStatus;
@ -40,46 +41,11 @@ import org.linphone.core.ProxyConfig;
import org.linphone.core.SearchResult; import org.linphone.core.SearchResult;
import org.linphone.views.ContactAvatar; import org.linphone.views.ContactAvatar;
import java.util.ArrayList; public class SearchContactsListAdapter
import java.util.List; extends RecyclerView.Adapter<SearchContactsListAdapter.ViewHolder> {
public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContactsListAdapter.ViewHolder> {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final String TAG = SearchContactsListAdapter.class.getSimpleName(); private static final String TAG = SearchContactsListAdapter.class.getSimpleName();
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView name;
public TextView address;
public ImageView linphoneContact;
public ImageView isSelect;
public RelativeLayout avatarLayout;
private ClickListener mListener;
public ViewHolder(View view, ClickListener listener) {
super(view);
name = view.findViewById(R.id.contact_name);
address = view.findViewById(R.id.contact_address);
linphoneContact = view.findViewById(R.id.contact_linphone);
isSelect = view.findViewById(R.id.contact_is_select);
avatarLayout = view.findViewById(R.id.avatar_layout);
mListener = listener;
view.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (mListener != null) {
mListener.onItemClicked(getAdapterPosition());
}
}
public interface ClickListener {
void onItemClicked(int position);
}
}
private List<ContactAddress> contacts; private List<ContactAddress> contacts;
private List<ContactAddress> contactsSelected; private List<ContactAddress> contactsSelected;
private ProgressBar progressBar; private ProgressBar progressBar;
@ -88,6 +54,19 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
private boolean mHideSelectionMark; private boolean mHideSelectionMark;
private String mPreviousSearch; private String mPreviousSearch;
public SearchContactsListAdapter(
List<ContactAddress> contactsList,
ProgressBar pB,
ViewHolder.ClickListener clickListener,
boolean hideSelectionMark) {
mHideSelectionMark = hideSelectionMark;
mListener = clickListener;
progressBar = pB;
setContactsSelectedList(null);
setContactsList(contactsList);
mPreviousSearch = null;
}
public List<ContactAddress> getContacts() { public List<ContactAddress> getContacts() {
return contacts; return contacts;
} }
@ -100,32 +79,27 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
mListener = listener; mListener = listener;
} }
public SearchContactsListAdapter(List<ContactAddress> contactsList, ProgressBar pB, ViewHolder.ClickListener clickListener, boolean hideSelectionMark) {
mHideSelectionMark = hideSelectionMark;
mListener = clickListener;
progressBar = pB;
setContactsSelectedList(null);
setContactsList(contactsList);
mPreviousSearch = null;
}
@NonNull @NonNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_contact_cell, parent, false); View v =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.search_contact_cell, parent, false);
return new ViewHolder(v, mListener); return new ViewHolder(v, mListener);
} }
@Override @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) { public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ContactAddress contact = getItem(position); ContactAddress contact = getItem(position);
final String a = (contact.getAddressAsDisplayableString().isEmpty()) ? contact.getPhoneNumber() : contact.getAddressAsDisplayableString(); final String a =
(contact.getAddressAsDisplayableString().isEmpty())
? contact.getPhoneNumber()
: contact.getAddressAsDisplayableString();
LinphoneContact c = contact.getContact(); LinphoneContact c = contact.getContact();
String address = contact.getAddressAsDisplayableString(); String address = contact.getAddressAsDisplayableString();
if (c != null && c.getFullName() != null) { if (c != null && c.getFullName() != null) {
if (address == null) if (address == null) address = c.getPresenceModelForUriOrTel(a);
address = c.getPresenceModelForUriOrTel(a);
holder.name.setVisibility(View.VISIBLE); holder.name.setVisibility(View.VISIBLE);
holder.name.setText(c.getFullName()); holder.name.setText(c.getFullName());
} else if (contact.getAddress() != null) { } else if (contact.getAddress() != null) {
@ -139,7 +113,10 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
} else if (address != null) { } else if (address != null) {
Address tmpAddr = Factory.instance().createAddress(address); Address tmpAddr = Factory.instance().createAddress(address);
holder.name.setVisibility(View.VISIBLE); holder.name.setVisibility(View.VISIBLE);
holder.name.setText((tmpAddr.getDisplayName() != null) ? tmpAddr.getDisplayName() : tmpAddr.getUsername()); holder.name.setText(
(tmpAddr.getDisplayName() != null)
? tmpAddr.getDisplayName()
: tmpAddr.getUsername());
} else { } else {
holder.name.setVisibility(View.GONE); holder.name.setVisibility(View.GONE);
} }
@ -149,7 +126,7 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
c.setFullName(holder.name.getText().toString()); c.setFullName(holder.name.getText().toString());
} }
ContactAvatar.displayAvatar(c, holder.avatarLayout); ContactAvatar.displayAvatar(c, holder.avatarLayout);
//TODO get if contact has security capabilities // TODO get if contact has security capabilities
} else { } else {
ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout); ContactAvatar.displayAvatar(holder.name.getText().toString(), holder.avatarLayout);
} }
@ -193,14 +170,8 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
return false; return false;
} }
public void setContactsList(List<ContactAddress> contactsList) { public List<ContactAddress> getContactsSelectedList() {
if (contactsList == null) { return contactsSelected;
contacts = getContactsList();
if (progressBar != null)
progressBar.setVisibility(View.GONE);
} else {
contacts = contactsList;
}
} }
public void setContactsSelectedList(List<ContactAddress> contactsList) { public void setContactsSelectedList(List<ContactAddress> contactsList) {
@ -211,26 +182,37 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
} }
} }
public List<ContactAddress> getContactsSelectedList() {
return contactsSelected;
}
public List<ContactAddress> getContactsList() { public List<ContactAddress> getContactsList() {
List<ContactAddress> list = new ArrayList<>(); List<ContactAddress> list = new ArrayList<>();
if (ContactsManager.getInstance().hasContacts()) { if (ContactsManager.getInstance().hasContacts()) {
List<LinphoneContact> contacts = mOnlySipContact ? ContactsManager.getInstance().getSIPContacts() : ContactsManager.getInstance().getContacts(); List<LinphoneContact> contacts =
mOnlySipContact
? ContactsManager.getInstance().getSIPContacts()
: ContactsManager.getInstance().getContacts();
for (LinphoneContact contact : contacts) { for (LinphoneContact contact : contacts) {
for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) { for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) {
if (!mOnlySipContact || (mOnlySipContact && (noa.isSIPAddress() || contact.getPresenceModelForUriOrTel(noa.getValue()) != null))) { if (!mOnlySipContact
|| (mOnlySipContact
&& (noa.isSIPAddress()
|| contact.getPresenceModelForUriOrTel(noa.getValue())
!= null))) {
ContactAddress ca = null; ContactAddress ca = null;
if (noa.isSIPAddress()) { if (noa.isSIPAddress()) {
Address address = LinphoneManager.getLc().interpretUrl(noa.getValue()); Address address = LinphoneManager.getLc().interpretUrl(noa.getValue());
if (address != null) { if (address != null) {
ca = new ContactAddress(contact, address.asString(), "", contact.isFriend()); ca =
new ContactAddress(
contact,
address.asString(),
"",
contact.isFriend());
} }
} else { } else {
ProxyConfig prx = LinphoneManager.getLc().getDefaultProxyConfig(); ProxyConfig prx = LinphoneManager.getLc().getDefaultProxyConfig();
String number = (prx != null) ? prx.normalizePhoneNumber(noa.getValue()) : noa.getValue(); String number =
(prx != null)
? prx.normalizePhoneNumber(noa.getValue())
: noa.getValue();
ca = new ContactAddress(contact, "", number, contact.isFriend()); ca = new ContactAddress(contact, "", number, contact.isFriend());
} }
if (ca != null) list.add(ca); if (ca != null) list.add(ca);
@ -247,6 +229,15 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
return list; return list;
} }
public void setContactsList(List<ContactAddress> contactsList) {
if (contactsList == null) {
contacts = getContactsList();
if (progressBar != null) progressBar.setVisibility(View.GONE);
} else {
contacts = contactsList;
}
}
public int getCount() { public int getCount() {
return contacts.size(); return contacts.size();
} }
@ -255,7 +246,6 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
return contacts.get(position); return contacts.get(position);
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return contacts.size(); return contacts.size();
@ -274,10 +264,14 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
String domain = ""; String domain = "";
ProxyConfig prx = LinphoneManager.getLc().getDefaultProxyConfig(); ProxyConfig prx = LinphoneManager.getLc().getDefaultProxyConfig();
if (prx != null) domain = prx.getDomain(); if (prx != null) domain = prx.getDomain();
SearchResult[] results = ContactsManager.getInstance().getMagicSearch().getContactListFromFilter(search, mOnlySipContact ? domain : ""); SearchResult[] results =
ContactsManager.getInstance()
.getMagicSearch()
.getContactListFromFilter(search, mOnlySipContact ? domain : "");
for (SearchResult sr : results) { for (SearchResult sr : results) {
boolean found = false; boolean found = false;
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(sr.getAddress()); LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(sr.getAddress());
if (contact == null) { if (contact == null) {
contact = new LinphoneContact(); contact = new LinphoneContact();
if (sr.getFriend() != null) { if (sr.getFriend() != null) {
@ -287,35 +281,54 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
} }
if (sr.getAddress() != null || sr.getPhoneNumber() != null) { if (sr.getAddress() != null || sr.getPhoneNumber() != null) {
for (ContactAddress ca : result) { for (ContactAddress ca : result) {
String normalizedPhoneNumber = (ca != null && ca.getPhoneNumber() != null && prx != null) ? prx.normalizePhoneNumber(ca.getPhoneNumber()) : null; String normalizedPhoneNumber =
if ((sr.getAddress() != null && ca.getAddress() != null (ca != null && ca.getPhoneNumber() != null && prx != null)
&& ca.getAddress().asStringUriOnly().equals(sr.getAddress().asStringUriOnly())) ? prx.normalizePhoneNumber(ca.getPhoneNumber())
|| (sr.getPhoneNumber() != null && normalizedPhoneNumber != null : null;
&& sr.getPhoneNumber().equals(normalizedPhoneNumber))) { if ((sr.getAddress() != null
&& ca.getAddress() != null
&& ca.getAddress()
.asStringUriOnly()
.equals(sr.getAddress().asStringUriOnly()))
|| (sr.getPhoneNumber() != null
&& normalizedPhoneNumber != null
&& sr.getPhoneNumber().equals(normalizedPhoneNumber))) {
found = true; found = true;
break; break;
} }
} }
} }
if (!found) { if (!found) {
if (LinphoneActivity.instance().getResources().getBoolean(R.bool.hide_sip_contacts_without_presence)) { if (LinphoneActivity.instance()
.getResources()
.getBoolean(R.bool.hide_sip_contacts_without_presence)) {
if (contact.getFriend() != null) { if (contact.getFriend() != null) {
for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) { for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) {
PresenceModel pm = contact.getFriend().getPresenceModelForUriOrTel(noa.getValue()); PresenceModel pm =
if (pm != null && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) { contact.getFriend().getPresenceModelForUriOrTel(noa.getValue());
result.add(new ContactAddress(contact, if (pm != null
(sr.getAddress() != null) ? sr.getAddress().asStringUriOnly() : "", && pm.getBasicStatus().equals(PresenceBasicStatus.Open)) {
sr.getPhoneNumber(), result.add(
contact.isFriend())); new ContactAddress(
contact,
(sr.getAddress() != null)
? sr.getAddress().asStringUriOnly()
: "",
sr.getPhoneNumber(),
contact.isFriend()));
break; break;
} }
} }
} }
} else { } else {
result.add(new ContactAddress(contact, result.add(
(sr.getAddress() != null) ? sr.getAddress().asStringUriOnly() : "", new ContactAddress(
sr.getPhoneNumber(), contact,
contact.isFriend())); (sr.getAddress() != null)
? sr.getAddress().asStringUriOnly()
: "",
sr.getPhoneNumber(),
contact.isFriend()));
} }
} }
} }
@ -324,5 +337,36 @@ public class SearchContactsListAdapter extends RecyclerView.Adapter<SearchContac
resultContactsSearch.setAdapter(this); resultContactsSearch.setAdapter(this);
notifyDataSetChanged(); notifyDataSetChanged();
} }
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView name;
public TextView address;
public ImageView linphoneContact;
public ImageView isSelect;
public RelativeLayout avatarLayout;
private ClickListener mListener;
public ViewHolder(View view, ClickListener listener) {
super(view);
name = view.findViewById(R.id.contact_name);
address = view.findViewById(R.id.contact_address);
linphoneContact = view.findViewById(R.id.contact_linphone);
isSelect = view.findViewById(R.id.contact_is_select);
avatarLayout = view.findViewById(R.id.avatar_layout);
mListener = listener;
view.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (mListener != null) {
mListener.onItemClicked(getAdapterPosition());
}
}
public interface ClickListener {
void onItemClicked(int position);
}
}
}

View file

@ -21,7 +21,6 @@ package org.linphone.firebase;
import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService; import com.google.firebase.iid.FirebaseInstanceIdService;
import org.linphone.settings.LinphonePreferences; import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils; import org.linphone.utils.LinphoneUtils;
@ -30,13 +29,16 @@ public class FirebaseIdService extends FirebaseInstanceIdService {
public void onTokenRefresh() { public void onTokenRefresh() {
// Get updated InstanceID token. // Get updated InstanceID token.
final String refreshedToken = FirebaseInstanceId.getInstance().getToken(); final String refreshedToken = FirebaseInstanceId.getInstance().getToken();
android.util.Log.i("FirebaseIdService", "[Push Notification] Refreshed token: " + refreshedToken); android.util.Log.i(
"FirebaseIdService", "[Push Notification] Refreshed token: " + refreshedToken);
LinphoneUtils.dispatchOnUIThread(new Runnable() { LinphoneUtils.dispatchOnUIThread(
@Override new Runnable() {
public void run() { @Override
LinphonePreferences.instance().setPushNotificationRegistrationID(refreshedToken); public void run() {
} LinphonePreferences.instance()
}); .setPushNotificationRegistrationID(refreshedToken);
}
});
} }
} }

View file

@ -19,21 +19,18 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.content.Intent; import static android.content.Intent.ACTION_MAIN;
import android.content.Intent;
import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage; import com.google.firebase.messaging.RemoteMessage;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.utils.LinphoneUtils; import org.linphone.utils.LinphoneUtils;
import static android.content.Intent.ACTION_MAIN;
public class FirebaseMessaging extends FirebaseMessagingService { public class FirebaseMessaging extends FirebaseMessagingService {
public FirebaseMessaging() { public FirebaseMessaging() {}
}
@Override @Override
public void onMessageReceived(RemoteMessage remoteMessage) { public void onMessageReceived(RemoteMessage remoteMessage) {
@ -46,16 +43,19 @@ public class FirebaseMessaging extends FirebaseMessagingService {
intent.putExtra("PushNotification", true); intent.putExtra("PushNotification", true);
startService(intent); startService(intent);
} else if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) { } else if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) {
LinphoneUtils.dispatchOnUIThread(new Runnable() { LinphoneUtils.dispatchOnUIThread(
@Override new Runnable() {
public void run() { @Override
Log.i("[Push Notification] Push notification received with LinphoneManager still alive"); public void run() {
if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) { Log.i(
LinphoneManager.getLc().setNetworkReachable(false); "[Push Notification] Push notification received with LinphoneManager still alive");
LinphoneManager.getLc().setNetworkReachable(true); if (LinphoneManager.isInstanciated()
} && LinphoneManager.getLc().getCallsNb() == 0) {
} LinphoneManager.getLc().setNetworkReachable(false);
}); LinphoneManager.getLc().setNetworkReachable(true);
}
}
});
} }
} }
} }

View file

@ -25,25 +25,23 @@ import android.content.Intent;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.content.ContextCompat;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.core.content.ContextCompat;
import org.linphone.BuildConfig; import org.linphone.BuildConfig;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.Core.LogCollectionUploadState; import org.linphone.core.Core.LogCollectionUploadState;
import org.linphone.core.CoreListenerStub; import org.linphone.core.CoreListenerStub;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
public class AboutFragment extends Fragment implements OnClickListener { public class AboutFragment extends Fragment implements OnClickListener {
View sendLogButton = null; View sendLogButton = null;
@ -53,40 +51,52 @@ public class AboutFragment extends Fragment implements OnClickListener {
private boolean uploadInProgress; private boolean uploadInProgress;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.about, container, false); View view = inflater.inflate(R.layout.about, container, false);
TextView aboutVersion = view.findViewById(R.id.about_android_version); TextView aboutVersion = view.findViewById(R.id.about_android_version);
TextView aboutLiblinphoneVersion = view.findViewById(R.id.about_liblinphone_version); TextView aboutLiblinphoneVersion = view.findViewById(R.id.about_liblinphone_version);
aboutLiblinphoneVersion.setText(String.format(getString(R.string.about_liblinphone_version), LinphoneManager.getLc().getVersion())); aboutLiblinphoneVersion.setText(
aboutVersion.setText(String.format(getString(R.string.about_version), BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")")); String.format(
getString(R.string.about_liblinphone_version),
LinphoneManager.getLc().getVersion()));
aboutVersion.setText(
String.format(
getString(R.string.about_version),
BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")"));
sendLogButton = view.findViewById(R.id.send_log); sendLogButton = view.findViewById(R.id.send_log);
sendLogButton.setOnClickListener(this); sendLogButton.setOnClickListener(this);
sendLogButton.setVisibility(LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE); sendLogButton.setVisibility(
LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
resetLogButton = view.findViewById(R.id.reset_log); resetLogButton = view.findViewById(R.id.reset_log);
resetLogButton.setOnClickListener(this); resetLogButton.setOnClickListener(this);
resetLogButton.setVisibility(LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE); resetLogButton.setVisibility(
LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onLogCollectionUploadProgressIndication(Core lc, int offset, int total) { @Override
} public void onLogCollectionUploadProgressIndication(
Core lc, int offset, int total) {}
@Override @Override
public void onLogCollectionUploadStateChanged(Core lc, LogCollectionUploadState state, String info) { public void onLogCollectionUploadStateChanged(
if (state == LogCollectionUploadState.InProgress) { Core lc, LogCollectionUploadState state, String info) {
displayUploadLogsInProgress(); if (state == LogCollectionUploadState.InProgress) {
} else if (state == LogCollectionUploadState.Delivered || state == LogCollectionUploadState.NotDelivered) { displayUploadLogsInProgress();
uploadInProgress = false; } else if (state == LogCollectionUploadState.Delivered
if (progress != null) progress.dismiss(); || state == LogCollectionUploadState.NotDelivered) {
if (state == LogCollectionUploadState.Delivered) { uploadInProgress = false;
sendLogs(LinphoneService.instance().getApplicationContext(), info); if (progress != null) progress.dismiss();
if (state == LogCollectionUploadState.Delivered) {
sendLogs(LinphoneService.instance().getApplicationContext(), info);
}
}
} }
} };
}
};
return view; return view;
} }
@ -100,7 +110,10 @@ public class AboutFragment extends Fragment implements OnClickListener {
progress = ProgressDialog.show(LinphoneActivity.instance(), null, null); progress = ProgressDialog.show(LinphoneActivity.instance(), null, null);
Drawable d = new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.colorE)); Drawable d = new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.colorE));
d.setAlpha(200); d.setAlpha(200);
progress.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); progress.getWindow()
.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
progress.getWindow().setBackgroundDrawable(d); progress.getWindow().setBackgroundDrawable(d);
progress.setContentView(R.layout.progress_dialog); progress.setContentView(R.layout.progress_dialog);
progress.show(); progress.show();
@ -110,7 +123,9 @@ public class AboutFragment extends Fragment implements OnClickListener {
final String appName = context.getString(R.string.app_name); final String appName = context.getString(R.string.app_name);
Intent i = new Intent(Intent.ACTION_SEND); Intent i = new Intent(Intent.ACTION_SEND);
i.putExtra(Intent.EXTRA_EMAIL, new String[]{context.getString(R.string.about_bugreport_email)}); i.putExtra(
Intent.EXTRA_EMAIL,
new String[] {context.getString(R.string.about_bugreport_email)});
i.putExtra(Intent.EXTRA_SUBJECT, appName + " Logs"); i.putExtra(Intent.EXTRA_SUBJECT, appName + " Logs");
i.putExtra(Intent.EXTRA_TEXT, info); i.putExtra(Intent.EXTRA_TEXT, info);
i.setType("application/zip"); i.setType("application/zip");

View file

@ -30,11 +30,10 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
@ -53,9 +52,14 @@ public class DialerFragment extends Fragment {
private ImageView mAddContact; private ImageView mAddContact;
private OnClickListener addContactListener, cancelListener, transferListener; private OnClickListener addContactListener, cancelListener, transferListener;
/** @return null if not ready yet */
public static DialerFragment instance() {
return instance;
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialer, container, false); View view = inflater.inflate(R.layout.dialer, container, false);
mAddress = view.findViewById(R.id.address); mAddress = view.findViewById(R.id.address);
@ -66,14 +70,19 @@ public class DialerFragment extends Fragment {
mCall = view.findViewById(R.id.call); mCall = view.findViewById(R.id.call);
mCall.setAddressWidget(mAddress); mCall.setAddressWidget(mAddress);
if (LinphoneActivity.isInstanciated() && LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getCallsNb() > 0) { if (LinphoneActivity.isInstanciated()
&& LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null
&& LinphoneManager.getLcIfManagerNotDestroyedOrNull().getCallsNb() > 0) {
if (isCallTransferOngoing) { if (isCallTransferOngoing) {
mCall.setImageResource(R.drawable.call_transfer); mCall.setImageResource(R.drawable.call_transfer);
} else { } else {
mCall.setImageResource(R.drawable.call_add); mCall.setImageResource(R.drawable.call_add);
} }
} else { } else {
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getVideoActivationPolicy().getAutomaticallyInitiate()) { if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null
&& LinphoneManager.getLcIfManagerNotDestroyedOrNull()
.getVideoActivationPolicy()
.getAutomaticallyInitiate()) {
mCall.setImageResource(R.drawable.call_video_start); mCall.setImageResource(R.drawable.call_video_start);
} else { } else {
mCall.setImageResource(R.drawable.call_audio_start); mCall.setImageResource(R.drawable.call_audio_start);
@ -86,32 +95,41 @@ public class DialerFragment extends Fragment {
} }
mAddContact = view.findViewById(R.id.add_contact); mAddContact = view.findViewById(R.id.add_contact);
mAddContact.setEnabled(!(LinphoneActivity.isInstanciated() && LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null && LinphoneManager.getLc().getCallsNb() > 0)); mAddContact.setEnabled(
!(LinphoneActivity.isInstanciated()
&& LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null
&& LinphoneManager.getLc().getCallsNb() > 0));
addContactListener = new OnClickListener() { addContactListener =
@Override new OnClickListener() {
public void onClick(View v) { @Override
LinphoneActivity.instance().displayContactsForEdition(mAddress.getText().toString()); public void onClick(View v) {
} LinphoneActivity.instance()
}; .displayContactsForEdition(mAddress.getText().toString());
cancelListener = new OnClickListener() { }
@Override };
public void onClick(View v) { cancelListener =
LinphoneActivity.instance().resetClassicMenuLayoutAndGoBackToCallIfStillRunning(); new OnClickListener() {
} @Override
}; public void onClick(View v) {
transferListener = new OnClickListener() { LinphoneActivity.instance()
@Override .resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
public void onClick(View v) { }
Core lc = LinphoneManager.getLc(); };
if (lc.getCurrentCall() == null) { transferListener =
return; new OnClickListener() {
} @Override
lc.transferCall(lc.getCurrentCall(), mAddress.getText().toString()); public void onClick(View v) {
isCallTransferOngoing = false; Core lc = LinphoneManager.getLc();
LinphoneActivity.instance().resetClassicMenuLayoutAndGoBackToCallIfStillRunning(); if (lc.getCurrentCall() == null) {
} return;
}; }
lc.transferCall(lc.getCurrentCall(), mAddress.getText().toString());
isCallTransferOngoing = false;
LinphoneActivity.instance()
.resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
}
};
resetLayout(); resetLayout();
@ -129,13 +147,6 @@ public class DialerFragment extends Fragment {
return view; return view;
} }
/**
* @return null if not ready yet
*/
public static DialerFragment instance() {
return instance;
}
@Override @Override
public void onPause() { public void onPause() {
instance = null; instance = null;
@ -153,7 +164,9 @@ public class DialerFragment extends Fragment {
LinphoneActivity.instance().showStatusBar(); LinphoneActivity.instance().showStatusBar();
} }
boolean isOrientationLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; boolean isOrientationLandscape =
getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE;
if (isOrientationLandscape && !getResources().getBoolean(R.bool.isTablet)) { if (isOrientationLandscape && !getResources().getBoolean(R.bool.isTablet)) {
((LinearLayout) numpad).setVisibility(View.GONE); ((LinearLayout) numpad).setVisibility(View.GONE);
} else { } else {
@ -165,7 +178,8 @@ public class DialerFragment extends Fragment {
String addressWaitingToBeCalled = LinphoneActivity.instance().mAddressWaitingToBeCalled; String addressWaitingToBeCalled = LinphoneActivity.instance().mAddressWaitingToBeCalled;
if (addressWaitingToBeCalled != null) { if (addressWaitingToBeCalled != null) {
mAddress.setText(addressWaitingToBeCalled); mAddress.setText(addressWaitingToBeCalled);
if (getResources().getBoolean(R.bool.automatically_start_intercepted_outgoing_gsm_call)) { if (getResources()
.getBoolean(R.bool.automatically_start_intercepted_outgoing_gsm_call)) {
newOutgoingCall(addressWaitingToBeCalled); newOutgoingCall(addressWaitingToBeCalled);
} }
LinphoneActivity.instance().mAddressWaitingToBeCalled = null; LinphoneActivity.instance().mAddressWaitingToBeCalled = null;
@ -207,7 +221,10 @@ public class DialerFragment extends Fragment {
} }
public void enableDisableAddContact() { public void enableDisableAddContact() {
mAddContact.setEnabled(LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null && LinphoneManager.getLc().getCallsNb() > 0 || !mAddress.getText().toString().equals("")); mAddContact.setEnabled(
LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null
&& LinphoneManager.getLc().getCallsNb() > 0
|| !mAddress.getText().toString().equals(""));
} }
public void displayTextInAddressBar(String numberOrSipAddress) { public void displayTextInAddressBar(String numberOrSipAddress) {
@ -228,7 +245,9 @@ public class DialerFragment extends Fragment {
mAddress.setText(intent.getData().getSchemeSpecificPart()); mAddress.setText(intent.getData().getSchemeSpecificPart());
} else { } else {
Uri contactUri = intent.getData(); Uri contactUri = intent.getData();
String address = ContactsManager.getAddressOrNumberForAndroidContact(LinphoneService.instance().getContentResolver(), contactUri); String address =
ContactsManager.getAddressOrNumberForAndroidContact(
LinphoneService.instance().getContentResolver(), contactUri);
if (address != null) { if (address != null) {
mAddress.setText(address); mAddress.setText(address);
} else { } else {

View file

@ -24,17 +24,15 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.linphone.R; import org.linphone.R;
public class EmptyFragment extends Fragment { public class EmptyFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.empty_fragment, container, false); View view = inflater.inflate(R.layout.empty_fragment, container, false);
return view; return view;
} }
} }

View file

@ -46,16 +46,23 @@ public enum FragmentsAvailable {
return fragment == HISTORY_LIST || fragment == HISTORY_DETAIL; return fragment == HISTORY_LIST || fragment == HISTORY_DETAIL;
case CONTACT_DETAIL: case CONTACT_DETAIL:
return fragment == CONTACTS_LIST || fragment == CONTACT_EDITOR || fragment == CONTACT_DETAIL; return fragment == CONTACTS_LIST
|| fragment == CONTACT_EDITOR
|| fragment == CONTACT_DETAIL;
case CONTACT_EDITOR: case CONTACT_EDITOR:
return fragment == CONTACTS_LIST || fragment == CONTACT_DETAIL || fragment == CONTACT_EDITOR; return fragment == CONTACTS_LIST
|| fragment == CONTACT_DETAIL
|| fragment == CONTACT_EDITOR;
case CHAT: case CHAT:
return fragment == CHAT_LIST || fragment == CHAT; return fragment == CHAT_LIST || fragment == CHAT;
case GROUP_CHAT: case GROUP_CHAT:
return fragment == CHAT_LIST || fragment == GROUP_CHAT || fragment == INFO_GROUP_CHAT || fragment == CREATE_CHAT; return fragment == CHAT_LIST
|| fragment == GROUP_CHAT
|| fragment == INFO_GROUP_CHAT
|| fragment == CREATE_CHAT;
case MESSAGE_IMDN: case MESSAGE_IMDN:
return fragment == GROUP_CHAT || fragment == MESSAGE_IMDN; return fragment == GROUP_CHAT || fragment == MESSAGE_IMDN;

View file

@ -26,7 +26,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import androidx.core.content.ContextCompat;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -36,12 +35,11 @@ import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.core.content.ContextCompat;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.assistant.AssistantActivity; import org.linphone.assistant.AssistantActivity;
import org.linphone.call.CallActivity; import org.linphone.call.CallActivity;
import org.linphone.core.Call; import org.linphone.core.Call;
@ -53,6 +51,7 @@ import org.linphone.core.MediaEncryption;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.core.RegistrationState; import org.linphone.core.RegistrationState;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
public class StatusFragment extends Fragment { public class StatusFragment extends Fragment {
private Handler refreshHandler = new Handler(); private Handler refreshHandler = new Handler();
@ -65,8 +64,8 @@ public class StatusFragment extends Fragment {
private int mDisplayedQuality = -1; private int mDisplayedQuality = -1;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.status, container, false); View view = inflater.inflate(R.layout.status, container, false);
statusText = view.findViewById(R.id.status_text); statusText = view.findViewById(R.id.status_text);
@ -80,64 +79,71 @@ public class StatusFragment extends Fragment {
// We create it once to not delay the first display // We create it once to not delay the first display
populateSliderContent(); populateSliderContent();
mListener = new CoreListenerStub() { mListener =
@Override new CoreListenerStub() {
public void onRegistrationStateChanged(final Core lc, final ProxyConfig proxy, final RegistrationState state, String smessage) { @Override
if (!isAttached || !LinphoneService.isReady()) { public void onRegistrationStateChanged(
return; final Core lc,
} final ProxyConfig proxy,
final RegistrationState state,
if (lc.getProxyConfigList() == null) { String smessage) {
statusLed.setImageResource(R.drawable.led_disconnected); if (!isAttached || !LinphoneService.isReady()) {
statusText.setText(getString(R.string.no_account)); return;
} else {
statusLed.setVisibility(View.VISIBLE);
}
if (lc.getDefaultProxyConfig() != null && lc.getDefaultProxyConfig().equals(proxy)) {
statusLed.setImageResource(getStatusIconResource(state, true));
statusText.setText(getStatusIconText(state));
} else if (lc.getDefaultProxyConfig() == null) {
statusLed.setImageResource(getStatusIconResource(state, true));
statusText.setText(getStatusIconText(state));
}
try {
statusText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
lc.refreshRegisters();
} }
});
} catch (IllegalStateException ise) {
}
}
@Override if (lc.getProxyConfigList() == null) {
public void onNotifyReceived(Core lc, Event ev, String eventName, Content content) { statusLed.setImageResource(R.drawable.led_disconnected);
statusText.setText(getString(R.string.no_account));
} else {
statusLed.setVisibility(View.VISIBLE);
}
if (!content.getType().equals("application")) return; if (lc.getDefaultProxyConfig() != null
if (!content.getSubtype().equals("simple-message-summary")) return; && lc.getDefaultProxyConfig().equals(proxy)) {
statusLed.setImageResource(getStatusIconResource(state, true));
statusText.setText(getStatusIconText(state));
} else if (lc.getDefaultProxyConfig() == null) {
statusLed.setImageResource(getStatusIconResource(state, true));
statusText.setText(getStatusIconText(state));
}
if (content.getSize() == 0) return; try {
statusText.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
lc.refreshRegisters();
}
});
} catch (IllegalStateException ise) {
}
}
int unreadCount = -1; @Override
String data = content.getStringBuffer(); public void onNotifyReceived(
String[] voiceMail = data.split("voice-message: "); Core lc, Event ev, String eventName, Content content) {
final String[] intToParse = voiceMail[1].split("/", 0);
unreadCount = Integer.parseInt(intToParse[0]); if (!content.getType().equals("application")) return;
if (unreadCount > 0) { if (!content.getSubtype().equals("simple-message-summary")) return;
voicemailCount.setText(unreadCount);
voicemail.setVisibility(View.VISIBLE);
voicemailCount.setVisibility(View.VISIBLE);
} else {
voicemail.setVisibility(View.GONE);
voicemailCount.setVisibility(View.GONE);
}
}
}; if (content.getSize() == 0) return;
int unreadCount = -1;
String data = content.getStringBuffer();
String[] voiceMail = data.split("voice-message: ");
final String[] intToParse = voiceMail[1].split("/", 0);
unreadCount = Integer.parseInt(intToParse[0]);
if (unreadCount > 0) {
voicemailCount.setText(unreadCount);
voicemail.setVisibility(View.VISIBLE);
voicemailCount.setVisibility(View.VISIBLE);
} else {
voicemail.setVisibility(View.GONE);
voicemailCount.setVisibility(View.GONE);
}
}
};
isAttached = true; isAttached = true;
Activity activity = getActivity(); Activity activity = getActivity();
@ -174,15 +180,15 @@ public class StatusFragment extends Fragment {
isAttached = false; isAttached = false;
} }
//NORMAL STATUS BAR // NORMAL STATUS BAR
private void populateSliderContent() { private void populateSliderContent() {
if (LinphoneManager.isInstanciated() && LinphoneManager.getLc() != null) { if (LinphoneManager.isInstanciated() && LinphoneManager.getLc() != null) {
voicemailCount.setVisibility(View.GONE); voicemailCount.setVisibility(View.GONE);
if (isInCall && isAttached) { if (isInCall && isAttached) {
//Call call = LinphoneManager.getLc().getCurrentCall(); // Call call = LinphoneManager.getLc().getCurrentCall();
//initCallStatsRefresher(call, callStats); // initCallStatsRefresher(call, callStats);
} else if (!isInCall) { } else if (!isInCall) {
voicemailCount.setVisibility(View.VISIBLE); voicemailCount.setVisibility(View.VISIBLE);
} }
@ -208,7 +214,13 @@ public class StatusFragment extends Fragment {
private int getStatusIconResource(RegistrationState state, boolean isDefaultAccount) { private int getStatusIconResource(RegistrationState state, boolean isDefaultAccount) {
try { try {
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
boolean defaultAccountConnected = (isDefaultAccount && lc != null && lc.getDefaultProxyConfig() != null && lc.getDefaultProxyConfig().getState() == RegistrationState.Ok) || !isDefaultAccount; boolean defaultAccountConnected =
(isDefaultAccount
&& lc != null
&& lc.getDefaultProxyConfig() != null
&& lc.getDefaultProxyConfig().getState()
== RegistrationState.Ok)
|| !isDefaultAccount;
if (state == RegistrationState.Ok && defaultAccountConnected) { if (state == RegistrationState.Ok && defaultAccountConnected) {
return R.drawable.led_connected; return R.drawable.led_connected;
} else if (state == RegistrationState.Progress) { } else if (state == RegistrationState.Progress) {
@ -227,13 +239,15 @@ public class StatusFragment extends Fragment {
private String getStatusIconText(RegistrationState state) { private String getStatusIconText(RegistrationState state) {
Context context = getActivity(); Context context = getActivity();
if (!isAttached && LinphoneActivity.isInstanciated()) if (!isAttached && LinphoneActivity.isInstanciated()) context = LinphoneActivity.instance();
context = LinphoneActivity.instance(); else if (!isAttached && LinphoneService.isReady()) context = LinphoneService.instance();
else if (!isAttached && LinphoneService.isReady())
context = LinphoneService.instance();
try { try {
if (state == RegistrationState.Ok && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getDefaultProxyConfig().getState() == RegistrationState.Ok) { if (state == RegistrationState.Ok
&& LinphoneManager.getLcIfManagerNotDestroyedOrNull()
.getDefaultProxyConfig()
.getState()
== RegistrationState.Ok) {
return context.getString(R.string.status_connected); return context.getString(R.string.status_connected);
} else if (state == RegistrationState.Progress) { } else if (state == RegistrationState.Progress) {
return context.getString(R.string.status_in_progress); return context.getString(R.string.status_in_progress);
@ -249,27 +263,28 @@ public class StatusFragment extends Fragment {
return context.getString(R.string.status_not_connected); return context.getString(R.string.status_not_connected);
} }
//INCALL STATUS BAR // INCALL STATUS BAR
private void startCallQuality() { private void startCallQuality() {
callQuality.setVisibility(View.VISIBLE); callQuality.setVisibility(View.VISIBLE);
refreshHandler.postDelayed(mCallQualityUpdater = new Runnable() { refreshHandler.postDelayed(
Call mCurrentCall = LinphoneManager.getLc() mCallQualityUpdater =
.getCurrentCall(); new Runnable() {
Call mCurrentCall = LinphoneManager.getLc().getCurrentCall();
public void run() { public void run() {
if (mCurrentCall == null) { if (mCurrentCall == null) {
mCallQualityUpdater = null; mCallQualityUpdater = null;
return; return;
} }
float newQuality = mCurrentCall.getCurrentQuality(); float newQuality = mCurrentCall.getCurrentQuality();
updateQualityOfSignalIcon(newQuality); updateQualityOfSignalIcon(newQuality);
if (isInCall) { if (isInCall) {
refreshHandler.postDelayed(this, 1000); refreshHandler.postDelayed(this, 1000);
} else } else mCallQualityUpdater = null;
mCallQualityUpdater = null; }
} },
}, 1000); 1000);
} }
void updateQualityOfSignalIcon(float quality) { void updateQualityOfSignalIcon(float quality) {
@ -278,24 +293,19 @@ public class StatusFragment extends Fragment {
if (iQuality == mDisplayedQuality) return; if (iQuality == mDisplayedQuality) return;
if (quality >= 4) // Good Quality if (quality >= 4) // Good Quality
{ {
callQuality.setImageResource( callQuality.setImageResource(R.drawable.call_quality_indicator_4);
R.drawable.call_quality_indicator_4);
} else if (quality >= 3) // Average quality } else if (quality >= 3) // Average quality
{ {
callQuality.setImageResource( callQuality.setImageResource(R.drawable.call_quality_indicator_3);
R.drawable.call_quality_indicator_3);
} else if (quality >= 2) // Low quality } else if (quality >= 2) // Low quality
{ {
callQuality.setImageResource( callQuality.setImageResource(R.drawable.call_quality_indicator_2);
R.drawable.call_quality_indicator_2);
} else if (quality >= 1) // Very low quality } else if (quality >= 1) // Very low quality
{ {
callQuality.setImageResource( callQuality.setImageResource(R.drawable.call_quality_indicator_1);
R.drawable.call_quality_indicator_1);
} else // Worst quality } else // Worst quality
{ {
callQuality.setImageResource( callQuality.setImageResource(R.drawable.call_quality_indicator_0);
R.drawable.call_quality_indicator_0);
} }
mDisplayedQuality = iQuality; mDisplayedQuality = iQuality;
} }
@ -326,7 +336,8 @@ public class StatusFragment extends Fragment {
statusLed.setImageResource(R.drawable.led_disconnected); statusLed.setImageResource(R.drawable.led_disconnected);
statusText.setText(getString(R.string.no_account)); statusText.setText(getString(R.string.no_account));
} else { } else {
statusLed.setImageResource(getStatusIconResource(lc.getDefaultProxyConfig().getState(), true)); statusLed.setImageResource(
getStatusIconResource(lc.getDefaultProxyConfig().getState(), true));
statusText.setText(getStatusIconText(lc.getDefaultProxyConfig().getState())); statusText.setText(getStatusIconText(lc.getDefaultProxyConfig().getState()));
} }
} }
@ -357,15 +368,19 @@ public class StatusFragment extends Fragment {
MediaEncryption mediaEncryption = call.getCurrentParams().getMediaEncryption(); MediaEncryption mediaEncryption = call.getCurrentParams().getMediaEncryption();
if (isVideoEnabled) { if (isVideoEnabled) {
//background.setVisibility(View.GONE); // background.setVisibility(View.GONE);
} else { } else {
//background.setVisibility(View.VISIBLE); // background.setVisibility(View.VISIBLE);
} }
encryption.setVisibility(View.VISIBLE); encryption.setVisibility(View.VISIBLE);
if (mediaEncryption == MediaEncryption.SRTP || (mediaEncryption == MediaEncryption.ZRTP && call.getAuthenticationTokenVerified()) || mediaEncryption == MediaEncryption.DTLS) { if (mediaEncryption == MediaEncryption.SRTP
|| (mediaEncryption == MediaEncryption.ZRTP
&& call.getAuthenticationTokenVerified())
|| mediaEncryption == MediaEncryption.DTLS) {
encryption.setImageResource(R.drawable.security_ok); encryption.setImageResource(R.drawable.security_ok);
} else if (mediaEncryption == MediaEncryption.ZRTP && !call.getAuthenticationTokenVerified()) { } else if (mediaEncryption == MediaEncryption.ZRTP
&& !call.getAuthenticationTokenVerified()) {
encryption.setImageResource(R.drawable.security_pending); encryption.setImageResource(R.drawable.security_pending);
} else { } else {
encryption.setImageResource(R.drawable.security_ko); encryption.setImageResource(R.drawable.security_ko);
@ -376,12 +391,13 @@ public class StatusFragment extends Fragment {
} }
if (mediaEncryption == MediaEncryption.ZRTP) { if (mediaEncryption == MediaEncryption.ZRTP) {
encryption.setOnClickListener(new OnClickListener() { encryption.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View v) { @Override
showZRTPDialog(call); public void onClick(View v) {
} showZRTPDialog(call);
}); }
});
} else { } else {
encryption.setOnClickListener(null); encryption.setOnClickListener(null);
} }
@ -414,7 +430,10 @@ public class StatusFragment extends Fragment {
Drawable d = new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.colorC)); Drawable d = new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.colorC));
d.setAlpha(200); d.setAlpha(200);
ZRTPdialog.setContentView(R.layout.dialog); ZRTPdialog.setContentView(R.layout.dialog);
ZRTPdialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); ZRTPdialog.getWindow()
.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
ZRTPdialog.getWindow().setBackgroundDrawable(d); ZRTPdialog.getWindow().setBackgroundDrawable(d);
String zrtpToRead, zrtpToListen; String zrtpToRead, zrtpToListen;
@ -450,29 +469,31 @@ public class StatusFragment extends Fragment {
icon.setVisibility(View.VISIBLE); icon.setVisibility(View.VISIBLE);
icon.setImageResource(R.drawable.security_2_indicator); icon.setImageResource(R.drawable.security_2_indicator);
delete.setOnClickListener(new OnClickListener() { delete.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
if (call != null) { public void onClick(View view) {
call.setAuthenticationTokenVerified(false); if (call != null) {
if (encryption != null) { call.setAuthenticationTokenVerified(false);
encryption.setImageResource(R.drawable.security_ko); if (encryption != null) {
encryption.setImageResource(R.drawable.security_ko);
}
}
ZRTPdialog.dismiss();
} }
} });
ZRTPdialog.dismiss();
}
});
accept.setOnClickListener(new OnClickListener() { accept.setOnClickListener(
@Override new OnClickListener() {
public void onClick(View view) { @Override
call.setAuthenticationTokenVerified(true); public void onClick(View view) {
if (encryption != null) { call.setAuthenticationTokenVerified(true);
encryption.setImageResource(R.drawable.security_ok); if (encryption != null) {
} encryption.setImageResource(R.drawable.security_ok);
ZRTPdialog.dismiss(); }
} ZRTPdialog.dismiss();
}); }
});
ZRTPdialog.show(); ZRTPdialog.show();
} }
} }

View file

@ -1,53 +1,55 @@
package org.linphone.history; package org.linphone.history;
/* /*
HistoryAdapter.java HistoryAdapter.java
Copyright (C) 2018 Belledonne Communications, Grenoble, France Copyright (C) 2018 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull;
import org.linphone.utils.LinphoneUtils; import java.text.SimpleDateFormat;
import org.linphone.R; import java.util.Calendar;
import java.util.List;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.core.CallLog; import org.linphone.core.CallLog;
import org.linphone.views.ContactAvatar; import org.linphone.utils.LinphoneUtils;
import org.linphone.utils.SelectableAdapter; import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper; import org.linphone.utils.SelectableHelper;
import org.linphone.views.ContactAvatar;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> { public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
private List<CallLog> mLogs; private List<CallLog> mLogs;
private Context mContext; private Context mContext;
private HistoryViewHolder.ClickListener clickListener; private HistoryViewHolder.ClickListener clickListener;
public HistoryAdapter(Context aContext, List<CallLog> logs, HistoryViewHolder.ClickListener listener, SelectableHelper helper) { public HistoryAdapter(
Context aContext,
List<CallLog> logs,
HistoryViewHolder.ClickListener listener,
SelectableHelper helper) {
super(helper); super(helper);
this.mLogs = logs; this.mLogs = logs;
this.mContext = aContext; this.mContext = aContext;
@ -65,9 +67,10 @@ public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
@NonNull @NonNull
@Override @Override
public HistoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public HistoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_cell, parent, false); View v =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.history_cell, parent, false);
return new HistoryViewHolder(v, clickListener); return new HistoryViewHolder(v, clickListener);
} }
@Override @Override
@ -130,18 +133,17 @@ public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
} }
holder.detail.setVisibility(isEditionEnabled() ? View.INVISIBLE : View.VISIBLE); holder.detail.setVisibility(isEditionEnabled() ? View.INVISIBLE : View.VISIBLE);
holder.detail.setOnClickListener(!isEditionEnabled() ? holder.detail.setOnClickListener(
new View.OnClickListener() { !isEditionEnabled()
@Override ? new View.OnClickListener() {
public void onClick(View v) { @Override
if (LinphoneActivity.isInstanciated()) { public void onClick(View v) {
LinphoneActivity.instance().displayHistoryDetail(sipUri, log); if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayHistoryDetail(sipUri, log);
}
}
} }
} : null);
}
:
null
);
} }
@Override @Override
@ -157,7 +159,9 @@ public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
} else if (isYesterday(cal)) { } else if (isYesterday(cal)) {
return mContext.getString(R.string.yesterday); return mContext.getString(R.string.yesterday);
} else { } else {
dateFormat = new SimpleDateFormat(mContext.getResources().getString(R.string.history_date_format)); dateFormat =
new SimpleDateFormat(
mContext.getResources().getString(R.string.history_date_format));
} }
return dateFormat.format(cal.getTime()); return dateFormat.format(cal.getTime());
@ -168,9 +172,9 @@ public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
return false; return false;
} }
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)); && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
} }
private boolean isToday(Calendar cal) { private boolean isToday(Calendar cal) {
@ -182,4 +186,4 @@ public class HistoryAdapter extends SelectableAdapter<HistoryViewHolder> {
yesterday.roll(Calendar.DAY_OF_MONTH, -1); yesterday.roll(Calendar.DAY_OF_MONTH, -1);
return isSameDay(cal, yesterday); return isSameDay(cal, yesterday);
} }
} }

View file

@ -29,14 +29,9 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.LinphoneManager;
import org.linphone.fragments.FragmentsAvailable;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
@ -47,6 +42,9 @@ import org.linphone.core.Factory;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
public class HistoryDetailFragment extends Fragment implements OnClickListener { public class HistoryDetailFragment extends Fragment implements OnClickListener {
private ImageView dialBack, chat, addToContacts, goToContact, back; private ImageView dialBack, chat, addToContacts, goToContact, back;
@ -60,8 +58,8 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
private ChatRoomListenerStub mChatRoomCreationListener; private ChatRoomListenerStub mChatRoomCreationListener;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
sipUri = getArguments().getString("SipUri"); sipUri = getArguments().getString("SipUri");
displayName = getArguments().getString("DisplayName"); displayName = getArguments().getString("DisplayName");
pictureUri = getArguments().getString("PictureUri"); pictureUri = getArguments().getString("PictureUri");
@ -107,19 +105,24 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
displayHistory(status, callTime, callDate); displayHistory(status, callTime, callDate);
mChatRoomCreationListener = new ChatRoomListenerStub() { mChatRoomCreationListener =
@Override new ChatRoomListenerStub() {
public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { @Override
if (newState == ChatRoom.State.Created) { public void onStateChanged(ChatRoom cr, ChatRoom.State newState) {
mWaitLayout.setVisibility(View.GONE); if (newState == ChatRoom.State.Created) {
LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), null); mWaitLayout.setVisibility(View.GONE);
} else if (newState == ChatRoom.State.CreationFailed) { LinphoneActivity.instance()
mWaitLayout.setVisibility(View.GONE); .goToChat(cr.getPeerAddress().asStringUriOnly(), null);
LinphoneActivity.instance().displayChatRoomError(); } else if (newState == ChatRoom.State.CreationFailed) {
Log.e("Group chat room for address " + cr.getPeerAddress() + " has failed !"); mWaitLayout.setVisibility(View.GONE);
} LinphoneActivity.instance().displayChatRoomError();
} Log.e(
}; "Group chat room for address "
+ cr.getPeerAddress()
+ " has failed !");
}
}
};
return view; return view;
} }
@ -143,7 +146,9 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
time.setText(callTime == null ? "" : callTime); time.setText(callTime == null ? "" : callTime);
Long longDate = Long.parseLong(callDate); Long longDate = Long.parseLong(callDate);
date.setText(LinphoneUtils.timestampToHumanDate(getActivity(), longDate, getString(R.string.history_detail_date_format))); date.setText(
LinphoneUtils.timestampToHumanDate(
getActivity(), longDate, getString(R.string.history_detail_date_format)));
Address lAddress = Factory.instance().createAddress(sipUri); Address lAddress = Factory.instance().createAddress(sipUri);
@ -152,22 +157,39 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
contact = ContactsManager.getInstance().findContactFromAddress(lAddress); contact = ContactsManager.getInstance().findContactFromAddress(lAddress);
if (contact != null) { if (contact != null) {
contactName.setText(contact.getFullName()); contactName.setText(contact.getFullName());
ImageUtils.setImagePictureFromUri(view.getContext(), contactPicture, contact.getPhotoUri(), contact.getThumbnailUri()); ImageUtils.setImagePictureFromUri(
view.getContext(),
contactPicture,
contact.getPhotoUri(),
contact.getThumbnailUri());
addToContacts.setVisibility(View.GONE); addToContacts.setVisibility(View.GONE);
goToContact.setVisibility(View.VISIBLE); goToContact.setVisibility(View.VISIBLE);
} else { } else {
contactName.setText(displayName == null ? LinphoneUtils.getAddressDisplayName(sipUri) : displayName); contactName.setText(
contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap()); displayName == null
? LinphoneUtils.getAddressDisplayName(sipUri)
: displayName);
contactPicture.setImageBitmap(
ContactsManager.getInstance().getDefaultAvatarBitmap());
addToContacts.setVisibility(View.VISIBLE); addToContacts.setVisibility(View.VISIBLE);
goToContact.setVisibility(View.GONE); goToContact.setVisibility(View.GONE);
} }
} else { } else {
contactAddress.setText(sipUri); contactAddress.setText(sipUri);
contactName.setText(displayName == null ? LinphoneUtils.getAddressDisplayName(sipUri) : displayName); contactName.setText(
displayName == null
? LinphoneUtils.getAddressDisplayName(sipUri)
: displayName);
} }
} }
public void changeDisplayedHistory(String sipUri, String displayName, String pictureUri, String status, String callTime, String callDate) { public void changeDisplayedHistory(
String sipUri,
String displayName,
String pictureUri,
String status,
String callTime,
String callDate) {
if (displayName == null) { if (displayName == null) {
displayName = LinphoneUtils.getUsernameFromAddress(sipUri); displayName = LinphoneUtils.getUsernameFromAddress(sipUri);
} }
@ -195,23 +217,32 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
getFragmentManager().popBackStackImmediate(); getFragmentManager().popBackStackImmediate();
} }
if (id == R.id.call) { if (id == R.id.call) {
LinphoneActivity.instance().setAddresGoToDialerAndCall(sipUri, displayName, pictureUri == null ? null : Uri.parse(pictureUri)); LinphoneActivity.instance()
.setAddresGoToDialerAndCall(
sipUri, displayName, pictureUri == null ? null : Uri.parse(pictureUri));
} else if (id == R.id.chat) { } else if (id == R.id.chat) {
Core lc = LinphoneManager.getLc(); Core lc = LinphoneManager.getLc();
Address participant = Factory.instance().createAddress(sipUri); Address participant = Factory.instance().createAddress(sipUri);
ChatRoom room = lc.findOneToOneChatRoom(lc.getDefaultProxyConfig().getContact(), participant, false); ChatRoom room =
lc.findOneToOneChatRoom(
lc.getDefaultProxyConfig().getContact(), participant, false);
if (room != null) { if (room != null) {
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null); LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null);
} else { } else {
ProxyConfig lpc = lc.getDefaultProxyConfig(); ProxyConfig lpc = lc.getDefaultProxyConfig();
if (lpc != null && lpc.getConferenceFactoryUri() != null && !LinphonePreferences.instance().useBasicChatRoomFor1To1()) { if (lpc != null
&& lpc.getConferenceFactoryUri() != null
&& !LinphonePreferences.instance().useBasicChatRoomFor1To1()) {
mWaitLayout.setVisibility(View.VISIBLE); mWaitLayout.setVisibility(View.VISIBLE);
mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), true); mChatRoom =
lc.createClientGroupChatRoom(
getString(R.string.dummy_group_chat_subject), true);
mChatRoom.addListener(mChatRoomCreationListener); mChatRoom.addListener(mChatRoomCreationListener);
mChatRoom.addParticipant(participant); mChatRoom.addParticipant(participant);
} else { } else {
room = lc.getChatRoom(participant); room = lc.getChatRoom(participant);
LinphoneActivity.instance().goToChat(room.getPeerAddress().asStringUriOnly(), null); LinphoneActivity.instance()
.goToChat(room.getPeerAddress().asStringUriOnly(), null);
} }
} }
} else if (id == R.id.add_contact) { } else if (id == R.id.add_contact) {

View file

@ -22,9 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -33,24 +30,29 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.fragments.FragmentsAvailable;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.ContactsUpdatedListener; import org.linphone.contacts.ContactsUpdatedListener;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.core.CallLog; import org.linphone.core.CallLog;
import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.SelectableHelper; import org.linphone.utils.SelectableHelper;
public class HistoryListFragment extends Fragment
import java.util.ArrayList; implements OnClickListener,
import java.util.Arrays; OnItemClickListener,
import java.util.List; HistoryViewHolder.ClickListener,
ContactsUpdatedListener,
public class HistoryListFragment extends Fragment implements OnClickListener, OnItemClickListener, HistoryViewHolder.ClickListener, ContactsUpdatedListener, SelectableHelper.DeleteListener { SelectableHelper.DeleteListener {
private RecyclerView historyList; private RecyclerView historyList;
private TextView noCallHistory, noMissedCallHistory; private TextView noCallHistory, noMissedCallHistory;
private ImageView missedCalls, allCalls; private ImageView missedCalls, allCalls;
@ -63,8 +65,8 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
private SelectableHelper mSelectionHelper; private SelectableHelper mSelectionHelper;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.history, container, false); View view = inflater.inflate(R.layout.history, container, false);
mContext = getActivity().getApplicationContext(); mContext = getActivity().getApplicationContext();
mSelectionHelper = new SelectableHelper(view, this); mSelectionHelper = new SelectableHelper(view, this);
@ -76,9 +78,10 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
mLayoutManager = new LinearLayoutManager(mContext); mLayoutManager = new LinearLayoutManager(mContext);
historyList.setLayoutManager(mLayoutManager); historyList.setLayoutManager(mLayoutManager);
//Divider between items // Divider between items
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(historyList.getContext(), DividerItemDecoration dividerItemDecoration =
mLayoutManager.getOrientation()); new DividerItemDecoration(
historyList.getContext(), mLayoutManager.getOrientation());
dividerItemDecoration.setDrawable(mContext.getResources().getDrawable(R.drawable.divider)); dividerItemDecoration.setDrawable(mContext.getResources().getDrawable(R.drawable.divider));
historyList.addItemDecoration(dividerItemDecoration); historyList.addItemDecoration(dividerItemDecoration);
@ -133,7 +136,7 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
removeNotMissedCallsFromLogs(); removeNotMissedCallsFromLogs();
noCallHistory.setVisibility(View.GONE); noCallHistory.setVisibility(View.GONE);
noMissedCallHistory.setVisibility(View.GONE); noMissedCallHistory.setVisibility(View.GONE);
if (mLogs.isEmpty()) { if (mLogs.isEmpty()) {
if (mOnlyDisplayMissedCalls) { if (mOnlyDisplayMissedCalls) {
noMissedCallHistory.setVisibility(View.VISIBLE); noMissedCallHistory.setVisibility(View.VISIBLE);
@ -160,7 +163,9 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs());
hideHistoryListAndDisplayMessageIfEmpty(); hideHistoryListAndDisplayMessageIfEmpty();
mHistoryAdapter = new HistoryAdapter(getActivity().getApplicationContext(), mLogs, this, mSelectionHelper); mHistoryAdapter =
new HistoryAdapter(
getActivity().getApplicationContext(), mLogs, this, mSelectionHelper);
historyList.setAdapter(mHistoryAdapter); historyList.setAdapter(mHistoryAdapter);
mSelectionHelper.setAdapter(mHistoryAdapter); mSelectionHelper.setAdapter(mHistoryAdapter);
mSelectionHelper.setDialogMessage(R.string.chat_room_delete_dialog); mSelectionHelper.setDialogMessage(R.string.chat_room_delete_dialog);
@ -174,8 +179,9 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
@Override @Override
public void onContactsUpdated() { public void onContactsUpdated() {
if (!LinphoneActivity.isInstanciated() || LinphoneActivity.instance().getCurrentFragment() != FragmentsAvailable.HISTORY_LIST) if (!LinphoneActivity.isInstanciated()
return; || LinphoneActivity.instance().getCurrentFragment()
!= FragmentsAvailable.HISTORY_LIST) return;
HistoryAdapter adapter = (HistoryAdapter) historyList.getAdapter(); HistoryAdapter adapter = (HistoryAdapter) historyList.getAdapter();
if (adapter != null) { if (adapter != null) {
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
@ -240,7 +246,9 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
} else { } else {
address = log.getToAddress(); address = log.getToAddress();
} }
LinphoneActivity.instance().setAddresGoToDialerAndCall(address.asStringUriOnly(), address.getDisplayName(), null); LinphoneActivity.instance()
.setAddresGoToDialerAndCall(
address.asStringUriOnly(), address.getDisplayName(), null);
} }
} }
} }
@ -253,4 +261,4 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On
mHistoryAdapter.toggleSelection(position); mHistoryAdapter.toggleSelection(position);
return true; return true;
} }
} }

View file

@ -1,35 +1,35 @@
package org.linphone.history; package org.linphone.history;
/* /*
HistoryViewHolder.java HistoryViewHolder.java
Copyright (C) 2018 Belledonne Communications, Grenoble, France Copyright (C) 2018 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import androidx.recyclerview.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import org.linphone.R; import org.linphone.R;
public class HistoryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { public class HistoryViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
public TextView contact; public TextView contact;
public ImageView detail; public ImageView detail;
public CheckBox select; public CheckBox select;
@ -75,4 +75,4 @@ public class HistoryViewHolder extends RecyclerView.ViewHolder implements View.O
boolean onItemLongClicked(int position); boolean onItemLongClicked(int position);
} }
} }

View file

@ -30,7 +30,8 @@ public class NotifiableMessage {
Uri mFilePath; Uri mFilePath;
String mFileMime; String mFileMime;
public NotifiableMessage(String message, String sender, long time, Uri filePath, String fileMime) { public NotifiableMessage(
String message, String sender, long time, Uri filePath, String fileMime) {
mMessage = message; mMessage = message;
mSender = sender; mSender = sender;
mTime = time; mTime = time;

View file

@ -26,11 +26,10 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.R; import org.linphone.R;
import org.linphone.LinphoneActivity;
import org.linphone.compatibility.Compatibility; import org.linphone.compatibility.Compatibility;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
@ -38,7 +37,6 @@ import org.linphone.core.ChatMessage;
import org.linphone.core.ChatMessageListenerStub; import org.linphone.core.ChatMessageListenerStub;
import org.linphone.core.ChatRoom; import org.linphone.core.ChatRoom;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.core.ProxyConfig;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
public class NotificationBroadcastReceiver extends BroadcastReceiver { public class NotificationBroadcastReceiver extends BroadcastReceiver {
@ -54,17 +52,20 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
onError(context, notifId); onError(context, notifId);
return; return;
} }
String remoteSipAddr = LinphoneService.instance().getNotificationManager().getSipUriForNotificationId(notifId); String remoteSipAddr =
LinphoneService.instance()
.getNotificationManager()
.getSipUriForNotificationId(notifId);
Core core = LinphoneManager.getLc(); Core core = LinphoneManager.getLc();
if (core == null) { if (core == null) {
Log.e("Couldn't get Core instance"); Log.e("Couldn't get Core instance");
onError(context, notifId); onError(context, notifId);
return; return;
} }
Address remoteAddr = core.interpretUrl(remoteSipAddr); Address remoteAddr = core.interpretUrl(remoteSipAddr);
if (remoteAddr == null) { if (remoteAddr == null) {
Log.e("Couldn't interpret remote address " + remoteSipAddr); Log.e("Couldn't interpret remote address " + remoteSipAddr);
onError(context, notifId); onError(context, notifId);
return; return;
@ -78,33 +79,46 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
} }
ChatRoom room = core.findChatRoom(remoteAddr, localAddr); ChatRoom room = core.findChatRoom(remoteAddr, localAddr);
if (room == null) { if (room == null) {
Log.e("Couldn't find chat room for remote address " + remoteSipAddr + " and local address " + localyIdentity); Log.e(
"Couldn't find chat room for remote address "
+ remoteSipAddr
+ " and local address "
+ localyIdentity);
onError(context, notifId); onError(context, notifId);
return; return;
} }
room.markAsRead(); room.markAsRead();
if (LinphoneActivity.isInstanciated()) { if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayMissedChats(LinphoneManager.getInstance().getUnreadMessageCount()); LinphoneActivity.instance()
.displayMissedChats(LinphoneManager.getInstance().getUnreadMessageCount());
} }
ChatMessage msg = room.createMessage(reply); ChatMessage msg = room.createMessage(reply);
msg.send(); msg.send();
msg.setListener(new ChatMessageListenerStub() { msg.setListener(
@Override new ChatMessageListenerStub() {
public void onMsgStateChanged(ChatMessage msg, ChatMessage.State state) { @Override
if (state == ChatMessage.State.Delivered) { public void onMsgStateChanged(ChatMessage msg, ChatMessage.State state) {
Notification replied = Compatibility.createRepliedNotification(context, reply); if (state == ChatMessage.State.Delivered) {
LinphoneService.instance().getNotificationManager().sendNotification(notifId, replied); Notification replied =
} else if (state == ChatMessage.State.NotDelivered) { Compatibility.createRepliedNotification(context, reply);
Log.e("Couldn't send reply, message is not delivered"); LinphoneService.instance()
onError(context, notifId); .getNotificationManager()
} .sendNotification(notifId, replied);
} } else if (state == ChatMessage.State.NotDelivered) {
}); Log.e("Couldn't send reply, message is not delivered");
} else if (intent.getAction() == Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION || intent.getAction() == Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION) { onError(context, notifId);
String remoteAddr = LinphoneService.instance().getNotificationManager().getSipUriForCallNotificationId(notifId); }
}
});
} else if (intent.getAction() == Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION
|| intent.getAction() == Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION) {
String remoteAddr =
LinphoneService.instance()
.getNotificationManager()
.getSipUriForCallNotificationId(notifId);
Core core = LinphoneManager.getLc(); Core core = LinphoneManager.getLc();
if (core == null) { if (core == null) {
@ -126,7 +140,8 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
} }
private void onError(Context context, int notifId) { private void onError(Context context, int notifId) {
Notification replyError = Compatibility.createRepliedNotification(context, context.getString(R.string.error)); Notification replyError =
Compatibility.createRepliedNotification(context, context.getString(R.string.error));
LinphoneService.instance().getNotificationManager().sendNotification(notifId, replyError); LinphoneService.instance().getNotificationManager().sendNotification(notifId, replyError);
} }

View file

@ -19,6 +19,8 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static android.content.Context.NOTIFICATION_SERVICE;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -27,24 +29,20 @@ import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import java.util.HashMap;
import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService;
import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneService;
import org.linphone.R;
import org.linphone.compatibility.Compatibility; import org.linphone.compatibility.Compatibility;
import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact; import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address; import org.linphone.core.Address;
import org.linphone.core.Call; import org.linphone.core.Call;
import org.linphone.mediastream.Version; import org.linphone.mediastream.Version;
import org.linphone.settings.LinphonePreferences;
import java.util.HashMap; import org.linphone.utils.ImageUtils;
import org.linphone.utils.LinphoneUtils;
import static android.content.Context.NOTIFICATION_SERVICE;
public class NotificationsManager { public class NotificationsManager {
private static final int SERVICE_NOTIF_ID = 1; private static final int SERVICE_NOTIF_ID = 1;
@ -69,10 +67,11 @@ public class NotificationsManager {
Compatibility.createNotificationChannels(mContext); Compatibility.createNotificationChannels(mContext);
Intent notifIntent = new Intent(mContext, LinphoneService.instance().getIncomingReceivedActivity()); Intent notifIntent =
new Intent(mContext, LinphoneService.instance().getIncomingReceivedActivity());
notifIntent.putExtra("Notification", true); notifIntent.putExtra("Notification", true);
//Disable service notification for Android O // Disable service notification for Android O
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
LinphonePreferences.instance().setServiceNotificationVisibility(false); LinphonePreferences.instance().setServiceNotificationVisibility(false);
} }
@ -83,10 +82,20 @@ public class NotificationsManager {
} catch (Exception e) { } catch (Exception e) {
} }
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent =
mServiceNotification = Compatibility.createNotification(mContext, mContext.getString(R.string.service_name), "", PendingIntent.getActivity(
R.drawable.linphone_notification_icon, R.mipmap.ic_launcher, bm, pendingIntent, true, mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.PRIORITY_MIN); mServiceNotification =
Compatibility.createNotification(
mContext,
mContext.getString(R.string.service_name),
"",
R.drawable.linphone_notification_icon,
R.mipmap.ic_launcher,
bm,
pendingIntent,
true,
Notification.PRIORITY_MIN);
if (isServiceNotificationDisplayed()) { if (isServiceNotificationDisplayed()) {
startForeground(); startForeground();
@ -130,15 +139,27 @@ public class NotificationsManager {
return null; return null;
} }
public void displayGroupChatMessageNotification(String subject, String conferenceAddress, String fromName, Uri fromPictureUri, String message, Address localIdentity, long timestamp, Uri filePath, String fileMime) { public void displayGroupChatMessageNotification(
String subject,
String conferenceAddress,
String fromName,
Uri fromPictureUri,
String message,
Address localIdentity,
long timestamp,
Uri filePath,
String fileMime) {
Intent notifIntent = new Intent(mContext, LinphoneActivity.class); Intent notifIntent = new Intent(mContext, LinphoneActivity.class);
notifIntent.putExtra("GoToChat", true); notifIntent.putExtra("GoToChat", true);
notifIntent.putExtra("ChatContactSipUri", conferenceAddress); notifIntent.putExtra("ChatContactSipUri", conferenceAddress);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent =
PendingIntent.getActivity(
mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, fromPictureUri); Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, fromPictureUri);
Notifiable notif = mChatNotifMap.get(conferenceAddress); Notifiable notif = mChatNotifMap.get(conferenceAddress);
NotifiableMessage notifMessage = new NotifiableMessage(message, fromName, timestamp, filePath, fileMime); NotifiableMessage notifMessage =
new NotifiableMessage(message, fromName, timestamp, filePath, fileMime);
if (notif == null) { if (notif == null) {
notif = new Notifiable(mLastNotificationId); notif = new Notifiable(mLastNotificationId);
mLastNotificationId += 1; mLastNotificationId += 1;
@ -152,16 +173,34 @@ public class NotificationsManager {
notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity)); notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity));
notif.setLocalIdentity(localIdentity.asString()); notif.setLocalIdentity(localIdentity.asString());
Notification notification = Compatibility.createMessageNotification(mContext, notif, subject, Notification notification =
mContext.getString(R.string.group_chat_notif).replace("%1", fromName).replace("%2", message), bm, pendingIntent); Compatibility.createMessageNotification(
mContext,
notif,
subject,
mContext.getString(R.string.group_chat_notif)
.replace("%1", fromName)
.replace("%2", message),
bm,
pendingIntent);
sendNotification(notif.getNotificationId(), notification); sendNotification(notif.getNotificationId(), notification);
} }
public void displayMessageNotification(String fromSipUri, String fromName, Uri fromPictureUri, String message, Address localIdentity, long timestamp, Uri filePath, String fileMime) { public void displayMessageNotification(
String fromSipUri,
String fromName,
Uri fromPictureUri,
String message,
Address localIdentity,
long timestamp,
Uri filePath,
String fileMime) {
Intent notifIntent = new Intent(mContext, LinphoneActivity.class); Intent notifIntent = new Intent(mContext, LinphoneActivity.class);
notifIntent.putExtra("GoToChat", true); notifIntent.putExtra("GoToChat", true);
notifIntent.putExtra("ChatContactSipUri", fromSipUri); notifIntent.putExtra("ChatContactSipUri", fromSipUri);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent =
PendingIntent.getActivity(
mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (fromName == null) { if (fromName == null) {
fromName = fromSipUri; fromName = fromSipUri;
@ -169,7 +208,8 @@ public class NotificationsManager {
Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, fromPictureUri); Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, fromPictureUri);
Notifiable notif = mChatNotifMap.get(fromSipUri); Notifiable notif = mChatNotifMap.get(fromSipUri);
NotifiableMessage notifMessage = new NotifiableMessage(message, fromName, timestamp, filePath, fileMime); NotifiableMessage notifMessage =
new NotifiableMessage(message, fromName, timestamp, filePath, fileMime);
if (notif == null) { if (notif == null) {
notif = new Notifiable(mLastNotificationId); notif = new Notifiable(mLastNotificationId);
mLastNotificationId += 1; mLastNotificationId += 1;
@ -182,19 +222,26 @@ public class NotificationsManager {
notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity)); notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity));
notif.setLocalIdentity(localIdentity.asString()); notif.setLocalIdentity(localIdentity.asString());
Notification notification = Compatibility.createMessageNotification(mContext, notif, fromName, message, bm, pendingIntent); Notification notification =
Compatibility.createMessageNotification(
mContext, notif, fromName, message, bm, pendingIntent);
sendNotification(notif.getNotificationId(), notification); sendNotification(notif.getNotificationId(), notification);
} }
public void displayMissedCallNotification(Call call) { public void displayMissedCallNotification(Call call) {
Intent missedCallNotifIntent = new Intent(mContext, LinphoneActivity.class); Intent missedCallNotifIntent = new Intent(mContext, LinphoneActivity.class);
missedCallNotifIntent.putExtra("GoToHistory", true); missedCallNotifIntent.putExtra("GoToHistory", true);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, missedCallNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent =
PendingIntent.getActivity(
mContext, 0, missedCallNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
int missedCallCount = LinphoneManager.getLcIfManagerNotDestroyedOrNull().getMissedCallsCount(); int missedCallCount =
LinphoneManager.getLcIfManagerNotDestroyedOrNull().getMissedCallsCount();
String body; String body;
if (missedCallCount > 1) { if (missedCallCount > 1) {
body = mContext.getString(R.string.missed_calls_notif_body).replace("%i", String.valueOf(missedCallCount)); body =
mContext.getString(R.string.missed_calls_notif_body)
.replace("%i", String.valueOf(missedCallCount));
} else { } else {
Address address = call.getRemoteAddress(); Address address = call.getRemoteAddress();
LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address); LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address);
@ -208,14 +255,22 @@ public class NotificationsManager {
} }
} }
Notification notif = Compatibility.createMissedCallNotification(mContext, mContext.getString(R.string.missed_calls_notif_title), body, pendingIntent); Notification notif =
Compatibility.createMissedCallNotification(
mContext,
mContext.getString(R.string.missed_calls_notif_title),
body,
pendingIntent);
sendNotification(MISSED_CALLS_NOTIF_ID, notif); sendNotification(MISSED_CALLS_NOTIF_ID, notif);
} }
public void displayCallNotification(Call call) { public void displayCallNotification(Call call) {
if (call == null) return; if (call == null) return;
Intent callNotifIntent = new Intent(mContext, LinphoneService.instance().getIncomingReceivedActivity()); Intent callNotifIntent =
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, callNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT); new Intent(mContext, LinphoneService.instance().getIncomingReceivedActivity());
PendingIntent pendingIntent =
PendingIntent.getActivity(
mContext, 0, callNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Address address = call.getRemoteAddress(); Address address = call.getRemoteAddress();
String addressAsString = address.asStringUriOnly(); String addressAsString = address.asStringUriOnly();
@ -264,10 +319,20 @@ public class NotificationsManager {
Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, pictureUri); Bitmap bm = ImageUtils.getRoundBitmapFromUri(mContext, pictureUri);
String name = LinphoneUtils.getAddressDisplayName(address); String name = LinphoneUtils.getAddressDisplayName(address);
boolean showAnswerAction = call.getState() == Call.State.IncomingReceived || call.getState() == Call.State.IncomingEarlyMedia; boolean showAnswerAction =
Notification notification = Compatibility.createInCallNotification(mContext, notif.getNotificationId(), call.getState() == Call.State.IncomingReceived
showAnswerAction, mContext.getString(R.string.service_name), || call.getState() == Call.State.IncomingEarlyMedia;
mContext.getString(notificationTextId), iconId, bm, name, pendingIntent); Notification notification =
Compatibility.createInCallNotification(
mContext,
notif.getNotificationId(),
showAnswerAction,
mContext.getString(R.string.service_name),
mContext.getString(notificationTextId),
iconId,
bm,
name,
pendingIntent);
sendNotification(notif.getNotificationId(), notification); sendNotification(notif.getNotificationId(), notification);
} }
@ -283,9 +348,16 @@ public class NotificationsManager {
public void displayInappNotification(String message) { public void displayInappNotification(String message) {
Intent notifIntent = new Intent(mContext, LinphoneActivity.class); Intent notifIntent = new Intent(mContext, LinphoneActivity.class);
notifIntent.putExtra("GoToInapp", true); notifIntent.putExtra("GoToInapp", true);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent =
PendingIntent.getActivity(
mContext, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notif = Compatibility.createSimpleNotification(mContext, mContext.getString(R.string.inapp_notification_title), message, pendingIntent); Notification notif =
Compatibility.createSimpleNotification(
mContext,
mContext.getString(R.string.inapp_notification_title),
message,
pendingIntent);
sendNotification(IN_APP_NOTIF_ID, notif); sendNotification(IN_APP_NOTIF_ID, notif);
} }
} }

View file

@ -29,17 +29,16 @@ import android.view.View.OnClickListener;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import java.util.ArrayList;
import org.linphone.settings.LinphonePreferences; import java.util.List;
import org.linphone.R; import org.linphone.R;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.xmlrpc.XmlRpcHelper; import org.linphone.xmlrpc.XmlRpcHelper;
import org.linphone.xmlrpc.XmlRpcListenerBase; import org.linphone.xmlrpc.XmlRpcListenerBase;
import java.util.ArrayList; public class InAppPurchaseActivity extends Activity
import java.util.List; implements InAppPurchaseListener, OnClickListener {
public class InAppPurchaseActivity extends Activity implements InAppPurchaseListener, OnClickListener {
private static InAppPurchaseActivity instance; private static InAppPurchaseActivity instance;
private InAppPurchaseHelper inAppPurchaseHelper; private InAppPurchaseHelper inAppPurchaseHelper;
private ImageView cancel, back; private ImageView cancel, back;
@ -49,6 +48,10 @@ public class InAppPurchaseActivity extends Activity implements InAppPurchaseList
private Fragment fragment; private Fragment fragment;
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
public static InAppPurchaseActivity instance() {
return instance;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -92,12 +95,10 @@ public class InAppPurchaseActivity extends Activity implements InAppPurchaseList
inAppPurchaseHelper.purchaseItemAsync(item.getId(), username); inAppPurchaseHelper.purchaseItemAsync(item.getId(), username);
} }
public String getGmailAccount() { public String getGmailAccount() {
return inAppPurchaseHelper.getGmailAccount(); return inAppPurchaseHelper.getGmailAccount();
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
instance = null; instance = null;
@ -122,22 +123,18 @@ public class InAppPurchaseActivity extends Activity implements InAppPurchaseList
return null; return null;
} }
public static InAppPurchaseActivity instance() {
return instance;
}
@Override @Override
public void onServiceAvailableForQueries() { public void onServiceAvailableForQueries() {
//email.setText(inAppPurchaseHelper.getGmailAccount()); // email.setText(inAppPurchaseHelper.getGmailAccount());
//email.setEnabled(false); // email.setEnabled(false);
//inAppPurchaseHelper.getPurchasedItemsAsync(); // inAppPurchaseHelper.getPurchasedItemsAsync();
inAppPurchaseHelper.getAvailableItemsForPurchaseAsync(); inAppPurchaseHelper.getAvailableItemsForPurchaseAsync();
} }
@Override @Override
public void onAvailableItemsForPurchaseQueryFinished(ArrayList<Purchasable> items) { public void onAvailableItemsForPurchaseQueryFinished(ArrayList<Purchasable> items) {
//purchasableItemsLayout.removeAllViews(); // purchasableItemsLayout.removeAllViews();
inProgress.setVisibility(View.GONE); inProgress.setVisibility(View.GONE);
purchasedItems = new ArrayList<>(); purchasedItems = new ArrayList<>();
for (Purchasable item : items) { for (Purchasable item : items) {
@ -154,8 +151,10 @@ public class InAppPurchaseActivity extends Activity implements InAppPurchaseList
inAppPurchaseHelper.getAvailableItemsForPurchaseAsync(); inAppPurchaseHelper.getAvailableItemsForPurchaseAsync();
} else { } else {
for (Purchasable purchasedItem : purchasedItems) { for (Purchasable purchasedItem : purchasedItems) {
Log.d("[In-app purchase] Found already bought item, expires " + purchasedItem.getExpireDate()); Log.d(
//displayRecoverAccountButton(purchasedItem); "[In-app purchase] Found already bought item, expires "
+ purchasedItem.getExpireDate());
// displayRecoverAccountButton(purchasedItem);
} }
} }
} }
@ -167,12 +166,18 @@ public class InAppPurchaseActivity extends Activity implements InAppPurchaseList
Purchasable item = LinphonePreferences.instance().getInAppPurchasedItem(); Purchasable item = LinphonePreferences.instance().getInAppPurchasedItem();
xmlRpcHelper.updateAccountExpireAsync(new XmlRpcListenerBase() { xmlRpcHelper.updateAccountExpireAsync(
@Override new XmlRpcListenerBase() {
public void onAccountExpireUpdated(String result) { @Override
//TODO public void onAccountExpireUpdated(String result) {
} // TODO
}, LinphonePreferences.instance().getAccountUsername(0), LinphonePreferences.instance().getAccountHa1(0), getString(R.string.default_domain), item.getPayload(), item.getPayloadSignature()); }
},
LinphonePreferences.instance().getAccountUsername(0),
LinphonePreferences.instance().getAccountHa1(0),
getString(R.string.default_domain),
item.getPayload(),
item.getPayloadSignature());
} }
} }
@ -193,19 +198,19 @@ public class InAppPurchaseActivity extends Activity implements InAppPurchaseList
} }
@Override @Override
public void onRecoverAccountSuccessful(boolean success) { public void onRecoverAccountSuccessful(boolean success) {}
}
@Override @Override
public void onError(final String error) { public void onError(final String error) {
Log.e(error); Log.e(error);
mHandler.post(new Runnable() { mHandler.post(
@Override new Runnable() {
public void run() { @Override
inProgress.setVisibility(View.GONE); public void run() {
Toast.makeText(InAppPurchaseActivity.this, error, Toast.LENGTH_LONG).show(); inProgress.setVisibility(View.GONE);
} Toast.makeText(InAppPurchaseActivity.this, error, Toast.LENGTH_LONG).show();
}); }
});
} }
@Override @Override

View file

@ -29,13 +29,11 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import java.util.Locale;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.settings.LinphonePreferences;
import java.util.Locale;
public class InAppPurchaseFragment extends Fragment implements View.OnClickListener { public class InAppPurchaseFragment extends Fragment implements View.OnClickListener {
private LinearLayout usernameLayout; private LinearLayout usernameLayout;
@ -47,8 +45,8 @@ public class InAppPurchaseFragment extends Fragment implements View.OnClickListe
private Button buyItemButton; private Button buyItemButton;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -61,13 +59,19 @@ public class InAppPurchaseFragment extends Fragment implements View.OnClickListe
displayBuySubscriptionButton(item); displayBuySubscriptionButton(item);
defaultEmail = InAppPurchaseActivity.instance().getGmailAccount(); defaultEmail = InAppPurchaseActivity.instance().getGmailAccount();
defaultUsername = LinphonePreferences.instance().getAccountUsername(LinphonePreferences.instance().getDefaultAccountIndex()); defaultUsername =
LinphonePreferences.instance()
.getAccountUsername(
LinphonePreferences.instance().getDefaultAccountIndex());
usernameLayout = view.findViewById(R.id.username_layout); usernameLayout = view.findViewById(R.id.username_layout);
username = view.findViewById(R.id.username); username = view.findViewById(R.id.username);
if (!getResources().getBoolean(R.bool.hide_username_in_inapp)) { if (!getResources().getBoolean(R.bool.hide_username_in_inapp)) {
usernameLayout.setVisibility(View.VISIBLE); usernameLayout.setVisibility(View.VISIBLE);
username.setText(LinphonePreferences.instance().getAccountUsername(LinphonePreferences.instance().getDefaultAccountIndex())); username.setText(
LinphonePreferences.instance()
.getAccountUsername(
LinphonePreferences.instance().getDefaultAccountIndex()));
addUsernameHandler(username, errorMessage); addUsernameHandler(username, errorMessage);
} else { } else {
@ -90,27 +94,25 @@ public class InAppPurchaseFragment extends Fragment implements View.OnClickListe
} }
private void addUsernameHandler(final EditText field, final TextView errorMessage) { private void addUsernameHandler(final EditText field, final TextView errorMessage) {
field.addTextChangedListener(new TextWatcher() { field.addTextChangedListener(
public void afterTextChanged(Editable s) { new TextWatcher() {
public void afterTextChanged(Editable s) {}
} public void beforeTextChanged(
CharSequence s, int start, int count, int after) {}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void onTextChanged(CharSequence s, int start, int count, int after) {
usernameOk = false;
} String username = s.toString();
if (isUsernameCorrect(username)) {
public void onTextChanged(CharSequence s, int start, int count, int after) { usernameOk = true;
usernameOk = false; errorMessage.setText("");
String username = s.toString(); } else {
if (isUsernameCorrect(username)) { errorMessage.setText(R.string.wizard_username_incorrect);
usernameOk = true; }
errorMessage.setText(""); if (buyItemButton != null) buyItemButton.setEnabled(usernameOk);
} else { }
errorMessage.setText(R.string.wizard_username_incorrect); });
}
if (buyItemButton != null) buyItemButton.setEnabled(usernameOk);
}
});
} }
private boolean isUsernameCorrect(String username) { private boolean isUsernameCorrect(String username) {
@ -137,4 +139,4 @@ public class InAppPurchaseFragment extends Fragment implements View.OnClickListe
username = lpc.normalizePhoneNumber(username); username = lpc.normalizePhoneNumber(username);
return username.toLowerCase(Locale.getDefault()); return username.toLowerCase(Locale.getDefault());
} }
} }

View file

@ -32,18 +32,15 @@ import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Patterns; import android.util.Patterns;
import com.android.vending.billing.IInAppBillingService; import com.android.vending.billing.IInAppBillingService;
import org.json.JSONException;
import org.json.JSONObject;
import org.linphone.settings.LinphonePreferences;
import org.linphone.mediastream.Log;
import org.linphone.xmlrpc.XmlRpcHelper;
import org.linphone.xmlrpc.XmlRpcListenerBase;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.json.JSONException;
import org.json.JSONObject;
import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.xmlrpc.XmlRpcHelper;
import org.linphone.xmlrpc.XmlRpcListenerBase;
public class InAppPurchaseHelper { public class InAppPurchaseHelper {
public static final int API_VERSION = 3; public static final int API_VERSION = 3;
@ -86,9 +83,12 @@ public class InAppPurchaseHelper {
public static final String PURCHASE_DETAILS_PAYLOAD = "developerPayload"; public static final String PURCHASE_DETAILS_PAYLOAD = "developerPayload";
public static final String PURCHASE_DETAILS_PURCHASE_TOKEN = "purchaseToken"; public static final String PURCHASE_DETAILS_PURCHASE_TOKEN = "purchaseToken";
public static final String CLIENT_ERROR_SUBSCRIPTION_PURCHASE_NOT_AVAILABLE = "SUBSCRIPTION_PURCHASE_NOT_AVAILABLE"; public static final String CLIENT_ERROR_SUBSCRIPTION_PURCHASE_NOT_AVAILABLE =
public static final String CLIENT_ERROR_BIND_TO_BILLING_SERVICE_FAILED = "BIND_TO_BILLING_SERVICE_FAILED"; "SUBSCRIPTION_PURCHASE_NOT_AVAILABLE";
public static final String CLIENT_ERROR_BILLING_SERVICE_UNAVAILABLE = "BILLING_SERVICE_UNAVAILABLE"; public static final String CLIENT_ERROR_BIND_TO_BILLING_SERVICE_FAILED =
"BIND_TO_BILLING_SERVICE_FAILED";
public static final String CLIENT_ERROR_BILLING_SERVICE_UNAVAILABLE =
"BILLING_SERVICE_UNAVAILABLE";
private Context mContext; private Context mContext;
private InAppPurchaseListener mListener; private InAppPurchaseListener mListener;
@ -97,6 +97,59 @@ public class InAppPurchaseHelper {
private Handler mHandler = new Handler(); private Handler mHandler = new Handler();
private String mGmailAccount; private String mGmailAccount;
public InAppPurchaseHelper(Activity context, InAppPurchaseListener listener) {
mContext = context;
mListener = listener;
mGmailAccount = getGmailAccount();
Log.d(
"[In-app purchase] creating InAppPurchaseHelper for context "
+ context.getLocalClassName());
mServiceConn =
new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("[In-app purchase] onServiceDisconnected!");
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("[In-app purchase] onServiceConnected!");
mService = IInAppBillingService.Stub.asInterface(service);
String packageName = mContext.getPackageName();
try {
int response =
mService.isBillingSupported(
API_VERSION, packageName, ITEM_TYPE_SUBS);
if (response != RESPONSE_RESULT_OK || mGmailAccount == null) {
Log.e("[In-app purchase] Error: Subscriptions aren't supported!");
mListener.onError(CLIENT_ERROR_SUBSCRIPTION_PURCHASE_NOT_AVAILABLE);
} else {
mListener.onServiceAvailableForQueries();
}
} catch (RemoteException e) {
Log.e(e);
}
}
};
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
boolean ok =
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
if (!ok) {
Log.e("[In-app purchase] Error: Bind service failed");
mListener.onError(CLIENT_ERROR_BIND_TO_BILLING_SERVICE_FAILED);
}
} else {
Log.e("[In-app purchase] Error: Billing service unavailable on device.");
mListener.onError(CLIENT_ERROR_BILLING_SERVICE_UNAVAILABLE);
}
}
private String responseCodeToErrorMessage(int responseCode) { private String responseCodeToErrorMessage(int responseCode) {
switch (responseCode) { switch (responseCode) {
case RESULT_USER_CANCELED: case RESULT_USER_CANCELED:
@ -119,54 +172,6 @@ public class InAppPurchaseHelper {
return "UNKNOWN_RESPONSE_CODE"; return "UNKNOWN_RESPONSE_CODE";
} }
public InAppPurchaseHelper(Activity context, InAppPurchaseListener listener) {
mContext = context;
mListener = listener;
mGmailAccount = getGmailAccount();
Log.d("[In-app purchase] creating InAppPurchaseHelper for context " + context.getLocalClassName());
mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("[In-app purchase] onServiceDisconnected!");
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("[In-app purchase] onServiceConnected!");
mService = IInAppBillingService.Stub.asInterface(service);
String packageName = mContext.getPackageName();
try {
int response = mService.isBillingSupported(API_VERSION, packageName, ITEM_TYPE_SUBS);
if (response != RESPONSE_RESULT_OK || mGmailAccount == null) {
Log.e("[In-app purchase] Error: Subscriptions aren't supported!");
mListener.onError(CLIENT_ERROR_SUBSCRIPTION_PURCHASE_NOT_AVAILABLE);
} else {
mListener.onServiceAvailableForQueries();
}
} catch (RemoteException e) {
Log.e(e);
}
}
};
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
boolean ok = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
if (!ok) {
Log.e("[In-app purchase] Error: Bind service failed");
mListener.onError(CLIENT_ERROR_BIND_TO_BILLING_SERVICE_FAILED);
}
} else {
Log.e("[In-app purchase] Error: Billing service unavailable on device.");
mListener.onError(CLIENT_ERROR_BILLING_SERVICE_UNAVAILABLE);
}
}
private ArrayList<Purchasable> getAvailableItemsForPurchase() { private ArrayList<Purchasable> getAvailableItemsForPurchase() {
ArrayList<Purchasable> products = new ArrayList<>(); ArrayList<Purchasable> products = new ArrayList<>();
ArrayList<String> skuList = LinphonePreferences.instance().getInAppPurchasables(); ArrayList<String> skuList = LinphonePreferences.instance().getInAppPurchasables();
@ -175,7 +180,9 @@ public class InAppPurchaseHelper {
Bundle skuDetails = null; Bundle skuDetails = null;
try { try {
skuDetails = mService.getSkuDetails(API_VERSION, mContext.getPackageName(), ITEM_TYPE_SUBS, querySkus); skuDetails =
mService.getSkuDetails(
API_VERSION, mContext.getPackageName(), ITEM_TYPE_SUBS, querySkus);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(e); Log.e(e);
} }
@ -192,7 +199,11 @@ public class InAppPurchaseHelper {
String title = object.getString(SKU_DETAILS_TITLE); String title = object.getString(SKU_DETAILS_TITLE);
String desc = object.getString(SKU_DETAILS_DESC); String desc = object.getString(SKU_DETAILS_DESC);
Purchasable purchasable = new Purchasable(id).setTitle(title).setDescription(desc).setPrice(price); Purchasable purchasable =
new Purchasable(id)
.setTitle(title)
.setDescription(desc)
.setPrice(price);
Log.w("Purchasable item " + purchasable.getDescription()); Log.w("Purchasable item " + purchasable.getDescription());
products.add(purchasable); products.add(purchasable);
} catch (JSONException e) { } catch (JSONException e) {
@ -200,7 +211,9 @@ public class InAppPurchaseHelper {
} }
} }
} else { } else {
Log.e("[In-app purchase] Error: responde code is not ok: " + responseCodeToErrorMessage(response)); Log.e(
"[In-app purchase] Error: responde code is not ok: "
+ responseCodeToErrorMessage(response));
mListener.onError(responseCodeToErrorMessage(response)); mListener.onError(responseCodeToErrorMessage(response));
} }
} }
@ -209,21 +222,27 @@ public class InAppPurchaseHelper {
} }
public void getAvailableItemsForPurchaseAsync() { public void getAvailableItemsForPurchaseAsync() {
new Thread(new Runnable() { new Thread(
public void run() { new Runnable() {
final ArrayList<Purchasable> items = getAvailableItemsForPurchase(); public void run() {
if (mHandler != null && mListener != null) { final ArrayList<Purchasable> items = getAvailableItemsForPurchase();
mHandler.post(new Runnable() { if (mHandler != null && mListener != null) {
public void run() { mHandler.post(
mListener.onAvailableItemsForPurchaseQueryFinished(items); new Runnable() {
} public void run() {
}); mListener
} .onAvailableItemsForPurchaseQueryFinished(
} items);
}).start(); }
});
}
}
})
.start();
} }
public void parseAndVerifyPurchaseItemResultAsync(int requestCode, int resultCode, Intent data) { public void parseAndVerifyPurchaseItemResultAsync(
int requestCode, int resultCode, Intent data) {
if (requestCode == ACTIVITY_RESULT_CODE_PURCHASE_ITEM) { if (requestCode == ACTIVITY_RESULT_CODE_PURCHASE_ITEM) {
int responseCode = data.getIntExtra(RESPONSE_CODE, 0); int responseCode = data.getIntExtra(RESPONSE_CODE, 0);
@ -236,12 +255,15 @@ public class InAppPurchaseHelper {
LinphonePreferences.instance().setInAppPurchasedItem(item); LinphonePreferences.instance().setInAppPurchasedItem(item);
XmlRpcHelper xmlRpcHelper = new XmlRpcHelper(); XmlRpcHelper xmlRpcHelper = new XmlRpcHelper();
xmlRpcHelper.verifySignatureAsync(new XmlRpcListenerBase() { xmlRpcHelper.verifySignatureAsync(
@Override new XmlRpcListenerBase() {
public void onSignatureVerified(boolean success) { @Override
mListener.onPurchasedItemConfirmationQueryFinished(success); public void onSignatureVerified(boolean success) {
} mListener.onPurchasedItemConfirmationQueryFinished(success);
}, payload, signature); }
},
payload,
signature);
} }
} }
} }
@ -249,7 +271,13 @@ public class InAppPurchaseHelper {
private void purchaseItem(String productId, String sipIdentity) { private void purchaseItem(String productId, String sipIdentity) {
Bundle buyIntentBundle = null; Bundle buyIntentBundle = null;
try { try {
buyIntentBundle = mService.getBuyIntent(API_VERSION, mContext.getPackageName(), productId, ITEM_TYPE_SUBS, sipIdentity); buyIntentBundle =
mService.getBuyIntent(
API_VERSION,
mContext.getPackageName(),
productId,
ITEM_TYPE_SUBS,
sipIdentity);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(e); Log.e(e);
} }
@ -258,7 +286,14 @@ public class InAppPurchaseHelper {
PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT); PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
if (pendingIntent != null) { if (pendingIntent != null) {
try { try {
((Activity) mContext).startIntentSenderForResult(pendingIntent.getIntentSender(), ACTIVITY_RESULT_CODE_PURCHASE_ITEM, new Intent(), 0, 0, 0); ((Activity) mContext)
.startIntentSenderForResult(
pendingIntent.getIntentSender(),
ACTIVITY_RESULT_CODE_PURCHASE_ITEM,
new Intent(),
0,
0,
0);
} catch (SendIntentException e) { } catch (SendIntentException e) {
Log.e(e); Log.e(e);
} }
@ -267,11 +302,13 @@ public class InAppPurchaseHelper {
} }
public void purchaseItemAsync(final String productId, final String sipIdentity) { public void purchaseItemAsync(final String productId, final String sipIdentity) {
new Thread(new Runnable() { new Thread(
public void run() { new Runnable() {
purchaseItem(productId, sipIdentity); public void run() {
} purchaseItem(productId, sipIdentity);
}).start(); }
})
.start();
} }
public void destroy() { public void destroy() {
@ -298,18 +335,18 @@ public class InAppPurchaseHelper {
private Purchasable verifySignature(String payload, String signature) { private Purchasable verifySignature(String payload, String signature) {
// TODO FIXME rework to be async // TODO FIXME rework to be async
/*XmlRpcHelper helper = new XmlRpcHelper(); /*XmlRpcHelper helper = new XmlRpcHelper();
if (helper.verifySignature(payload, signature)) { if (helper.verifySignature(payload, signature)) {
try { try {
JSONObject json = new JSONObject(payload); JSONObject json = new JSONObject(payload);
String productId = json.getString(PURCHASE_DETAILS_PRODUCT_ID); String productId = json.getString(PURCHASE_DETAILS_PRODUCT_ID);
Purchasable item = new Purchasable(productId); Purchasable item = new Purchasable(productId);
item.setPayloadAndSignature(payload, signature); item.setPayloadAndSignature(payload, signature);
return item; return item;
} catch (JSONException e) { } catch (JSONException e) {
Log.e(e); Log.e(e);
} }
}*/ }*/
return null; return null;
} }

View file

@ -28,10 +28,8 @@ import android.widget.AdapterView;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import org.linphone.R;
import java.util.List; import java.util.List;
import org.linphone.R;
public class InAppPurchaseListFragment extends Fragment implements AdapterView.OnItemClickListener { public class InAppPurchaseListFragment extends Fragment implements AdapterView.OnItemClickListener {
private ListView inappList; private ListView inappList;
@ -39,8 +37,8 @@ public class InAppPurchaseListFragment extends Fragment implements AdapterView.O
private List<Purchasable> mPurchasableItems; private List<Purchasable> mPurchasableItems;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mInflater = inflater; mInflater = inflater;
View view = inflater.inflate(R.layout.in_app_list, container, false); View view = inflater.inflate(R.layout.in_app_list, container, false);
@ -54,9 +52,14 @@ public class InAppPurchaseListFragment extends Fragment implements AdapterView.O
return view; return view;
} }
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Purchasable item = (Purchasable) view.getTag();
InAppPurchaseActivity.instance().displayPurchase(item);
}
class InAppListAdapter extends BaseAdapter { class InAppListAdapter extends BaseAdapter {
InAppListAdapter() { InAppListAdapter() {}
}
public int getCount() { public int getCount() {
return mPurchasableItems.size(); return mPurchasableItems.size();
@ -92,11 +95,4 @@ public class InAppPurchaseListFragment extends Fragment implements AdapterView.O
return view; return view;
} }
} }
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Purchasable item = (Purchasable) view.getTag();
InAppPurchaseActivity.instance().displayPurchase(item);
}
} }

View file

@ -21,9 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import java.util.ArrayList; import java.util.ArrayList;
public interface InAppPurchaseListener { public interface InAppPurchaseListener {
/** /** Callback called when the in-app purchase listener is connected and available for queries */
* Callback called when the in-app purchase listener is connected and available for queries
*/
void onServiceAvailableForQueries(); void onServiceAvailableForQueries();
/** /**

View file

@ -69,17 +69,17 @@ public class Purchasable {
return expire; return expire;
} }
public Purchasable setExpire(long expire) {
this.expire = expire;
return this;
}
public String getExpireDate() { public String getExpireDate() {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()); DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
Date date = new Date(expire); Date date = new Date(expire);
return dateFormat.format(date); return dateFormat.format(date);
} }
public Purchasable setExpire(long expire) {
this.expire = expire;
return this;
}
public Purchasable setPayloadAndSignature(String payload, String signature) { public Purchasable setPayloadAndSignature(String payload, String signature) {
this.purchasePayload = payload; this.purchasePayload = payload;
this.purchasePayloadSignature = signature; this.purchasePayloadSignature = signature;
@ -94,12 +94,12 @@ public class Purchasable {
return this.purchasePayloadSignature; return this.purchasePayloadSignature;
} }
public String getUserData() {
return this.userData;
}
public Purchasable setUserData(String data) { public Purchasable setUserData(String data) {
this.userData = data; this.userData = data;
return this; return this;
} }
public String getUserData() {
return this.userData;
}
} }

View file

@ -23,7 +23,6 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.Log; import android.util.Log;
import org.linphone.settings.LinphonePreferences; import org.linphone.settings.LinphonePreferences;
public class AccountEnableReceiver extends BroadcastReceiver { public class AccountEnableReceiver extends BroadcastReceiver {
@ -35,10 +34,14 @@ public class AccountEnableReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
int prefsAccountIndex = (int) (long) intent.getLongExtra(FIELD_ID, -1); int prefsAccountIndex = (int) (long) intent.getLongExtra(FIELD_ID, -1);
boolean enable = intent.getBooleanExtra(FIELD_ACTIVE, true); boolean enable = intent.getBooleanExtra(FIELD_ACTIVE, true);
Log.i(TAG, "Received broadcast for index=" + Integer.toString(prefsAccountIndex) + ",enable=" + Boolean.toString(enable)); Log.i(
if (prefsAccountIndex < 0 || prefsAccountIndex >= LinphonePreferences.instance().getAccountCount()) TAG,
return; "Received broadcast for index="
+ Integer.toString(prefsAccountIndex)
+ ",enable="
+ Boolean.toString(enable));
if (prefsAccountIndex < 0
|| prefsAccountIndex >= LinphonePreferences.instance().getAccountCount()) return;
LinphonePreferences.instance().setAccountEnabled(prefsAccountIndex, enable); LinphonePreferences.instance().setAccountEnabled(prefsAccountIndex, enable);
} }
} }

View file

@ -28,13 +28,11 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.media.AudioManager; import android.media.AudioManager;
import java.util.List;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.call.CallActivity; import org.linphone.call.CallActivity;
import java.util.List;
public class BluetoothManager extends BroadcastReceiver { public class BluetoothManager extends BroadcastReceiver {
private static BluetoothManager instance; private static BluetoothManager instance;
@ -47,6 +45,16 @@ public class BluetoothManager extends BroadcastReceiver {
private boolean isBluetoothConnected; private boolean isBluetoothConnected;
private boolean isScoConnected; private boolean isScoConnected;
public BluetoothManager() {
isBluetoothConnected = false;
if (!ensureInit()) {
android.util.Log.w(
"BluetoothManager",
"[Bluetooth] Manager tried to init but LinphoneService not ready yet...");
}
instance = this;
}
public static BluetoothManager getInstance() { public static BluetoothManager getInstance() {
if (instance == null) { if (instance == null) {
instance = new BluetoothManager(); instance = new BluetoothManager();
@ -54,22 +62,19 @@ public class BluetoothManager extends BroadcastReceiver {
return instance; return instance;
} }
public BluetoothManager() {
isBluetoothConnected = false;
if (!ensureInit()) {
android.util.Log.w("BluetoothManager", "[Bluetooth] Manager tried to init but LinphoneService not ready yet...");
}
instance = this;
}
public void initBluetooth() { public void initBluetooth() {
if (!ensureInit()) { if (!ensureInit()) {
android.util.Log.w("BluetoothManager", "[Bluetooth] Manager tried to init bluetooth but LinphoneService not ready yet..."); android.util.Log.w(
"BluetoothManager",
"[Bluetooth] Manager tried to init bluetooth but LinphoneService not ready yet...");
return; return;
} }
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.PLANTRONICS); filter.addCategory(
BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY
+ "."
+ BluetoothAssignedNumbers.PLANTRONICS);
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT); filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
@ -89,29 +94,36 @@ public class BluetoothManager extends BroadcastReceiver {
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) { if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
if (mProfileListener != null) { if (mProfileListener != null) {
android.util.Log.w("BluetoothManager", "[Bluetooth] Headset profile was already opened, let's close it"); android.util.Log.w(
"BluetoothManager",
"[Bluetooth] Headset profile was already opened, let's close it");
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
} }
mProfileListener = new BluetoothProfile.ServiceListener() { mProfileListener =
public void onServiceConnected(int profile, BluetoothProfile proxy) { new BluetoothProfile.ServiceListener() {
if (profile == BluetoothProfile.HEADSET) { public void onServiceConnected(int profile, BluetoothProfile proxy) {
android.util.Log.d("BluetoothManager", "[Bluetooth] Headset connected"); if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy; android.util.Log.d(
isBluetoothConnected = true; "BluetoothManager", "[Bluetooth] Headset connected");
} mBluetoothHeadset = (BluetoothHeadset) proxy;
} isBluetoothConnected = true;
}
}
public void onServiceDisconnected(int profile) { public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) { if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null; mBluetoothHeadset = null;
isBluetoothConnected = false; isBluetoothConnected = false;
android.util.Log.d("BluetoothManager", "[Bluetooth] Headset disconnected"); android.util.Log.d(
LinphoneManager.getInstance().routeAudioToReceiver(); "BluetoothManager", "[Bluetooth] Headset disconnected");
} LinphoneManager.getInstance().routeAudioToReceiver();
} }
}; }
boolean success = mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET); };
boolean success =
mBluetoothAdapter.getProfileProxy(
mContext, mProfileListener, BluetoothProfile.HEADSET);
if (!success) { if (!success) {
android.util.Log.e("BluetoothManager", "[Bluetooth] getProfileProxy failed !"); android.util.Log.e("BluetoothManager", "[Bluetooth] getProfileProxy failed !");
} }
@ -146,7 +158,10 @@ public class BluetoothManager extends BroadcastReceiver {
public boolean routeAudioToBluetooth() { public boolean routeAudioToBluetooth() {
ensureInit(); ensureInit();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager != null && mAudioManager.isBluetoothScoAvailableOffCall()) { if (mBluetoothAdapter != null
&& mBluetoothAdapter.isEnabled()
&& mAudioManager != null
&& mAudioManager.isBluetoothScoAvailableOffCall()) {
if (isBluetoothHeadsetAvailable()) { if (isBluetoothHeadsetAvailable()) {
if (mAudioManager != null && !mAudioManager.isBluetoothScoOn()) { if (mAudioManager != null && !mAudioManager.isBluetoothScoOn()) {
android.util.Log.d("BluetoothManager", "[Bluetooth] SCO off, let's start it"); android.util.Log.d("BluetoothManager", "[Bluetooth] SCO off, let's start it");
@ -177,7 +192,9 @@ public class BluetoothManager extends BroadcastReceiver {
} }
if (ok) { if (ok) {
if (retries > 0) { if (retries > 0) {
android.util.Log.d("BluetoothManager", "[Bluetooth] Audio route ok after " + retries + " retries"); android.util.Log.d(
"BluetoothManager",
"[Bluetooth] Audio route ok after " + retries + " retries");
} else { } else {
android.util.Log.d("BluetoothManager", "[Bluetooth] Audio route ok"); android.util.Log.d("BluetoothManager", "[Bluetooth] Audio route ok");
} }
@ -192,24 +209,34 @@ public class BluetoothManager extends BroadcastReceiver {
} }
public boolean isUsingBluetoothAudioRoute() { public boolean isUsingBluetoothAudioRoute() {
return mBluetoothHeadset != null && mBluetoothHeadset.isAudioConnected(mBluetoothDevice) && isScoConnected; return mBluetoothHeadset != null
&& mBluetoothHeadset.isAudioConnected(mBluetoothDevice)
&& isScoConnected;
} }
public boolean isBluetoothHeadsetAvailable() { public boolean isBluetoothHeadsetAvailable() {
ensureInit(); ensureInit();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager != null && mAudioManager.isBluetoothScoAvailableOffCall()) { if (mBluetoothAdapter != null
&& mBluetoothAdapter.isEnabled()
&& mAudioManager != null
&& mAudioManager.isBluetoothScoAvailableOffCall()) {
boolean isHeadsetConnected = false; boolean isHeadsetConnected = false;
if (mBluetoothHeadset != null) { if (mBluetoothHeadset != null) {
List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices(); List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
mBluetoothDevice = null; mBluetoothDevice = null;
for (final BluetoothDevice dev : devices) { for (final BluetoothDevice dev : devices) {
if (mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED) { if (mBluetoothHeadset.getConnectionState(dev)
== BluetoothHeadset.STATE_CONNECTED) {
mBluetoothDevice = dev; mBluetoothDevice = dev;
isHeadsetConnected = true; isHeadsetConnected = true;
break; break;
} }
} }
android.util.Log.d("BluetoothManager", isHeadsetConnected ? "[Bluetooth] Headset found, bluetooth audio route available" : "[Bluetooth] No headset found, bluetooth audio route unavailable"); android.util.Log.d(
"BluetoothManager",
isHeadsetConnected
? "[Bluetooth] Headset found, bluetooth audio route available"
: "[Bluetooth] No headset found, bluetooth audio route unavailable");
} }
return isHeadsetConnected; return isHeadsetConnected;
} }
@ -275,30 +302,32 @@ public class BluetoothManager extends BroadcastReceiver {
} }
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (!LinphoneManager.isInstanciated()) if (!LinphoneManager.isInstanciated()) return;
return;
String action = intent.getAction(); String action = intent.getAction();
if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(action)) { if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(action)) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0); int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: connected"); android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: connected");
// LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH); // LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH);
isScoConnected = true; isScoConnected = true;
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: disconnected"); android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: disconnected");
// LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER); // LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER);
isScoConnected = false; isScoConnected = false;
} else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) { } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) {
android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: connecting"); android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: connecting");
// LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH); // LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH);
isScoConnected = true; isScoConnected = true;
} else { } else {
android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: " + state); android.util.Log.d("BluetoothManager", "[Bluetooth] SCO state: " + state);
} }
refreshCallView(); refreshCallView();
} else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.STATE_DISCONNECTED); int state =
intent.getIntExtra(
BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
if (state == 0) { if (state == 0) {
android.util.Log.d("BluetoothManager", "[Bluetooth] State: disconnected"); android.util.Log.d("BluetoothManager", "[Bluetooth] State: disconnected");
stopBluetooth(); stopBluetooth();
@ -308,22 +337,41 @@ public class BluetoothManager extends BroadcastReceiver {
} else { } else {
android.util.Log.d("BluetoothManager", "[Bluetooth] State: " + state); android.util.Log.d("BluetoothManager", "[Bluetooth] State: " + state);
} }
} else if (intent.getAction().equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) { } else if (intent.getAction()
String command = intent.getExtras().getString(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD); .equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) {
//int type = intent.getExtras().getInt(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE); String command =
intent.getExtras()
.getString(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD);
// int type =
// intent.getExtras().getInt(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE);
Object[] args = (Object[]) intent.getExtras().get(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS); Object[] args =
(Object[])
intent.getExtras()
.get(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS);
if (args.length <= 0) { if (args.length <= 0) {
android.util.Log.d("BluetoothManager", "[Bluetooth] Event: " + command + ", no args"); android.util.Log.d(
"BluetoothManager", "[Bluetooth] Event: " + command + ", no args");
return; return;
} }
String eventName = (args[0]).toString(); String eventName = (args[0]).toString();
if (eventName.equals("BUTTON") && args.length >= 3) { if (eventName.equals("BUTTON") && args.length >= 3) {
String buttonID = args[1].toString(); String buttonID = args[1].toString();
String mode = args[2].toString(); String mode = args[2].toString();
android.util.Log.d("BluetoothManager", "[Bluetooth] Event: " + command + " : " + eventName + ", id = " + buttonID + " (" + mode + ")"); android.util.Log.d(
"BluetoothManager",
"[Bluetooth] Event: "
+ command
+ " : "
+ eventName
+ ", id = "
+ buttonID
+ " ("
+ mode
+ ")");
} else { } else {
android.util.Log.d("BluetoothManager", "[Bluetooth] Event: " + command + " : " + eventName); android.util.Log.d(
"BluetoothManager", "[Bluetooth] Event: " + command + " : " + eventName);
} }
} }
} }

View file

@ -22,11 +22,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.compatibility.Compatibility; import org.linphone.compatibility.Compatibility;
import org.linphone.settings.LinphonePreferences;
public class BootReceiver extends BroadcastReceiver { public class BootReceiver extends BroadcastReceiver {
@ -34,11 +33,14 @@ public class BootReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
LinphonePreferences.instance().setContext(context); LinphonePreferences.instance().setContext(context);
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SHUTDOWN)) { if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SHUTDOWN)) {
android.util.Log.d("LinphoneBootReceiver", "Device is shutting down, destroying Core to unregister"); android.util.Log.d(
"LinphoneBootReceiver",
"Device is shutting down, destroying Core to unregister");
LinphoneManager.destroy(); LinphoneManager.destroy();
} else { } else {
boolean autostart = LinphonePreferences.instance().isAutoStartEnabled(); boolean autostart = LinphonePreferences.instance().isAutoStartEnabled();
android.util.Log.i("LinphoneBootReceiver", "Device is starting, auto_start is " + autostart); android.util.Log.i(
"LinphoneBootReceiver", "Device is starting, auto_start is " + autostart);
if (autostart && !LinphoneService.isReady()) { if (autostart && !LinphoneService.isReady()) {
Intent lLinphoneServiceIntent = new Intent(Intent.ACTION_MAIN); Intent lLinphoneServiceIntent = new Intent(Intent.ACTION_MAIN);
lLinphoneServiceIntent.setClass(context, LinphoneService.class); lLinphoneServiceIntent.setClass(context, LinphoneService.class);

View file

@ -23,14 +23,13 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.PowerManager; import android.os.PowerManager;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
/* /*
* Purpose of this receiver is to disable keep alives when device is on idle * Purpose of this receiver is to disable keep alives when device is on idle

View file

@ -23,27 +23,24 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
public class HookReceiver extends BroadcastReceiver { public class HookReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (isOrderedBroadcast()) if (isOrderedBroadcast()) abortBroadcast();
abortBroadcast();
Bundle extras = intent.getExtras(); Bundle extras = intent.getExtras();
boolean b = extras.getBoolean("hookoff"); boolean b = extras.getBoolean("hookoff");
if (b) { if (b) {
//handset on // handset on
Log.i(" ======>>>>>> HookReceiver - handset ON"); Log.i(" ======>>>>>> HookReceiver - handset ON");
LinphoneManager.getInstance().enableSpeaker(false); LinphoneManager.getInstance().enableSpeaker(false);
if (!LinphoneManager.getInstance().isHansetModeOn()) if (!LinphoneManager.getInstance().isHansetModeOn())
LinphoneManager.getInstance().setHandsetMode(true); LinphoneManager.getInstance().setHandsetMode(true);
} else { } else {
//handset off // handset off
Log.i(" ======>>>>>> HookReceiver - handset OFF"); Log.i(" ======>>>>>> HookReceiver - handset OFF");
LinphoneManager.getInstance().enableSpeaker(true); LinphoneManager.getInstance().enableSpeaker(true);
LinphoneManager.getInstance().setHandsetMode(false); LinphoneManager.getInstance().setHandsetMode(false);

View file

@ -25,14 +25,13 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.SystemClock; import android.os.SystemClock;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.settings.LinphonePreferences;
import org.linphone.LinphoneService; import org.linphone.LinphoneService;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.Core; import org.linphone.core.Core;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
/* /*
* Purpose of this receiver is to disable keep alives when screen is off * Purpose of this receiver is to disable keep alives when screen is off
@ -52,18 +51,25 @@ public class KeepAliveReceiver extends BroadcastReceiver {
if (action == null) { if (action == null) {
Log.i("[KeepAlive] Refresh registers"); Log.i("[KeepAlive] Refresh registers");
lc.refreshRegisters(); lc.refreshRegisters();
//make sure iterate will have enough time, device will not sleep until exit from this method // make sure iterate will have enough time, device will not sleep until exit from
// this method
try { try {
Thread.sleep(2000); Thread.sleep(2000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e("Cannot sleep for 2s", e); Log.e("Cannot sleep for 2s", e);
} finally { } finally {
//make sure the application will at least wakes up every 10 mn // make sure the application will at least wakes up every 10 mn
Intent newIntent = new Intent(context, KeepAliveReceiver.class); Intent newIntent = new Intent(context, KeepAliveReceiver.class);
PendingIntent keepAlivePendingIntent = PendingIntent.getBroadcast(context, 0, newIntent, PendingIntent.FLAG_ONE_SHOT); PendingIntent keepAlivePendingIntent =
PendingIntent.getBroadcast(
context, 0, newIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)); AlarmManager alarmManager =
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 600000, keepAlivePendingIntent); ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
alarmManager.setExact(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 600000,
keepAlivePendingIntent);
} }
} else if (action.equalsIgnoreCase(Intent.ACTION_SCREEN_ON)) { } else if (action.equalsIgnoreCase(Intent.ACTION_SCREEN_ON)) {
Log.i("[KeepAlive] Screen is on, enable"); Log.i("[KeepAlive] Screen is on, enable");

View file

@ -23,21 +23,19 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
/** /** Intercept network state changes and update linphone core through LinphoneManager. */
* Intercept network state changes and update linphone core through LinphoneManager.
*/
public class NetworkManager extends BroadcastReceiver { public class NetworkManager extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager cm =
Boolean lNoConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Boolean lNoConnectivity =
intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (LinphoneManager.isInstanciated()) { if (LinphoneManager.isInstanciated()) {
LinphoneManager.getInstance().connectivityChanged(cm, lNoConnectivity); LinphoneManager.getInstance().connectivityChanged(cm, lNoConnectivity);
} }
} }
} }

View file

@ -19,18 +19,16 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.Log; import android.util.Log;
import org.linphone.settings.LinphonePreferences; import org.linphone.settings.LinphonePreferences;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
public class OutgoingCallReceiver extends BroadcastReceiver { public class OutgoingCallReceiver extends BroadcastReceiver {
private final static String TAG = "CallHandler"; private static final String TAG = "CallHandler";
private final String ACTION_CALL_LINPHONE = "org.linphone.intent.action.CallLaunched"; private final String ACTION_CALL_LINPHONE = "org.linphone.intent.action.CallLaunched";
private LinphonePreferences mPrefs; private LinphonePreferences mPrefs;
@ -53,4 +51,4 @@ public class OutgoingCallReceiver extends BroadcastReceiver {
} }
} }
} }
} }

View file

@ -23,22 +23,19 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.core.Core; import org.linphone.core.Core;
/** /** Pause current SIP calls when GSM phone rings or is active. */
* Pause current SIP calls when GSM phone rings or is active.
*/
public class PhoneStateChangedReceiver extends BroadcastReceiver { public class PhoneStateChangedReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
final String extraState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); final String extraState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (!LinphoneManager.isInstanciated()) if (!LinphoneManager.isInstanciated()) return;
return;
if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(extraState) || TelephonyManager.EXTRA_STATE_RINGING.equals(extraState)) { if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(extraState)
|| TelephonyManager.EXTRA_STATE_RINGING.equals(extraState)) {
LinphoneManager.getInstance().setCallGsmON(true); LinphoneManager.getInstance().setCallGsmON(true);
Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
lc.pauseAllCalls(); lc.pauseAllCalls();

View file

@ -22,20 +22,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import org.linphone.LinphoneManager;
import org.linphone.core.Player;
import org.linphone.core.PlayerListener;
import org.linphone.mediastream.Log;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.linphone.LinphoneManager;
import org.linphone.core.Player;
import org.linphone.core.PlayerListener;
import org.linphone.mediastream.Log;
public class Recording implements PlayerListener, Comparable<Recording> { public class Recording implements PlayerListener, Comparable<Recording> {
public static final Pattern RECORD_PATTERN =
Pattern.compile(".*/(.*)_(\\d{2}-\\d{2}-\\d{4}-\\d{2}-\\d{2}-\\d{2})\\..*");
private String recordPath, name; private String recordPath, name;
private Date recordDate; private Date recordDate;
private Player player; private Player player;
@ -43,8 +43,6 @@ public class Recording implements PlayerListener, Comparable<Recording> {
private Handler handler; private Handler handler;
private Runnable updateCurrentPositionTimer; private Runnable updateCurrentPositionTimer;
public static final Pattern RECORD_PATTERN = Pattern.compile(".*/(.*)_(\\d{2}-\\d{2}-\\d{4}-\\d{2}-\\d{2}-\\d{2})\\..*");
@SuppressLint("SimpleDateFormat") @SuppressLint("SimpleDateFormat")
public Recording(Context context, String recordPath) { public Recording(Context context, String recordPath) {
this.recordPath = recordPath; this.recordPath = recordPath;
@ -61,13 +59,14 @@ public class Recording implements PlayerListener, Comparable<Recording> {
} }
handler = new Handler(context.getMainLooper()); handler = new Handler(context.getMainLooper());
updateCurrentPositionTimer = new Runnable() { updateCurrentPositionTimer =
@Override new Runnable() {
public void run() { @Override
if (listener != null) listener.currentPositionChanged(getCurrentPosition()); public void run() {
if (isPlaying()) handler.postDelayed(updateCurrentPositionTimer, 20); if (listener != null) listener.currentPositionChanged(getCurrentPosition());
} if (isPlaying()) handler.postDelayed(updateCurrentPositionTimer, 20);
}; }
};
player = LinphoneManager.getLc().createLocalPlayer(null, null, null); player = LinphoneManager.getLc().createLocalPlayer(null, null, null);
player.setListener(this); player.setListener(this);

View file

@ -21,28 +21,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.SeekBar; import android.widget.SeekBar;
import androidx.annotation.NonNull;
import org.linphone.R;
import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.linphone.R;
import org.linphone.utils.SelectableAdapter;
import org.linphone.utils.SelectableHelper;
public class RecordingAdapter extends SelectableAdapter<RecordingViewHolder> { public class RecordingAdapter extends SelectableAdapter<RecordingViewHolder> {
private List<Recording> recordings; private List<Recording> recordings;
private Context context; private Context context;
private RecordingViewHolder.ClickListener clickListener; private RecordingViewHolder.ClickListener clickListener;
public RecordingAdapter(Context context, List<Recording> recordings, RecordingViewHolder.ClickListener listener, SelectableHelper helper) { public RecordingAdapter(
Context context,
List<Recording> recordings,
RecordingViewHolder.ClickListener listener,
SelectableHelper helper) {
super(helper); super(helper);
this.recordings = recordings; this.recordings = recordings;
@ -58,7 +60,9 @@ public class RecordingAdapter extends SelectableAdapter<RecordingViewHolder> {
@NonNull @NonNull
@Override @Override
public RecordingViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { public RecordingViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recording_cell, viewGroup, false); View v =
LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recording_cell, viewGroup, false);
return new RecordingViewHolder(v, clickListener); return new RecordingViewHolder(v, clickListener);
} }
@ -95,87 +99,101 @@ public class RecordingAdapter extends SelectableAdapter<RecordingViewHolder> {
} else { } else {
viewHolder.playButton.setImageResource(R.drawable.record_play); viewHolder.playButton.setImageResource(R.drawable.record_play);
} }
viewHolder.playButton.setOnClickListener(new View.OnClickListener() { viewHolder.playButton.setOnClickListener(
@Override new View.OnClickListener() {
public void onClick(View v) { @Override
if (record.isPaused()) { public void onClick(View v) {
record.play(); if (record.isPaused()) {
viewHolder.playButton.setImageResource(R.drawable.record_pause); record.play();
} else { viewHolder.playButton.setImageResource(R.drawable.record_pause);
record.pause(); } else {
viewHolder.playButton.setImageResource(R.drawable.record_play); record.pause();
} viewHolder.playButton.setImageResource(R.drawable.record_play);
} }
}); }
});
viewHolder.name.setText(record.getName()); viewHolder.name.setText(record.getName());
viewHolder.date.setText(new SimpleDateFormat("HH:mm").format(record.getRecordDate())); viewHolder.date.setText(new SimpleDateFormat("HH:mm").format(record.getRecordDate()));
int position = record.getCurrentPosition(); int position = record.getCurrentPosition();
viewHolder.currentPosition.setText(String.format("%02d:%02d", viewHolder.currentPosition.setText(
TimeUnit.MILLISECONDS.toMinutes(position), String.format(
TimeUnit.MILLISECONDS.toSeconds(position) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(position)) "%02d:%02d",
)); TimeUnit.MILLISECONDS.toMinutes(position),
TimeUnit.MILLISECONDS.toSeconds(position)
- TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(position))));
int duration = record.getDuration(); int duration = record.getDuration();
viewHolder.duration.setText(String.format("%02d:%02d", viewHolder.duration.setText(
TimeUnit.MILLISECONDS.toMinutes(duration), String.format(
TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)) "%02d:%02d",
)); TimeUnit.MILLISECONDS.toMinutes(duration),
TimeUnit.MILLISECONDS.toSeconds(duration)
- TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(duration))));
viewHolder.progressionBar.setMax(record.getDuration()); viewHolder.progressionBar.setMax(record.getDuration());
viewHolder.progressionBar.setProgress(0); viewHolder.progressionBar.setProgress(0);
viewHolder.progressionBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { viewHolder.progressionBar.setOnSeekBarChangeListener(
@Override new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { @Override
if (fromUser) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int progressToSet = progress > 0 && progress < seekBar.getMax() ? progress : 0; if (fromUser) {
int progressToSet =
progress > 0 && progress < seekBar.getMax() ? progress : 0;
if (progress == seekBar.getMax()) { if (progress == seekBar.getMax()) {
if (record.isPlaying()) record.pause(); if (record.isPlaying()) record.pause();
}
record.seek(progressToSet);
seekBar.setProgress(progressToSet);
int currentPosition = record.getCurrentPosition();
viewHolder.currentPosition.setText(
String.format(
"%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(currentPosition),
TimeUnit.MILLISECONDS.toSeconds(currentPosition)
- TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(
currentPosition))));
}
} }
record.seek(progressToSet); @Override
seekBar.setProgress(progressToSet); public void onStartTrackingTouch(SeekBar seekBar) {}
int currentPosition = record.getCurrentPosition(); @Override
viewHolder.currentPosition.setText(String.format("%02d:%02d", public void onStopTrackingTouch(SeekBar seekBar) {}
TimeUnit.MILLISECONDS.toMinutes(currentPosition), });
TimeUnit.MILLISECONDS.toSeconds(currentPosition) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(currentPosition))
));
}
}
@Override record.setRecordingListener(
public void onStartTrackingTouch(SeekBar seekBar) { new RecordingListener() {
@Override
public void currentPositionChanged(int currentPosition) {
viewHolder.currentPosition.setText(
String.format(
"%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(currentPosition),
TimeUnit.MILLISECONDS.toSeconds(currentPosition)
- TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(
currentPosition))));
viewHolder.progressionBar.setProgress(currentPosition);
}
} @Override
public void endOfRecordReached() {
@Override record.pause();
public void onStopTrackingTouch(SeekBar seekBar) { record.seek(0);
viewHolder.progressionBar.setProgress(0);
} viewHolder.currentPosition.setText("00:00");
}); viewHolder.playButton.setImageResource(R.drawable.record_play);
}
record.setRecordingListener(new RecordingListener() { });
@Override
public void currentPositionChanged(int currentPosition) {
viewHolder.currentPosition.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(currentPosition),
TimeUnit.MILLISECONDS.toSeconds(currentPosition) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(currentPosition))
));
viewHolder.progressionBar.setProgress(currentPosition);
}
@Override
public void endOfRecordReached() {
record.pause();
record.seek(0);
viewHolder.progressionBar.setProgress(0);
viewHolder.currentPosition.setText("00:00");
viewHolder.playButton.setImageResource(R.drawable.record_play);
}
});
} }
@Override @Override
@ -191,7 +209,9 @@ public class RecordingAdapter extends SelectableAdapter<RecordingViewHolder> {
} else if (isYesterday(cal)) { } else if (isYesterday(cal)) {
return context.getString(R.string.yesterday); return context.getString(R.string.yesterday);
} else { } else {
dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.history_date_format)); dateFormat =
new SimpleDateFormat(
context.getResources().getString(R.string.history_date_format));
} }
return dateFormat.format(cal.getTime()); return dateFormat.format(cal.getTime());
@ -202,9 +222,9 @@ public class RecordingAdapter extends SelectableAdapter<RecordingViewHolder> {
return false; return false;
} }
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)); && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
} }
private boolean isToday(Calendar cal) { private boolean isToday(Calendar cal) {

View file

@ -22,15 +22,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager; import org.linphone.LinphoneManager;
import org.linphone.R; import org.linphone.R;
@ -38,12 +41,10 @@ import org.linphone.fragments.FragmentsAvailable;
import org.linphone.utils.FileUtils; import org.linphone.utils.FileUtils;
import org.linphone.utils.SelectableHelper; import org.linphone.utils.SelectableHelper;
import java.io.File; public class RecordingListFragment extends Fragment
import java.util.ArrayList; implements AdapterView.OnItemClickListener,
import java.util.Collections; RecordingViewHolder.ClickListener,
import java.util.List; SelectableHelper.DeleteListener {
public class RecordingListFragment extends Fragment implements AdapterView.OnItemClickListener, RecordingViewHolder.ClickListener, SelectableHelper.DeleteListener {
private RecyclerView recordingList; private RecyclerView recordingList;
private List<Recording> recordings; private List<Recording> recordings;
private TextView noRecordings; private TextView noRecordings;
@ -53,8 +54,8 @@ public class RecordingListFragment extends Fragment implements AdapterView.OnIte
private SelectableHelper selectableHelper; private SelectableHelper selectableHelper;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(
Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recordings_list, container, false); View view = inflater.inflate(R.layout.recordings_list, container, false);
context = getActivity().getApplicationContext(); context = getActivity().getApplicationContext();
@ -66,9 +67,10 @@ public class RecordingListFragment extends Fragment implements AdapterView.OnIte
layoutManager = new LinearLayoutManager(context); layoutManager = new LinearLayoutManager(context);
recordingList.setLayoutManager(layoutManager); recordingList.setLayoutManager(layoutManager);
//Divider between items // Divider between items
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recordingList.getContext(), DividerItemDecoration dividerItemDecoration =
layoutManager.getOrientation()); new DividerItemDecoration(
recordingList.getContext(), layoutManager.getOrientation());
dividerItemDecoration.setDrawable(context.getResources().getDrawable(R.drawable.divider)); dividerItemDecoration.setDrawable(context.getResources().getDrawable(R.drawable.divider));
recordingList.addItemDecoration(dividerItemDecoration); recordingList.addItemDecoration(dividerItemDecoration);
@ -94,9 +96,9 @@ public class RecordingListFragment extends Fragment implements AdapterView.OnIte
if (directory.exists() && directory.isDirectory()) { if (directory.exists() && directory.isDirectory()) {
File[] existingRecordings = directory.listFiles(); File[] existingRecordings = directory.listFiles();
for(Recording r : recordings) { for (Recording r : recordings) {
boolean exists = false; boolean exists = false;
for(File f : existingRecordings) { for (File f : existingRecordings) {
if (f.getPath().equals(r.getRecordPath())) { if (f.getPath().equals(r.getRecordPath())) {
exists = true; exists = true;
break; break;
@ -117,9 +119,9 @@ public class RecordingListFragment extends Fragment implements AdapterView.OnIte
if (directory.exists() && directory.isDirectory()) { if (directory.exists() && directory.isDirectory()) {
File[] existingRecordings = directory.listFiles(); File[] existingRecordings = directory.listFiles();
for(File f : existingRecordings) { for (File f : existingRecordings) {
boolean exists = false; boolean exists = false;
for(Recording r : recordings) { for (Recording r : recordings) {
if (r.getRecordPath().equals(f.getPath())) { if (r.getRecordPath().equals(f.getPath())) {
exists = true; exists = true;
break; break;
@ -141,7 +143,8 @@ public class RecordingListFragment extends Fragment implements AdapterView.OnIte
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
// This is necessary, without it you won't be able to remove recordings as you won't be allowed to. // This is necessary, without it you won't be able to remove recordings as you won't be
// allowed to.
LinphoneActivity.instance().checkAndRequestExternalStoragePermission(); LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
LinphoneManager.getInstance().setAudioManagerModeNormal(); LinphoneManager.getInstance().setAudioManagerModeNormal();
@ -155,7 +158,9 @@ public class RecordingListFragment extends Fragment implements AdapterView.OnIte
searchForRecordings(); searchForRecordings();
hideRecordingListAndDisplayMessageIfEmpty(); hideRecordingListAndDisplayMessageIfEmpty();
recordingAdapter = new RecordingAdapter(getActivity().getApplicationContext(), recordings, this, selectableHelper); recordingAdapter =
new RecordingAdapter(
getActivity().getApplicationContext(), recordings, this, selectableHelper);
recordingList.setAdapter(recordingAdapter); recordingList.setAdapter(recordingAdapter);
selectableHelper.setAdapter(recordingAdapter); selectableHelper.setAdapter(recordingAdapter);
selectableHelper.setDialogMessage(R.string.recordings_delete_dialog); selectableHelper.setDialogMessage(R.string.recordings_delete_dialog);

View file

@ -1,36 +1,35 @@
package org.linphone.recording; package org.linphone.recording;
/* /*
RecordingViewHolder.java RecordingViewHolder.java
Copyright (C) 2018 Belledonne Communications, Grenoble, France Copyright (C) 2018 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import org.linphone.R; import org.linphone.R;
public class RecordingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { public class RecordingViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
public ImageView playButton; public ImageView playButton;
public TextView name, date, currentPosition, duration; public TextView name, date, currentPosition, duration;
public SeekBar progressionBar; public SeekBar progressionBar;

View file

@ -30,12 +30,11 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory; import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.view.WindowManager; import android.view.WindowManager;
import java.util.ArrayList;
import org.linphone.LinphoneManager; import java.util.List;
import org.linphone.settings.LinphonePreferences.AccountBuilder;
import org.linphone.utils.LinphoneUtils;
import org.linphone.R;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.assistant.AssistantActivity; import org.linphone.assistant.AssistantActivity;
import org.linphone.core.AccountCreator; import org.linphone.core.AccountCreator;
import org.linphone.core.AccountCreatorListener; import org.linphone.core.AccountCreatorListener;
@ -44,17 +43,276 @@ import org.linphone.core.NatPolicy;
import org.linphone.core.ProxyConfig; import org.linphone.core.ProxyConfig;
import org.linphone.fragments.FragmentsAvailable; import org.linphone.fragments.FragmentsAvailable;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import org.linphone.settings.LinphonePreferences.AccountBuilder;
import org.linphone.utils.LinphoneUtils;
import java.util.ArrayList; public class AccountPreferencesFragment extends PreferencesListFragment
import java.util.List; implements AccountCreatorListener {
public class AccountPreferencesFragment extends PreferencesListFragment implements AccountCreatorListener {
private int n; private int n;
OnPreferenceClickListener linkAccountListener =
new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent assistant = new Intent();
assistant.setClass(LinphoneActivity.instance(), AssistantActivity.class);
assistant.putExtra("LinkPhoneNumber", true);
assistant.putExtra("FromPref", true);
assistant.putExtra("AccountNumber", n);
startActivity(assistant);
return true;
}
};
private boolean isNewAccount = false; private boolean isNewAccount = false;
private LinphonePreferences mPrefs; private LinphonePreferences mPrefs;
OnPreferenceChangeListener avpfRRIntervalChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
try {
int intValue = Integer.parseInt(value);
if ((intValue < 1) || (intValue > 5)) {
return false;
}
} catch (NumberFormatException nfe) {
}
if (isNewAccount) {
// TODO
} else {
mPrefs.setAvpfRrInterval(n, value);
}
preference.setSummary(value);
return true;
}
};
OnPreferenceChangeListener escapeChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
// TODO
} else {
mPrefs.setReplacePlusByZeroZero(n, value);
}
return true;
}
};
OnPreferenceChangeListener pushNotificationListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
// TODO
} else {
mPrefs.enablePushNotifForProxy(n, value);
}
return true;
}
};
OnPreferenceChangeListener iceChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
} else {
mPrefs.setAccountIce(n, value);
((CheckBoxPreference) preference).setChecked(mPrefs.getAccountIce(n));
}
return true;
}
};
OnPreferenceChangeListener stunTurnChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
if (isNewAccount) {
} else {
mPrefs.setAccountStunServer(n, value);
preference.setSummary(value);
}
return true;
}
};
private EditTextPreference mProxyPreference; private EditTextPreference mProxyPreference;
OnPreferenceChangeListener transportChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = newValue.toString();
if (isNewAccount) {
// TODO
// builder.setTransport(transport);
} else {
mPrefs.setAccountTransport(n, key);
preference.setSummary(mPrefs.getAccountTransportString(n));
preference.setDefaultValue(mPrefs.getAccountTransportKey(n));
if (mProxyPreference != null) {
String newProxy = mPrefs.getAccountProxy(n);
mProxyPreference.setSummary(newProxy);
mProxyPreference.setText(newProxy);
}
}
return true;
}
};
private ListPreference mTransportPreference; private ListPreference mTransportPreference;
private AccountBuilder builder; private AccountBuilder builder;
OnPreferenceChangeListener usernameChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isEditTextEmpty(newValue.toString())) return false;
if (isNewAccount) {
builder.setUsername(newValue.toString());
} else {
mPrefs.setAccountUsername(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener useridChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setUserid(newValue.toString());
} else {
mPrefs.setAccountUserId(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener passwordChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isEditTextEmpty(newValue.toString())) return false;
if (isNewAccount) {
builder.setPassword(newValue.toString());
} else {
mPrefs.setAccountPassword(n, newValue.toString());
}
return true;
}
};
OnPreferenceChangeListener domainChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isEditTextEmpty(newValue.toString())) return false;
if (isNewAccount) {
builder.setDomain(newValue.toString());
} else {
mPrefs.setAccountDomain(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener displayNameChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setDisplayName(newValue.toString());
} else {
mPrefs.setAccountDisplayName(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener proxyChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
if (isNewAccount) {
builder.setServerAddr(newValue.toString());
preference.setSummary(newValue.toString());
} else {
mPrefs.setAccountProxy(n, value);
preference.setSummary(mPrefs.getAccountProxy(n));
if (mTransportPreference != null) {
mTransportPreference.setSummary(mPrefs.getAccountTransportString(n));
mTransportPreference.setValue(mPrefs.getAccountTransportKey(n));
}
}
return true;
}
};
OnPreferenceChangeListener outboundProxyChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setOutboundProxyEnabled((Boolean) newValue);
} else {
mPrefs.setAccountOutboundProxyEnabled(n, (Boolean) newValue);
}
return true;
}
};
OnPreferenceChangeListener expiresChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setExpires(newValue.toString());
} else {
mPrefs.setExpires(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener prefixChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
preference.setSummary(value);
if (isNewAccount) {
builder.setPrefix(value);
} else {
mPrefs.setPrefix(n, value);
}
return true;
}
};
OnPreferenceChangeListener avpfChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
builder.setAvpfEnabled(value);
} else {
mPrefs.setAvpfMode(n, value);
}
return true;
}
};
OnPreferenceChangeListener disableChangedListener =
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
builder.setEnabled(!value);
} else {
mPrefs.setAccountEnabled(n, !value);
}
return true;
}
};
private AccountCreator accountCreator; private AccountCreator accountCreator;
private ProgressDialog progress; private ProgressDialog progress;
@ -63,6 +321,20 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
mPrefs = LinphonePreferences.instance(); mPrefs = LinphonePreferences.instance();
} }
public static boolean isEditTextEmpty(String s) {
return s.equals(""); // really empty.
}
private static void setListPreferenceValues(
ListPreference pref, List<CharSequence> entries, List<CharSequence> values) {
CharSequence[] contents = new CharSequence[entries.size()];
entries.toArray(contents);
pref.setEntries(contents);
contents = new CharSequence[values.size()];
values.toArray(contents);
pref.setEntryValues(contents);
}
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -75,263 +347,17 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
initAccountPreferencesFields(screen); initAccountPreferencesFields(screen);
// Force hide keyboard // Force hide keyboard
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); getActivity()
.getWindow()
.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
} }
public static boolean isEditTextEmpty(String s) {
return s.equals(""); // really empty.
}
OnPreferenceChangeListener usernameChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isEditTextEmpty(newValue.toString())) return false;
if (isNewAccount) {
builder.setUsername(newValue.toString());
} else {
mPrefs.setAccountUsername(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener useridChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setUserid(newValue.toString());
} else {
mPrefs.setAccountUserId(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener passwordChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isEditTextEmpty(newValue.toString())) return false;
if (isNewAccount) {
builder.setPassword(newValue.toString());
} else {
mPrefs.setAccountPassword(n, newValue.toString());
}
return true;
}
};
OnPreferenceChangeListener domainChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isEditTextEmpty(newValue.toString())) return false;
if (isNewAccount) {
builder.setDomain(newValue.toString());
} else {
mPrefs.setAccountDomain(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener displayNameChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setDisplayName(newValue.toString());
} else {
mPrefs.setAccountDisplayName(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener proxyChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
if (isNewAccount) {
builder.setServerAddr(newValue.toString());
preference.setSummary(newValue.toString());
} else {
mPrefs.setAccountProxy(n, value);
preference.setSummary(mPrefs.getAccountProxy(n));
if (mTransportPreference != null) {
mTransportPreference.setSummary(mPrefs.getAccountTransportString(n));
mTransportPreference.setValue(mPrefs.getAccountTransportKey(n));
}
}
return true;
}
};
OnPreferenceChangeListener outboundProxyChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setOutboundProxyEnabled((Boolean) newValue);
} else {
mPrefs.setAccountOutboundProxyEnabled(n, (Boolean) newValue);
}
return true;
}
};
OnPreferenceChangeListener expiresChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (isNewAccount) {
builder.setExpires(newValue.toString());
} else {
mPrefs.setExpires(n, newValue.toString());
}
preference.setSummary(newValue.toString());
return true;
}
};
OnPreferenceChangeListener prefixChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
preference.setSummary(value);
if (isNewAccount) {
builder.setPrefix(value);
} else {
mPrefs.setPrefix(n, value);
}
return true;
}
};
OnPreferenceChangeListener avpfChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
builder.setAvpfEnabled(value);
} else {
mPrefs.setAvpfMode(n, value);
}
return true;
}
};
OnPreferenceChangeListener avpfRRIntervalChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
try {
int intValue = Integer.parseInt(value);
if ((intValue < 1) || (intValue > 5)) {
return false;
}
} catch (NumberFormatException nfe) {
}
if (isNewAccount) {
//TODO
} else {
mPrefs.setAvpfRrInterval(n, value);
}
preference.setSummary(value);
return true;
}
};
OnPreferenceChangeListener escapeChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
//TODO
} else {
mPrefs.setReplacePlusByZeroZero(n, value);
}
return true;
}
};
OnPreferenceClickListener linkAccountListener = new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent assistant = new Intent();
assistant.setClass(LinphoneActivity.instance(), AssistantActivity.class);
assistant.putExtra("LinkPhoneNumber", true);
assistant.putExtra("FromPref", true);
assistant.putExtra("AccountNumber", n);
startActivity(assistant);
return true;
}
};
OnPreferenceChangeListener pushNotificationListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
//TODO
} else {
mPrefs.enablePushNotifForProxy(n, value);
}
return true;
}
};
OnPreferenceChangeListener disableChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
builder.setEnabled(!value);
} else {
mPrefs.setAccountEnabled(n, !value);
}
return true;
}
};
OnPreferenceChangeListener transportChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = newValue.toString();
if (isNewAccount) {
//TODO
//builder.setTransport(transport);
} else {
mPrefs.setAccountTransport(n, key);
preference.setSummary(mPrefs.getAccountTransportString(n));
preference.setDefaultValue(mPrefs.getAccountTransportKey(n));
if (mProxyPreference != null) {
String newProxy = mPrefs.getAccountProxy(n);
mProxyPreference.setSummary(newProxy);
mProxyPreference.setText(newProxy);
}
}
return true;
}
};
OnPreferenceChangeListener iceChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean value = (Boolean) newValue;
if (isNewAccount) {
} else {
mPrefs.setAccountIce(n, value);
((CheckBoxPreference) preference).setChecked(mPrefs.getAccountIce(n));
}
return true;
}
};
OnPreferenceChangeListener stunTurnChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String value = newValue.toString();
if (isNewAccount) {
} else {
mPrefs.setAccountStunServer(n, value);
preference.setSummary(value);
}
return true;
}
};
private void initAccountPreferencesFields(PreferenceScreen parent) { private void initAccountPreferencesFields(PreferenceScreen parent) {
boolean isDefaultAccount = mPrefs.getDefaultAccountIndex() == n; boolean isDefaultAccount = mPrefs.getDefaultAccountIndex() == n;
NatPolicy natPolicy = null; NatPolicy natPolicy = null;
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null && if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null
LinphoneManager.getLc().getProxyConfigList() != null && && LinphoneManager.getLc().getProxyConfigList() != null
LinphoneManager.getLc().getProxyConfigList().length > n) { && LinphoneManager.getLc().getProxyConfigList().length > n) {
ProxyConfig proxy = LinphoneManager.getLc().getProxyConfigList()[n]; ProxyConfig proxy = LinphoneManager.getLc().getProxyConfigList()[n];
natPolicy = proxy.getNatPolicy(); natPolicy = proxy.getNatPolicy();
if (natPolicy == null) { if (natPolicy == null) {
@ -342,10 +368,15 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
} }
} }
accountCreator = LinphoneManager.getLc().createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); accountCreator =
LinphoneManager.getLc()
.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl());
accountCreator.setListener(this); accountCreator.setListener(this);
final PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_sipaccount_key)); final PreferenceCategory account =
(PreferenceCategory)
getPreferenceScreen()
.findPreference(getString(R.string.pref_sipaccount_key));
EditTextPreference username = (EditTextPreference) account.getPreference(0); EditTextPreference username = (EditTextPreference) account.getPreference(0);
username.setOnPreferenceChangeListener(usernameChangedListener); username.setOnPreferenceChangeListener(usernameChangedListener);
if (!isNewAccount) { if (!isNewAccount) {
@ -380,7 +411,9 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
displayName.setSummary(displayName.getText()); displayName.setSummary(displayName.getText());
} }
PreferenceCategory advanced = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_advanced_key)); PreferenceCategory advanced =
(PreferenceCategory)
getPreferenceScreen().findPreference(getString(R.string.pref_advanced_key));
mTransportPreference = (ListPreference) advanced.getPreference(0); mTransportPreference = (ListPreference) advanced.getPreference(0);
initializeTransportPreference(mTransportPreference); initializeTransportPreference(mTransportPreference);
mTransportPreference.setOnPreferenceChangeListener(transportChangedListener); mTransportPreference.setOnPreferenceChangeListener(transportChangedListener);
@ -390,8 +423,7 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
CheckBoxPreference ice = (CheckBoxPreference) advanced.getPreference(1); CheckBoxPreference ice = (CheckBoxPreference) advanced.getPreference(1);
ice.setOnPreferenceChangeListener(iceChangedListener); ice.setOnPreferenceChangeListener(iceChangedListener);
if (natPolicy != null) if (natPolicy != null) ice.setChecked(natPolicy.iceEnabled());
ice.setChecked(natPolicy.iceEnabled());
EditTextPreference stunTurn = (EditTextPreference) advanced.getPreference(2); EditTextPreference stunTurn = (EditTextPreference) advanced.getPreference(2);
stunTurn.setOnPreferenceChangeListener(stunTurnChangedListener); stunTurn.setOnPreferenceChangeListener(stunTurnChangedListener);
@ -404,7 +436,10 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
mProxyPreference.setOnPreferenceChangeListener(proxyChangedListener); mProxyPreference.setOnPreferenceChangeListener(proxyChangedListener);
if (!isNewAccount) { if (!isNewAccount) {
mProxyPreference.setText(mPrefs.getAccountProxy(n)); mProxyPreference.setText(mPrefs.getAccountProxy(n));
mProxyPreference.setSummary("".equals(mProxyPreference.getText()) || (mProxyPreference.getText() == null) ? getString(R.string.pref_help_proxy) : mProxyPreference.getText()); mProxyPreference.setSummary(
"".equals(mProxyPreference.getText()) || (mProxyPreference.getText() == null)
? getString(R.string.pref_help_proxy)
: mProxyPreference.getText());
} }
CheckBoxPreference outboundProxy = (CheckBoxPreference) advanced.getPreference(4); CheckBoxPreference outboundProxy = (CheckBoxPreference) advanced.getPreference(4);
@ -456,7 +491,9 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
pushNotif.setChecked(mPrefs.isPushNotifEnabledForProxy(n)); pushNotif.setChecked(mPrefs.isPushNotifEnabledForProxy(n));
} }
PreferenceCategory manage = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_manage_key)); PreferenceCategory manage =
(PreferenceCategory)
getPreferenceScreen().findPreference(getString(R.string.pref_manage_key));
final CheckBoxPreference disable = (CheckBoxPreference) manage.getPreference(0); final CheckBoxPreference disable = (CheckBoxPreference) manage.getPreference(0);
disable.setEnabled(true); disable.setEnabled(true);
disable.setOnPreferenceChangeListener(disableChangedListener); disable.setOnPreferenceChangeListener(disableChangedListener);
@ -467,15 +504,16 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
CheckBoxPreference mainAccount = (CheckBoxPreference) manage.getPreference(1); CheckBoxPreference mainAccount = (CheckBoxPreference) manage.getPreference(1);
mainAccount.setChecked(isDefaultAccount); mainAccount.setChecked(isDefaultAccount);
mainAccount.setEnabled(!mainAccount.isChecked()); mainAccount.setEnabled(!mainAccount.isChecked());
mainAccount.setOnPreferenceClickListener(new OnPreferenceClickListener() { mainAccount.setOnPreferenceClickListener(
public boolean onPreferenceClick(Preference preference) { new OnPreferenceClickListener() {
mPrefs.setDefaultAccount(n); public boolean onPreferenceClick(Preference preference) {
disable.setEnabled(false); mPrefs.setDefaultAccount(n);
disable.setChecked(false); disable.setEnabled(false);
preference.setEnabled(false); disable.setChecked(false);
return true; preference.setEnabled(false);
} return true;
}); }
});
if (!isNewAccount) { if (!isNewAccount) {
mainAccount.setEnabled(!mainAccount.isChecked()); mainAccount.setEnabled(!mainAccount.isChecked());
} }
@ -485,14 +523,15 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
final Preference delete = manage.getPreference(3); final Preference delete = manage.getPreference(3);
delete.setEnabled(!isNewAccount); delete.setEnabled(!isNewAccount);
delete.setOnPreferenceClickListener(new OnPreferenceClickListener() { delete.setOnPreferenceClickListener(
public boolean onPreferenceClick(Preference preference) { new OnPreferenceClickListener() {
mPrefs.deleteAccount(n); public boolean onPreferenceClick(Preference preference) {
LinphoneActivity.instance().displaySettings(); mPrefs.deleteAccount(n);
LinphoneActivity.instance().refreshAccounts(); LinphoneActivity.instance().displaySettings();
return true; LinphoneActivity.instance().refreshAccounts();
} return true;
}); }
});
} }
private void initializeTransportPreference(ListPreference pref) { private void initializeTransportPreference(ListPreference pref) {
@ -521,15 +560,6 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
} }
} }
private static void setListPreferenceValues(ListPreference pref, List<CharSequence> entries, List<CharSequence> values) {
CharSequence[] contents = new CharSequence[entries.size()];
entries.toArray(contents);
pref.setEntries(contents);
contents = new CharSequence[values.size()];
values.toArray(contents);
pref.setEntryValues(contents);
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@ -557,58 +587,57 @@ public class AccountPreferencesFragment extends PreferencesListFragment implemen
} }
@Override @Override
public void onUpdateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onUpdateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {
if (progress != null) progress.dismiss(); if (progress != null) progress.dismiss();
if (status.equals(AccountCreator.Status.RequestOk)) { if (status.equals(AccountCreator.Status.RequestOk)) {
mPrefs.setAccountPassword(n, accountCreator.getPassword()); mPrefs.setAccountPassword(n, accountCreator.getPassword());
PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_sipaccount_key)); PreferenceCategory account =
(PreferenceCategory)
getPreferenceScreen()
.findPreference(getString(R.string.pref_sipaccount_key));
((EditTextPreference) account.getPreference(2)).setText(mPrefs.getAccountPassword(n)); ((EditTextPreference) account.getPreference(2)).setText(mPrefs.getAccountPassword(n));
LinphoneUtils.displayErrorAlert(getString(R.string.pref_password_changed), LinphoneActivity.instance()); LinphoneUtils.displayErrorAlert(
getString(R.string.pref_password_changed), LinphoneActivity.instance());
} else { } else {
LinphoneUtils.displayErrorAlert(LinphoneUtils.errorForStatus(status), LinphoneActivity.instance()); LinphoneUtils.displayErrorAlert(
LinphoneUtils.errorForStatus(status), LinphoneActivity.instance());
} }
} }
@Override @Override
public void onIsAccountExist(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountExist(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
@Override @Override
public void onCreateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onCreateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onActivateAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onLinkAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onLinkAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onActivateAlias(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onActivateAlias(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAccountActivated(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountActivated(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onRecoverAccount(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onRecoverAccount(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAccountLinked(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAccountLinked(
AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
}
@Override @Override
public void onIsAliasUsed(AccountCreator accountCreator, AccountCreator.Status status, String resp) { public void onIsAliasUsed(
} AccountCreator accountCreator, AccountCreator.Status status, String resp) {}
} }

View file

@ -37,34 +37,30 @@ import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.widget.ListView; import android.widget.ListView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.linphone.R; import org.linphone.R;
import org.linphone.mediastream.Log; import org.linphone.mediastream.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@SuppressLint("ValidFragment") @SuppressLint("ValidFragment")
public class PreferencesListFragment extends ListFragment { public class PreferencesListFragment extends ListFragment {
private PreferenceManager mPreferenceManager; /** The starting request code given out to preference framework. */
/**
* The starting request code given out to preference framework.
*/
private static final int FIRST_REQUEST_CODE = 100; private static final int FIRST_REQUEST_CODE = 100;
private static final int MSG_BIND_PREFERENCES = 0;
private Handler mHandler = new Handler() { private static final int MSG_BIND_PREFERENCES = 0;
@Override private PreferenceManager mPreferenceManager;
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
}
}
};
private ListView preferencesList; private ListView preferencesList;
private Handler mHandler =
new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
}
}
};
private int xmlResID; private int xmlResID;
public PreferencesListFragment(int xmlId) { public PreferencesListFragment(int xmlId) {
@ -72,9 +68,7 @@ public class PreferencesListFragment extends ListFragment {
} }
// Must be provided // Must be provided
public PreferencesListFragment() { public PreferencesListFragment() {}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle b) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle b) {
@ -111,7 +105,10 @@ public class PreferencesListFragment extends ListFragment {
} }
mPreferenceManager = onCreatePreferenceManager(); mPreferenceManager = onCreatePreferenceManager();
preferencesList = (ListView) LayoutInflater.from(getActivity()).inflate(R.layout.preference_list_content, null); preferencesList =
(ListView)
LayoutInflater.from(getActivity())
.inflate(R.layout.preference_list_content, null);
preferencesList.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); preferencesList.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
addPreferencesFromResource(xmlResID); addPreferencesFromResource(xmlResID);
postBindPreferences(); postBindPreferences();
@ -152,7 +149,9 @@ public class PreferencesListFragment extends ListFragment {
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
try { try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class); Method m =
PreferenceManager.class.getDeclaredMethod(
"dispatchActivityResult", int.class, int.class, Intent.class);
m.setAccessible(true); m.setAccessible(true);
m.invoke(mPreferenceManager, requestCode, resultCode, data); m.invoke(mPreferenceManager, requestCode, resultCode, data);
} catch (Exception e) { } catch (Exception e) {
@ -162,9 +161,9 @@ public class PreferencesListFragment extends ListFragment {
/** /**
* Posts a message to bind the preferences to the list view. * Posts a message to bind the preferences to the list view.
* <p> *
* Binding late is preferred as any custom preference types created in * <p>Binding late is preferred as any custom preference types created in {@link
* {@link #onCreate(Bundle)} are able to have their views recycled. * #onCreate(Bundle)} are able to have their views recycled.
*/ */
private void postBindPreferences() { private void postBindPreferences() {
if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return; if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
@ -185,9 +184,11 @@ public class PreferencesListFragment extends ListFragment {
*/ */
private PreferenceManager onCreatePreferenceManager() { private PreferenceManager onCreatePreferenceManager() {
try { try {
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class); Constructor<PreferenceManager> c =
PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
c.setAccessible(true); c.setAccessible(true);
PreferenceManager preferenceManager = c.newInstance(this.getActivity(), FIRST_REQUEST_CODE); PreferenceManager preferenceManager =
c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
return preferenceManager; return preferenceManager;
} catch (Exception e) { } catch (Exception e) {
Log.e("[PreferencesListFragment] onCreatePreferenceManager " + e); Log.e("[PreferencesListFragment] onCreatePreferenceManager " + e);
@ -204,29 +205,10 @@ public class PreferencesListFragment extends ListFragment {
return mPreferenceManager; return mPreferenceManager;
} }
/**
* Sets the root of the preference hierarchy that this activity is showing.
*
* @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
*/
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
try {
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
m.setAccessible(true);
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
if (result && preferenceScreen != null) {
postBindPreferences();
}
} catch (Exception e) {
Log.e("[PreferencesListFragment] setPreferenceScreen " + e);
}
}
/** /**
* Gets the root of the preference hierarchy that this activity is showing. * Gets the root of the preference hierarchy that this activity is showing.
* *
* @return The {@link PreferenceScreen} that is the root of the preference * @return The {@link PreferenceScreen} that is the root of the preference hierarchy.
* hierarchy.
*/ */
public PreferenceScreen getPreferenceScreen() { public PreferenceScreen getPreferenceScreen() {
try { try {
@ -241,16 +223,47 @@ public class PreferencesListFragment extends ListFragment {
} }
/** /**
* Inflates the given XML resource and adds the preference hierarchy to the current * Sets the root of the preference hierarchy that this activity is showing.
* preference hierarchy. *
* @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
*/
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
try {
Method m =
PreferenceManager.class.getDeclaredMethod(
"setPreferences", PreferenceScreen.class);
m.setAccessible(true);
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
if (result && preferenceScreen != null) {
postBindPreferences();
}
} catch (Exception e) {
Log.e("[PreferencesListFragment] setPreferenceScreen " + e);
}
}
/**
* Inflates the given XML resource and adds the preference hierarchy to the current preference
* hierarchy.
* *
* @param preferencesResId The XML resource ID to inflate. * @param preferencesResId The XML resource ID to inflate.
*/ */
public void addPreferencesFromResource(int preferencesResId) { public void addPreferencesFromResource(int preferencesResId) {
try { try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class); Method m =
PreferenceManager.class.getDeclaredMethod(
"inflateFromResource",
Context.class,
int.class,
PreferenceScreen.class);
m.setAccessible(true); m.setAccessible(true);
PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(mPreferenceManager, getActivity(), preferencesResId, getPreferenceScreen()); PreferenceScreen prefScreen =
(PreferenceScreen)
m.invoke(
mPreferenceManager,
getActivity(),
preferencesResId,
getPreferenceScreen());
setPreferenceScreen(prefScreen); setPreferenceScreen(prefScreen);
} catch (Exception e) { } catch (Exception e) {
Log.e("[PreferencesListFragment] addPreferencesFromResource " + e); Log.e("[PreferencesListFragment] addPreferencesFromResource " + e);
@ -271,4 +284,4 @@ public class PreferencesListFragment extends ListFragment {
} }
return mPreferenceManager.findPreference(key); return mPreferenceManager.findPreference(key);
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.IBinder; import android.os.IBinder;
@ -37,4 +36,4 @@ public class AuthenticationService extends Service {
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return mAuthenticator.getIBinder(); return mAuthenticator.getIBinder();
} }
} }

Some files were not shown because too many files have changed in this diff Show more