From a1dc6c27f2ab24dc2b9077ec20d2f1c9efd41d09 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 3 May 2019 11:46:56 +0200 Subject: [PATCH] Revert "Using clipboard listener to automatically fill SMS code if possible + auto fill phone number if possible" This reverts commit b4d17844329e45ac7d7f62eadd21a422415c7bd1. --- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 123 +- .../java/org/linphone/LinphoneActivity.java | 33 +- .../linphone/LinphoneLauncherActivity.java | 21 +- .../java/org/linphone/LinphoneManager.java | 21 +- .../AccountConnectionAssistantActivity.java | 271 ----- .../linphone/assistant/AssistantActivity.java | 1065 ++++++++++++++--- .../assistant/AssistantFragmentsEnum.java | 33 + .../assistant/CodecDownloaderFragment.java | 220 ++++ .../linphone/assistant/CountryAdapter.java | 114 -- .../assistant/CountryListFragment.java | 90 ++ .../org/linphone/assistant/CountryPicker.java | 108 -- .../CreateAccountActivationFragment.java | 138 +++ .../CreateAccountCodeActivationFragment.java | 227 ++++ .../assistant/CreateAccountFragment.java | 804 +++++++++++++ ...CancellerCalibrationAssistantActivity.java | 131 -- .../EchoCancellerCalibrationFragment.java | 117 ++ ...EmailAccountCreationAssistantActivity.java | 270 ----- ...ailAccountValidationAssistantActivity.java | 101 -- .../GenericConnectionAssistantActivity.java | 108 -- .../assistant/LinphoneLoginFragment.java | 426 +++++++ .../org/linphone/assistant/LoginFragment.java | 125 ++ .../assistant/MenuAssistantActivity.java | 164 --- .../OpenH264DownloadAssistantActivity.java | 125 -- ...PhoneAccountCreationAssistantActivity.java | 240 ---- .../PhoneAccountLinkingAssistantActivity.java | 275 ----- ...oneAccountValidationAssistantActivity.java | 180 --- ...stantActivity.java => QrCodeFragment.java} | 36 +- .../RemoteConfigurationAssistantActivity.java | 203 ---- .../assistant/RemoteProvisioningActivity.java | 217 ++++ .../assistant/RemoteProvisioningFragment.java | 85 ++ .../RemoteProvisioningLoginActivity.java | 143 +++ .../linphone/assistant/WelcomeFragment.java | 78 ++ .../java/org/linphone/call/CallActivity.java | 5 + .../linphone/call/CallIncomingActivity.java | 5 + .../linphone/call/CallOutgoingActivity.java | 5 + .../chat/ChatRoomCreationFragment.java | 3 + .../linphone/fragments/StatusFragment.java | 15 + .../settings/AccountSettingsFragment.java | 8 +- .../settings/LinphonePreferences.java | 54 +- .../linphone/settings/SettingsFragment.java | 5 - .../org/linphone/utils/LinphoneUtils.java | 115 ++ .../org/linphone/utils/ThemableActivity.java | 5 - .../assistant_codec_downloader.xml | 103 ++ .../assistant_email_account_creation.xml | 211 ---- .../main/res/layout-land/assistant_menu.xml | 118 -- .../assistant_account_creation.xml | 399 ++++++ .../assistant_codec_downloader.xml | 110 ++ .../assistant_linphone_login.xml | 248 ++++ .../assistant_login.xml} | 230 ++-- .../layout-sw533dp-land/assistant_welcome.xml | 106 ++ .../assistant_codec_downloader.xml | 113 ++ .../assistant_codec_downloader.xml | 112 ++ ...remote_configuration.xml => assistant.xml} | 10 +- .../layout/assistant_account_connection.xml | 251 ---- .../res/layout/assistant_account_creation.xml | 344 ++++++ ...stant_account_creation_code_activation.xml | 73 ++ ...tant_account_creation_email_activation.xml | 63 + .../res/layout/assistant_codec_downloader.xml | 114 ++ .../res/layout/assistant_country_list.xml | 4 +- .../res/layout/assistant_ec_calibration.xml | 30 + .../assistant_echo_canceller_calibration.xml | 50 - .../assistant_email_account_creation.xml | 211 ---- .../assistant_email_account_validation.xml | 77 -- .../layout/assistant_generic_connection.xml | 233 ---- .../res/layout/assistant_linphone_login.xml | 222 ++++ app/src/main/res/layout/assistant_login.xml | 188 +++ app/src/main/res/layout/assistant_menu.xml | 118 -- .../assistant_openh264_codec_download.xml | 92 -- .../assistant_phone_account_creation.xml | 155 --- .../assistant_phone_account_linking.xml | 155 --- .../assistant_phone_account_validation.xml | 110 -- .../layout/assistant_remote_configuration.xml | 99 -- .../layout/assistant_remote_provisioning.xml | 78 ++ .../assistant_remote_provisioning_login.xml | 112 ++ app/src/main/res/layout/assistant_topbar.xml | 14 +- app/src/main/res/layout/assistant_welcome.xml | 94 ++ app/src/main/res/layout/qrcode.xml | 15 + .../main/res/raw/default_assistant_create.rc | 17 +- .../main/res/raw/linphone_assistant_create.rc | 12 +- .../res/values/non_localizable_custom.xml | 31 +- app/src/main/res/values/strings.xml | 3 - app/src/main/res/values/styles.xml | 6 - 83 files changed, 6580 insertions(+), 4669 deletions(-) delete mode 100644 app/src/main/java/org/linphone/assistant/AccountConnectionAssistantActivity.java create mode 100644 app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java create mode 100644 app/src/main/java/org/linphone/assistant/CodecDownloaderFragment.java delete mode 100644 app/src/main/java/org/linphone/assistant/CountryAdapter.java create mode 100644 app/src/main/java/org/linphone/assistant/CountryListFragment.java delete mode 100644 app/src/main/java/org/linphone/assistant/CountryPicker.java create mode 100644 app/src/main/java/org/linphone/assistant/CreateAccountActivationFragment.java create mode 100644 app/src/main/java/org/linphone/assistant/CreateAccountCodeActivationFragment.java create mode 100644 app/src/main/java/org/linphone/assistant/CreateAccountFragment.java delete mode 100644 app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java create mode 100644 app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationFragment.java delete mode 100644 app/src/main/java/org/linphone/assistant/EmailAccountCreationAssistantActivity.java delete mode 100644 app/src/main/java/org/linphone/assistant/EmailAccountValidationAssistantActivity.java delete mode 100644 app/src/main/java/org/linphone/assistant/GenericConnectionAssistantActivity.java create mode 100644 app/src/main/java/org/linphone/assistant/LinphoneLoginFragment.java create mode 100644 app/src/main/java/org/linphone/assistant/LoginFragment.java delete mode 100644 app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java delete mode 100644 app/src/main/java/org/linphone/assistant/OpenH264DownloadAssistantActivity.java delete mode 100644 app/src/main/java/org/linphone/assistant/PhoneAccountCreationAssistantActivity.java delete mode 100644 app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java delete mode 100644 app/src/main/java/org/linphone/assistant/PhoneAccountValidationAssistantActivity.java rename app/src/main/java/org/linphone/assistant/{QrCodeConfigurationAssistantActivity.java => QrCodeFragment.java} (77%) delete mode 100644 app/src/main/java/org/linphone/assistant/RemoteConfigurationAssistantActivity.java create mode 100644 app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java create mode 100644 app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java create mode 100644 app/src/main/java/org/linphone/assistant/RemoteProvisioningLoginActivity.java create mode 100644 app/src/main/java/org/linphone/assistant/WelcomeFragment.java create mode 100644 app/src/main/res/layout-land/assistant_codec_downloader.xml delete mode 100644 app/src/main/res/layout-land/assistant_email_account_creation.xml delete mode 100644 app/src/main/res/layout-land/assistant_menu.xml create mode 100644 app/src/main/res/layout-sw533dp-land/assistant_account_creation.xml create mode 100644 app/src/main/res/layout-sw533dp-land/assistant_codec_downloader.xml create mode 100644 app/src/main/res/layout-sw533dp-land/assistant_linphone_login.xml rename app/src/main/res/{layout-land/assistant_generic_connection.xml => layout-sw533dp-land/assistant_login.xml} (61%) create mode 100644 app/src/main/res/layout-sw533dp-land/assistant_welcome.xml create mode 100644 app/src/main/res/layout-sw533dp/assistant_codec_downloader.xml create mode 100644 app/src/main/res/layout-sw720dp-land/assistant_codec_downloader.xml rename app/src/main/res/layout/{assistant_qr_code_remote_configuration.xml => assistant.xml} (74%) delete mode 100644 app/src/main/res/layout/assistant_account_connection.xml create mode 100644 app/src/main/res/layout/assistant_account_creation.xml create mode 100644 app/src/main/res/layout/assistant_account_creation_code_activation.xml create mode 100644 app/src/main/res/layout/assistant_account_creation_email_activation.xml create mode 100644 app/src/main/res/layout/assistant_codec_downloader.xml create mode 100644 app/src/main/res/layout/assistant_ec_calibration.xml delete mode 100644 app/src/main/res/layout/assistant_echo_canceller_calibration.xml delete mode 100644 app/src/main/res/layout/assistant_email_account_creation.xml delete mode 100644 app/src/main/res/layout/assistant_email_account_validation.xml delete mode 100644 app/src/main/res/layout/assistant_generic_connection.xml create mode 100644 app/src/main/res/layout/assistant_linphone_login.xml create mode 100644 app/src/main/res/layout/assistant_login.xml delete mode 100644 app/src/main/res/layout/assistant_menu.xml delete mode 100644 app/src/main/res/layout/assistant_openh264_codec_download.xml delete mode 100644 app/src/main/res/layout/assistant_phone_account_creation.xml delete mode 100644 app/src/main/res/layout/assistant_phone_account_linking.xml delete mode 100644 app/src/main/res/layout/assistant_phone_account_validation.xml delete mode 100644 app/src/main/res/layout/assistant_remote_configuration.xml create mode 100644 app/src/main/res/layout/assistant_remote_provisioning.xml create mode 100644 app/src/main/res/layout/assistant_remote_provisioning_login.xml create mode 100644 app/src/main/res/layout/assistant_welcome.xml create mode 100644 app/src/main/res/layout/qrcode.xml diff --git a/app/build.gradle b/app/build.gradle index 6ba381ac7..f6ba9432e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,7 +59,7 @@ project.tasks['preBuild'].dependsOn 'getGitVersion' repositories { maven { // Replace snapshots by releases for releases ! - url "https://linphone.org/snapshots/maven_repository" + url "https://linphone.org/releases/maven_repository" } } @@ -72,7 +72,7 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 28 - versionCode 4119 + versionCode 4120 versionName "4.1" applicationId getPackageName() multiDexEnabled true @@ -167,7 +167,7 @@ dependencies { debugImplementation project(path: ":linphone-sdk-android", configuration: 'debug') } } else { - implementation "org.linphone:linphone-sdk-android:4.1+" + implementation "org.linphone:linphone-sdk-android:4.1-366-g1b22291" } } if (firebaseEnabled()) { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9361ef5cc..dee9a8d64 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -75,7 +75,6 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/org/linphone/LinphoneActivity.java b/app/src/main/java/org/linphone/LinphoneActivity.java index 176a329dd..edd3ceaed 100644 --- a/app/src/main/java/org/linphone/LinphoneActivity.java +++ b/app/src/main/java/org/linphone/LinphoneActivity.java @@ -29,6 +29,7 @@ import android.app.FragmentTransaction; import android.app.KeyguardManager; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -67,7 +68,8 @@ import java.util.Calendar; import java.util.Date; import java.util.List; import org.linphone.LinphoneManager.AddressType; -import org.linphone.assistant.MenuAssistantActivity; +import org.linphone.assistant.AssistantActivity; +import org.linphone.assistant.RemoteProvisioningLoginActivity; import org.linphone.call.CallActivity; import org.linphone.call.CallIncomingActivity; import org.linphone.call.CallOutgoingActivity; @@ -178,6 +180,31 @@ public class LinphoneActivity extends LinphoneGenericActivity LinphoneService.instance().removeForegroundServiceNotificationIfPossible(); + if (getResources().getBoolean(R.bool.orientation_portrait_only)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + boolean useFirstLoginActivity = + getResources().getBoolean(R.bool.display_account_assistant_at_first_start); + if (LinphonePreferences.instance().isProvisioningLoginViewEnabled()) { + Intent wizard = new Intent(); + wizard.setClass(this, RemoteProvisioningLoginActivity.class); + wizard.putExtra("Domain", LinphoneManager.getInstance().wizardLoginViewDomain); + startActivity(wizard); + finish(); + return; + } else if (savedInstanceState == null + && (useFirstLoginActivity + && LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null + && LinphonePreferences.instance().isFirstLaunch())) { + if (LinphonePreferences.instance().getAccountCount() > 0) { + LinphonePreferences.instance().firstLaunchSuccessful(); + } else { + startActivity(new Intent().setClass(this, AssistantActivity.class)); + finish(); + return; + } + } + if (getResources().getBoolean(R.bool.use_linphone_tag)) { if (getPackageManager() .checkPermission( @@ -1001,7 +1028,7 @@ public class LinphoneActivity extends LinphoneGenericActivity } private void displayAssistant() { - startActivity(new Intent(LinphoneActivity.this, MenuAssistantActivity.class)); + startActivity(new Intent(LinphoneActivity.this, AssistantActivity.class)); } private void displayInapp() { @@ -1622,7 +1649,7 @@ public class LinphoneActivity extends LinphoneGenericActivity new Intent() .setClass( LinphoneManager.getInstance().getContext(), - MenuAssistantActivity.class)); + AssistantActivity.class)); finish(); } } else if (selectedItem.equals(getString(R.string.menu_settings))) { diff --git a/app/src/main/java/org/linphone/LinphoneLauncherActivity.java b/app/src/main/java/org/linphone/LinphoneLauncherActivity.java index 71d2a7629..eb4e1fbc1 100644 --- a/app/src/main/java/org/linphone/LinphoneLauncherActivity.java +++ b/app/src/main/java/org/linphone/LinphoneLauncherActivity.java @@ -26,7 +26,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Handler; -import org.linphone.assistant.MenuAssistantActivity; +import org.linphone.assistant.RemoteProvisioningActivity; import org.linphone.settings.LinphonePreferences; /** Launch Linphone main activity when Service is ready. */ @@ -62,11 +62,12 @@ public class LinphoneLauncherActivity extends Activity { private void onServiceReady() { final Class classToStart; - - boolean useFirstLoginActivity = - getResources().getBoolean(R.bool.display_account_assistant_at_first_start); - if (useFirstLoginActivity && LinphonePreferences.instance().isFirstLaunch()) { - classToStart = MenuAssistantActivity.class; + /*if (getResources().getBoolean(R.bool.show_tutorials_instead_of_app)) { + classToStart = TutorialLauncherActivity.class; + } else */ + if (getResources().getBoolean(R.bool.display_sms_remote_provisioning_activity) + && LinphonePreferences.instance().isFirstRemoteProvisioning()) { + classToStart = RemoteProvisioningActivity.class; } else { classToStart = LinphoneActivity.class; } @@ -75,12 +76,8 @@ public class LinphoneLauncherActivity extends Activity { new Runnable() { @Override public void run() { - Intent intent = new Intent(); - intent.setClass(LinphoneLauncherActivity.this, classToStart); - if (getIntent() != null && getIntent().getExtras() != null) { - intent.putExtras(getIntent().getExtras()); - } - startActivity(intent); + startActivity( + getIntent().setClass(LinphoneLauncherActivity.this, classToStart)); } }, 500); diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index 32da921b3..75fe5b326 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -68,7 +68,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.TimerTask; -import org.linphone.assistant.PhoneAccountLinkingAssistantActivity; +import org.linphone.assistant.AssistantActivity; import org.linphone.call.CallActivity; import org.linphone.call.CallIncomingActivity; import org.linphone.call.CallManager; @@ -149,6 +149,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou private static boolean sExited; public final String configFile; + public String wizardLoginViewDomain = null; /** Called when the activity is first created. */ private final String mLPConfigXsd; @@ -379,7 +380,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou } else { progress.dismiss(); progress = null; - /*if (Build.VERSION.SDK_INT + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { LinphoneManager.getLc() .reloadMsPlugins( @@ -390,7 +391,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou } else { // We need to restart due to bad android linker AssistantActivity.instance().restartApplication(); - }*/ + } } } }); @@ -1496,8 +1497,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou new Timestamp( LinphoneActivity.instance() .getResources() - .getInteger( - R.integer.phone_number_linking_popup_time_interval)) + .getInteger(R.integer.popup_time_interval)) .getTime(); long newDate = now + future; @@ -1536,9 +1536,9 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou @Override public void onClick(View view) { Intent assistant = new Intent(); - assistant.setClass( - LinphoneActivity.instance(), - PhoneAccountLinkingAssistantActivity.class); + assistant.setClass(LinphoneActivity.instance(), AssistantActivity.class); + assistant.putExtra("LinkPhoneNumber", true); + assistant.putExtra("LinkPhoneNumberAsk", true); mServiceContext.startActivity(assistant); dialog.dismiss(); } @@ -1639,6 +1639,11 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou LinphonePreferences prefs = LinphonePreferences.instance(); if (state == ConfiguringState.Successful) { + if (prefs.isProvisioningLoginViewEnabled()) { + ProxyConfig proxyConfig = lc.createProxyConfig(); + Address addr = proxyConfig.getIdentityAddress(); + wizardLoginViewDomain = addr.getDomain(); + } prefs.setPushNotificationEnabled(prefs.isPushNotificationEnabled()); } } diff --git a/app/src/main/java/org/linphone/assistant/AccountConnectionAssistantActivity.java b/app/src/main/java/org/linphone/assistant/AccountConnectionAssistantActivity.java deleted file mode 100644 index 14c338cfb..000000000 --- a/app/src/main/java/org/linphone/assistant/AccountConnectionAssistantActivity.java +++ /dev/null @@ -1,271 +0,0 @@ -package org.linphone.assistant; - -/* -AccountConnectionAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.Intent; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.Switch; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; -import org.linphone.core.DialPlan; -import org.linphone.core.tools.Log; - -public class AccountConnectionAssistantActivity extends AssistantActivity { - private RelativeLayout mPhoneNumberConnection, mUsernameConnection; - private Switch mUsernameConnectionSwitch; - private EditText mPrefix, mPhoneNumber, mUsername, mPassword; - private TextView mCountryPicker, mError, mConnect; - private ImageView mPhoneNumberInfos; - - private AccountCreatorListenerStub mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_account_connection); - - mPhoneNumberConnection = findViewById(R.id.phone_number_form); - - mUsernameConnection = findViewById(R.id.username_form); - - mUsernameConnectionSwitch = findViewById(R.id.username_login); - mUsernameConnectionSwitch.setOnCheckedChangeListener( - new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - mPhoneNumberConnection.setVisibility(isChecked ? View.GONE : View.VISIBLE); - mUsernameConnection.setVisibility(isChecked ? View.VISIBLE : View.GONE); - } - }); - - mConnect = findViewById(R.id.assistant_login); - mConnect.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - mAccountCreator.setDomain(getString(R.string.default_domain)); - mConnect.setEnabled(false); - - if (mUsernameConnectionSwitch.isChecked()) { - mAccountCreator.setUsername(mUsername.getText().toString()); - mAccountCreator.setPassword(mPassword.getText().toString()); - - createProxyConfigAndLeaveAssistant(); - } else { - mAccountCreator.setUsername(mPhoneNumber.getText().toString()); - - AccountCreator.Status status = mAccountCreator.recoverAccount(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Account Connection] recoverAccount returned " + status); - mConnect.setEnabled(true); - showGenericErrorDialog(status); - } - } - } - }); - mConnect.setEnabled(false); - - if (getResources().getBoolean(R.bool.use_phone_number_validation)) { - if (getResources().getBoolean(R.bool.isTablet)) { - mUsernameConnectionSwitch.setChecked(true); - } else { - mUsernameConnection.setVisibility(View.GONE); - } - } else { - mPhoneNumberConnection.setVisibility(View.GONE); - findViewById(R.id.username_switch_layout).setVisibility(View.GONE); - } - - mCountryPicker = findViewById(R.id.select_country); - mCountryPicker.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - showCountryPickerDialog(); - } - }); - - mError = findViewById(R.id.phone_number_error); - - mPrefix = findViewById(R.id.dial_code); - mPrefix.setText("+"); - mPrefix.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - String prefix = s.toString(); - if (prefix.startsWith("+")) { - prefix = prefix.substring(1); - } - DialPlan dp = getDialPlanFromPrefix(prefix); - if (dp != null) { - mCountryPicker.setText(dp.getCountry()); - } - - updateConnectButtonAndDisplayError(); - } - }); - - mPhoneNumber = findViewById(R.id.phone_number); - mPhoneNumber.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - updateConnectButtonAndDisplayError(); - } - }); - - mPhoneNumberInfos = findViewById(R.id.info_phone_number); - mPhoneNumberInfos.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - showPhoneNumberDialog(); - } - }); - - mUsername = findViewById(R.id.assistant_username); - mUsername.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - mConnect.setEnabled(s.length() > 0 && mPassword.getText().length() > 0); - } - }); - - mPassword = findViewById(R.id.assistant_password); - mPassword.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - mConnect.setEnabled(s.length() > 0 && mUsername.getText().length() > 0); - } - }); - - mListener = - new AccountCreatorListenerStub() { - @Override - public void onRecoverAccount( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Account Connection] onRecoverAccount status is " + status); - if (status.equals(AccountCreator.Status.RequestOk)) { - Intent intent = - new Intent( - AccountConnectionAssistantActivity.this, - PhoneAccountValidationAssistantActivity.class); - intent.putExtra("isLoginVerification", true); - startActivity(intent); - } else { - mConnect.setEnabled(true); - showGenericErrorDialog(status); - } - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - - mAccountCreator.addListener(mListener); - - DialPlan dp = getDialPlanForCurrentCountry(); - displayDialPlan(dp); - - String phoneNumber = getDevicePhoneNumber(); - if (phoneNumber != null) { - mPhoneNumber.setText(phoneNumber); - } - } - - @Override - protected void onPause() { - super.onPause(); - mAccountCreator.removeListener(mListener); - } - - @Override - public void onCountryClicked(DialPlan dialPlan) { - super.onCountryClicked(dialPlan); - displayDialPlan(dialPlan); - } - - private void updateConnectButtonAndDisplayError() { - if (mPrefix.getText().toString().isEmpty() || mPhoneNumber.getText().toString().isEmpty()) - return; - - int status = arePhoneNumberAndPrefixOk(mPrefix, mPhoneNumber); - if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) { - mConnect.setEnabled(true); - mError.setText(""); - mError.setVisibility(View.INVISIBLE); - } else { - mConnect.setEnabled(false); - mError.setText(getErrorFromPhoneNumberStatus(status)); - mError.setVisibility(View.VISIBLE); - } - } - - private void displayDialPlan(DialPlan dp) { - if (dp != null) { - mPrefix.setText("+" + dp.getCountryCallingCode()); - mCountryPicker.setText(dp.getCountry()); - } - } -} diff --git a/app/src/main/java/org/linphone/assistant/AssistantActivity.java b/app/src/main/java/org/linphone/assistant/AssistantActivity.java index 98e9ebc24..083d93eb5 100644 --- a/app/src/main/java/org/linphone/assistant/AssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/AssistantActivity.java @@ -1,8 +1,7 @@ package org.linphone.assistant; - /* AssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France +Copyright (C) 2017 Belledonne Communications, Grenoble, France This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,251 +18,941 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import android.Manifest; +import android.app.ActivityManager; +import android.app.AlarmManager; import android.app.AlertDialog; +import android.app.Dialog; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.app.PendingIntent; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.telephony.TelephonyManager; +import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.view.WindowManager; -import android.widget.EditText; +import android.view.inputmethod.InputMethodManager; +import android.widget.BaseAdapter; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.linphone.LinphoneActivity; +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.AccountCreatorListener; +import org.linphone.core.Address; +import org.linphone.core.AuthInfo; +import org.linphone.core.ConfiguringState; import org.linphone.core.Core; +import org.linphone.core.CoreListenerStub; import org.linphone.core.DialPlan; import org.linphone.core.Factory; import org.linphone.core.ProxyConfig; +import org.linphone.core.RegistrationState; +import org.linphone.core.TransportType; import org.linphone.core.tools.Log; +import org.linphone.core.tools.OpenH264DownloadHelper; +import org.linphone.fragments.StatusFragment; +import org.linphone.mediastream.Version; import org.linphone.settings.LinphonePreferences; +import org.linphone.utils.LinphoneUtils; import org.linphone.utils.ThemableActivity; -public abstract class AssistantActivity extends ThemableActivity - implements CountryPicker.CountryPickedListener { - protected static AccountCreator mAccountCreator; +public class AssistantActivity extends ThemableActivity + implements OnClickListener, + ActivityCompat.OnRequestPermissionsResultCallback, + AccountCreatorListener { + private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201; + private static final int PERMISSIONS_REQUEST_CAMERA = 202; - protected View mTopBar, mStatusBar; - protected ImageView mBack; - protected AlertDialog mCountryPickerDialog; + private static AssistantActivity sInstance; - protected CountryPicker mCountryPicker; + public DialPlan country; + + private ImageView mBack /*, mCancel*/; + private AssistantFragmentsEnum mCurrentFragment; + private AssistantFragmentsEnum mLastFragment; + private AssistantFragmentsEnum mFirstFragment; + private Fragment mFragment; + private LinphonePreferences mPrefs; + private boolean mAccountCreated = false, + mNewAccount = false, + mIsLink = false, + mFromPref = false; + private CoreListenerStub mListener; + private Address mAddress; + private StatusFragment mStatus; + private ProgressDialog mProgress; + private Dialog mDialog; + private boolean mRemoteProvisioningInProgress; + private boolean mEchoCancellerAlreadyDone; + private AccountCreator mAccountCreator; + private CountryListAdapter mCountryListAdapter; + private LinearLayout mTopBar; + + public static AssistantActivity instance() { + return sInstance; + } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (mAccountCreator == null) { - String url = LinphonePreferences.instance().getXmlrpcUrl(); - Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); - core.loadConfigFromXml(LinphoneManager.getInstance().getDefaultDynamicConfigFile()); - mAccountCreator = core.createAccountCreator(url); + if (getResources().getBoolean(R.bool.orientation_portrait_only)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } + + setContentView(R.layout.assistant); + initUI(); + + if (getIntent().getBooleanExtra("LinkPhoneNumber", false)) { + mIsLink = true; + if (getIntent().getBooleanExtra("FromPref", false)) mFromPref = true; + displayCreateAccount(); + } else { + mFirstFragment = + getResources().getBoolean(R.bool.assistant_use_linphone_login_as_first_fragment) + ? AssistantFragmentsEnum.LINPHONE_LOGIN + : AssistantFragmentsEnum.WELCOME; + if (mFirstFragment == AssistantFragmentsEnum.WELCOME) { + mFirstFragment = + 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 (savedInstanceState == null) { + display(mFirstFragment); + } else { + mCurrentFragment = + (AssistantFragmentsEnum) + savedInstanceState.getSerializable("CurrentFragment"); + } + } + } + if (savedInstanceState != null && savedInstanceState.containsKey("echoCanceller")) { + mEchoCancellerAlreadyDone = savedInstanceState.getBoolean("echoCanceller"); + } else { + mEchoCancellerAlreadyDone = false; + } + mPrefs = LinphonePreferences.instance(); + mStatus.enableSideMenu(false); + + if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) { + mAccountCreator = + LinphoneManager.getLc() + .createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); + mAccountCreator.setListener(this); + } + + mCountryListAdapter = new CountryListAdapter(getApplicationContext()); + mListener = + new CoreListenerStub() { + + @Override + public void onConfiguringStatus( + Core lc, final ConfiguringState state, String message) { + if (mProgress != null) mProgress.dismiss(); + if (state == ConfiguringState.Successful) { + goToLinphoneActivity(); + } else if (state == ConfiguringState.Failed) { + Toast.makeText( + AssistantActivity.instance(), + getString(R.string.remote_provisioning_failure), + Toast.LENGTH_LONG) + .show(); + } + } + + @Override + public void onRegistrationStateChanged( + Core lc, ProxyConfig cfg, RegistrationState state, String smessage) { + if (mRemoteProvisioningInProgress) { + if (mProgress != null) mProgress.dismiss(); + if (state == RegistrationState.Ok) { + mRemoteProvisioningInProgress = false; + success(); + } + } else if (mAccountCreated && !mNewAccount) { + if (mAddress != null + && mAddress.asString() + .equals(cfg.getIdentityAddress().asString())) { + if (state == RegistrationState.Ok) { + if (mProgress != null) mProgress.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 (mProgress != null) mProgress.dismiss(); + if (mDialog == null || !mDialog.isShowing()) { + mDialog = createErrorDialog(cfg, smessage); + mDialog.setCancelable(false); + mDialog.show(); + } + } else if (!(state == RegistrationState.Progress)) { + if (mProgress != null) mProgress.dismiss(); + } + } + } + } + }; + sInstance = this; } @Override protected void onResume() { super.onResume(); - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - - mStatusBar = findViewById(R.id.status); - if (getResources().getBoolean(R.bool.assistant_hide_status_bar)) { - mStatusBar.setVisibility(View.GONE); + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.addListener(mListener); } - - mTopBar = findViewById(R.id.top_bar); - if (getResources().getBoolean(R.bool.assistant_hide_top_bar)) { - mTopBar.setVisibility(View.GONE); - } - - mBack = findViewById(R.id.back); - mBack.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); } @Override - public void onCountryClicked(DialPlan dialPlan) { - if (mCountryPickerDialog != null) { - mCountryPickerDialog.dismiss(); - mCountryPickerDialog = null; + protected void onPause() { + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.removeListener(mListener); + } + + super.onPause(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putSerializable("CurrentFragment", mCurrentFragment); + outState.putBoolean("echoCanceller", mEchoCancellerAlreadyDone); + super.onSaveInstanceState(outState); + } + + public void updateStatusFragment(StatusFragment fragment) { + mStatus = fragment; + } + + private AccountCreator loadAccountCreator(ProxyConfig cfg) { + ProxyConfig cfgTab[] = LinphoneManager.getLc().getProxyConfigList(); + int n = -1; + for (int i = 0; i < cfgTab.length; i++) { + if (cfgTab[i].equals(cfg)) { + n = i; + break; + } + } + if (n >= 0) { + mAccountCreator.setDomain(mPrefs.getAccountDomain(n)); + mAccountCreator.setUsername(mPrefs.getAccountUsername(n)); + } + return mAccountCreator; + } + + private void initUI() { + mBack = findViewById(R.id.back); + mBack.setOnClickListener(this); + // mCancel = findViewById(R.id.assistant_cancel); + // mCancel.setOnClickListener(this); + + mTopBar = findViewById(R.id.topbar); + if (getResources().getBoolean(R.bool.assistant_hide_top_bar)) { + mTopBar.setVisibility(View.GONE); } } - protected void createProxyConfigAndLeaveAssistant() { - Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); - boolean useLinphoneDefaultValues = - getString(R.string.default_domain).equals(mAccountCreator.getDomain()); - if (useLinphoneDefaultValues) { - core.loadConfigFromXml(LinphoneManager.getInstance().getLinphoneDynamicConfigFile()); - } + private void changeFragment(Fragment newFragment) { + hideKeyboard(); + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.replace(R.id.fragment_container, newFragment); + transaction.commitAllowingStateLoss(); + } - ProxyConfig proxyConfig = mAccountCreator.configure(); + @Override + public void onClick(View v) { + int id = v.getId(); + boolean firstLaunch = LinphonePreferences.instance().isFirstLaunch(); - if (useLinphoneDefaultValues) { - // Restore default values - core.loadConfigFromXml(LinphoneManager.getInstance().getDefaultDynamicConfigFile()); - } - - if (proxyConfig == null) { - Log.e("[Assistant] Account creator couldn't create proxy config"); - // TODO: display error message - } else { + /*if (id == R.id.assistant_cancel) { + hideKeyboard(); LinphonePreferences.instance().firstLaunchSuccessful(); + if (getResources().getBoolean(R.bool.assistant_cancel_move_to_back)) { + moveTaskToBack(true); + } else { + if (firstLaunch) startActivity(new Intent().setClass(this, LinphoneActivity.class)); + finish(); + } + } else*/ + if (id == R.id.back) { + hideKeyboard(); + if (mCurrentFragment == AssistantFragmentsEnum.WELCOME) { + LinphonePreferences.instance().firstLaunchSuccessful(); + if (getResources().getBoolean(R.bool.assistant_cancel_move_to_back)) { + moveTaskToBack(true); + } else { + if (firstLaunch) + startActivity(new Intent().setClass(this, LinphoneActivity.class)); + finish(); + } + } else { + onBackPressed(); + } + } + } + + @Override + public void onBackPressed() { + if (mIsLink) { + return; + } + boolean firstLaunch = LinphonePreferences.instance().isFirstLaunch(); + if (mCurrentFragment == mFirstFragment) { + LinphonePreferences.instance().firstLaunchSuccessful(); + if (getResources().getBoolean(R.bool.assistant_cancel_move_to_back)) { + moveTaskToBack(true); + } else { + LinphonePreferences.instance().firstLaunchSuccessful(); + if (firstLaunch) startActivity(new Intent().setClass(this, LinphoneActivity.class)); + finish(); + } + } else if (mCurrentFragment == AssistantFragmentsEnum.LOGIN + || mCurrentFragment == AssistantFragmentsEnum.LINPHONE_LOGIN + || mCurrentFragment == AssistantFragmentsEnum.CREATE_ACCOUNT + || mCurrentFragment == AssistantFragmentsEnum.REMOTE_PROVISIONING) { + displayMenu(); + } else if (mCurrentFragment == AssistantFragmentsEnum.WELCOME) { + if (firstLaunch) startActivity(new Intent().setClass(this, LinphoneActivity.class)); + finish(); + } else if (mCurrentFragment == AssistantFragmentsEnum.COUNTRY_CHOOSER) { + if (mLastFragment.equals(AssistantFragmentsEnum.LINPHONE_LOGIN)) { + displayLoginLinphone(null, null); + } else { + displayCreateAccount(); + } + } else if (mCurrentFragment == AssistantFragmentsEnum.QRCODE_READER) { + displayRemoteProvisioning(""); + } + } + + public void hideKeyboard() { + InputMethodManager imm = + (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + View view = this.getCurrentFocus(); + if (imm != null && view != null) { + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + } + + private void checkAndRequestAudioPermission() { + checkAndRequestPermission( + Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO); + } + + private void checkAndRequestVideoPermission() { + checkAndRequestPermission(Manifest.permission.CAMERA, PERMISSIONS_REQUEST_CAMERA); + } + + private void checkAndRequestPermission(String permission, int result) { + int permissionGranted = getPackageManager().checkPermission(permission, getPackageName()); + Log.i( + "[Permission] " + + permission + + " is " + + (permissionGranted == PackageManager.PERMISSION_GRANTED + ? "granted" + : "denied")); + + if (permissionGranted != PackageManager.PERMISSION_GRANTED) { + Log.i("[Permission] Asking for " + permission); + ActivityCompat.requestPermissions(this, new String[] {permission}, result); + } + } + + @Override + public void onRequestPermissionsResult( + int requestCode, String[] permissions, final int[] grantResults) { + for (int i = 0; i < permissions.length; i++) { + Log.i( + "[Permission] " + + permissions[i] + + " is " + + (grantResults[i] == PackageManager.PERMISSION_GRANTED + ? "granted" + : "denied")); + } + + switch (requestCode) { + case PERMISSIONS_REQUEST_CAMERA: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + displayQRCodeReader(); + } + break; + case PERMISSIONS_REQUEST_RECORD_AUDIO: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + launchEchoCancellerCalibration(); + } else { + isEchoCalibrationFinished(); + } + break; + } + } + + private void launchEchoCancellerCalibration() { + int recordAudio = + 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) { + EchoCancellerCalibrationFragment fragment = new EchoCancellerCalibrationFragment(); + fragment.enableEcCalibrationResultSending(true); + changeFragment(fragment); + mCurrentFragment = AssistantFragmentsEnum.ECHO_CANCELLER_CALIBRATION; + mBack.setVisibility(View.VISIBLE); + mBack.setEnabled(false); + } else { + checkAndRequestAudioPermission(); + } + } + + private void configureProxyConfig(AccountCreator accountCreator) { + Core lc = LinphoneManager.getLc(); + ProxyConfig proxyConfig = lc.createProxyConfig(); + AuthInfo authInfo; + + String identity = proxyConfig.getIdentityAddress().asStringUriOnly(); + if (identity == null || accountCreator.getUsername() == null) { + LinphoneUtils.displayErrorAlert(getString(R.string.error), this); + return; + } + identity = identity.replace("?", accountCreator.getUsername()); + Address addr = Factory.instance().createAddress(identity); + addr.setDisplayName(accountCreator.getUsername()); + mAddress = addr; + proxyConfig.edit(); + + proxyConfig.setIdentityAddress(addr); + + if (accountCreator.getPhoneNumber() != null && accountCreator.getPhoneNumber().length() > 0) + proxyConfig.setDialPrefix( + org.linphone.core.Utils.getPrefixFromE164(accountCreator.getPhoneNumber())); + + proxyConfig.done(); + + authInfo = + Factory.instance() + .createAuthInfo( + accountCreator.getUsername(), + null, + accountCreator.getPassword(), + accountCreator.getHa1(), + proxyConfig.getRealm(), + proxyConfig.getDomain()); + + lc.addProxyConfig(proxyConfig); + + lc.addAuthInfo(authInfo); + + lc.setDefaultProxyConfig(proxyConfig); + + if (LinphonePreferences.instance() != null) + LinphonePreferences.instance().setPushNotificationEnabled(true); + + if (!mNewAccount) { + displayRegistrationInProgressDialog(); + } + mAccountCreated = true; + } + + public void linphoneLogIn(AccountCreator accountCreator) { + LinphoneManager.getLc() + .loadConfigFromXml(LinphoneManager.getInstance().getLinphoneDynamicConfigFile()); + configureProxyConfig(accountCreator); + // Restore default values for proxy config + LinphoneManager.getLc() + .loadConfigFromXml(LinphoneManager.getInstance().getDefaultDynamicConfigFile()); + } + + public void genericLogIn( + String username, + String userid, + String password, + String displayname, + String prefix, + String domain, + TransportType transport) { + Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (core == null) return; + + AuthInfo authInfo = + Factory.instance().createAuthInfo(username, userid, password, null, null, domain); + core.addAuthInfo(authInfo); + + ProxyConfig proxyConfig = core.createProxyConfig(); + + String identity = "sip:" + username + "@" + domain; + Address identityAddr = Factory.instance().createAddress(identity); + if (identityAddr != null) { + identityAddr.setDisplayName(displayname); + proxyConfig.setIdentityAddress(identityAddr); + } + String proxy = ""; + proxyConfig.setServerAddr(proxy); + + proxyConfig.setDialPrefix(prefix); + + core.addProxyConfig(proxyConfig); + core.setDefaultProxyConfig(proxyConfig); + + mAccountCreated = true; + success(); + } + + private void display(AssistantFragmentsEnum fragment) { + switch (fragment) { + case WELCOME: + displayMenu(); + break; + case LINPHONE_LOGIN: + displayLoginLinphone(null, null); + break; + case CREATE_ACCOUNT: + displayCreateAccount(); + break; + default: + throw new IllegalStateException("Can't handle " + fragment); + } + } + + private void displayMenu() { + mFragment = new WelcomeFragment(); + changeFragment(mFragment); + country = null; + mCurrentFragment = AssistantFragmentsEnum.WELCOME; + } + + public void displayLoginGeneric() { + mFragment = new LoginFragment(); + changeFragment(mFragment); + mCurrentFragment = AssistantFragmentsEnum.LOGIN; + } + + public void displayLoginLinphone(String username, String password) { + mFragment = new LinphoneLoginFragment(); + Bundle extras = new Bundle(); + extras.putString("Phone", null); + extras.putString("Dialcode", null); + extras.putString("Username", username); + extras.putString("Password", password); + mFragment.setArguments(extras); + changeFragment(mFragment); + mCurrentFragment = AssistantFragmentsEnum.LINPHONE_LOGIN; + } + + public void displayCreateAccount() { + mFragment = new CreateAccountFragment(); + Bundle extra = new Bundle(); + extra.putBoolean("LinkPhoneNumber", mIsLink); + extra.putBoolean("LinkFromPref", mFromPref); + mFragment.setArguments(extra); + changeFragment(mFragment); + mCurrentFragment = AssistantFragmentsEnum.CREATE_ACCOUNT; + } + + public void displayRemoteProvisioning(String url) { + mFragment = new RemoteProvisioningFragment(); + Bundle extra = new Bundle(); + extra.putString("RemoteUrl", url); + mFragment.setArguments(extra); + changeFragment(mFragment); + mCurrentFragment = AssistantFragmentsEnum.REMOTE_PROVISIONING; + } + + public void displayQRCodeReader() { + if (getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()) + != PackageManager.PERMISSION_GRANTED) { + checkAndRequestVideoPermission(); + } else { + mFragment = new QrCodeFragment(); + changeFragment(mFragment); + mCurrentFragment = AssistantFragmentsEnum.QRCODE_READER; + } + } + + public void displayCountryChooser() { + mFragment = new CountryListFragment(); + changeFragment(mFragment); + mLastFragment = mCurrentFragment; + mCurrentFragment = AssistantFragmentsEnum.COUNTRY_CHOOSER; + } + + private void launchDownloadCodec() { + if (OpenH264DownloadHelper.isOpenH264DownloadEnabled()) { + OpenH264DownloadHelper downloadHelper = + Factory.instance().createOpenH264DownloadHelper(this); + if (Version.getCpuAbis().contains("armeabi-v7a") + && !Version.getCpuAbis().contains("x86") + && !downloadHelper.isCodecFound()) { + CodecDownloaderFragment codecFragment = new CodecDownloaderFragment(); + changeFragment(codecFragment); + mCurrentFragment = AssistantFragmentsEnum.DOWNLOAD_CODEC; + mBack.setEnabled(false); + } else goToLinphoneActivity(); + } else { goToLinphoneActivity(); } } - protected void goToLinphoneActivity() { + public void endDownloadCodec() { + goToLinphoneActivity(); + } + + private void displayRegistrationInProgressDialog() { + if (LinphoneManager.getLc().isNetworkReachable()) { + mProgress = ProgressDialog.show(this, null, null); + Drawable d = new ColorDrawable(ContextCompat.getColor(this, R.color.light_grey_color)); + d.setAlpha(200); + mProgress + .getWindow() + .setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT); + mProgress.getWindow().setBackgroundDrawable(d); + mProgress.setContentView(R.layout.wait_layout); + mProgress.show(); + } + } + + public void displayRemoteProvisioningInProgressDialog() { + mRemoteProvisioningInProgress = true; + + mProgress = ProgressDialog.show(this, null, null); + Drawable d = new ColorDrawable(ContextCompat.getColor(this, R.color.light_grey_color)); + d.setAlpha(200); + mProgress + .getWindow() + .setLayout( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT); + mProgress.getWindow().setBackgroundDrawable(d); + mProgress.setContentView(R.layout.wait_layout); + mProgress.show(); + } + + public void displayAssistantConfirm(String username, String password, String email) { + CreateAccountActivationFragment fragment = new CreateAccountActivationFragment(); + mNewAccount = true; + Bundle extras = new Bundle(); + extras.putString("Username", username); + extras.putString("Password", password); + extras.putString("Email", email); + fragment.setArguments(extras); + changeFragment(fragment); + + mCurrentFragment = AssistantFragmentsEnum.CREATE_ACCOUNT_ACTIVATION; + } + + public void displayAssistantCodeConfirm( + String username, String phone, String dialcode, boolean recoverAccount) { + CreateAccountCodeActivationFragment fragment = new CreateAccountCodeActivationFragment(); + mNewAccount = true; + Bundle extras = new Bundle(); + extras.putString("Username", username); + extras.putString("Phone", phone); + extras.putString("Dialcode", dialcode); + extras.putBoolean("RecoverAccount", recoverAccount); + extras.putBoolean("LinkAccount", mIsLink); + fragment.setArguments(extras); + changeFragment(fragment); + + mCurrentFragment = AssistantFragmentsEnum.CREATE_ACCOUNT_CODE_ACTIVATION; + } + + public void displayAssistantLinphoneLogin(String phone, String dialcode) { + LinphoneLoginFragment fragment = new LinphoneLoginFragment(); + mNewAccount = true; + Bundle extras = new Bundle(); + extras.putString("Phone", phone); + extras.putString("Dialcode", dialcode); + fragment.setArguments(extras); + changeFragment(fragment); + + mCurrentFragment = AssistantFragmentsEnum.LINPHONE_LOGIN; + } + + public void isAccountVerified() { + Toast.makeText(this, getString(R.string.assistant_account_validated), Toast.LENGTH_LONG) + .show(); + hideKeyboard(); + success(); + } + + public void isEchoCalibrationFinished() { + launchDownloadCodec(); + } + + private Dialog createErrorDialog(ProxyConfig proxy, String message) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + if (message.equals("Forbidden")) { + message = getString(R.string.assistant_error_bad_credentials); + } + builder.setMessage(message) + .setTitle(proxy.getState().toString()) + .setPositiveButton( + getString(R.string.continue_text), + 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()); + LinphonePreferences.instance().resetDefaultProxyConfig(); + LinphoneManager.getLc().refreshRegisters(); + dialog.dismiss(); + } + }); + return builder.show(); + } + + public void success() { boolean needsEchoCalibration = LinphoneManager.getLc().isEchoCancellerCalibrationRequired(); - boolean echoCalibrationDone = - LinphonePreferences.instance().isEchoCancellationCalibrationDone(); - Log.i( - "[Assistant] Echo cancellation calibration required ? " - + needsEchoCalibration - + ", already done ? " - + echoCalibrationDone); - - Intent intent; - if (needsEchoCalibration && !echoCalibrationDone) { - intent = new Intent(this, EchoCancellerCalibrationAssistantActivity.class); + if (needsEchoCalibration && mPrefs.isFirstLaunch()) { + launchEchoCancellerCalibration(); } else { - /*boolean openH264 = LinphonePreferences.instance().isOpenH264CodecDownloadEnabled(); - boolean codecFound = - LinphoneManager.getInstance().getOpenH264DownloadHelper().isCodecFound(); - boolean abiSupported = - Version.getCpuAbis().contains("armeabi-v7a") - && !Version.getCpuAbis().contains("x86"); - boolean androidVersionOk = Version.sdkStrictlyBelow(Build.VERSION_CODES.M); - - if (openH264 && abiSupported && androidVersionOk && !codecFound) { - intent = new Intent(this, OpenH264DownloadAssistantActivity.class); - } else {*/ - intent = new Intent(this, LinphoneActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - // } + launchDownloadCodec(); } - startActivity(intent); } - protected void showPhoneNumberDialog() { - new AlertDialog.Builder(this) - .setTitle(getString(R.string.phone_number_info_title)) - .setMessage( - getString(R.string.phone_number_link_info_content) - + "\n" - + getString( - R.string.phone_number_link_info_content_already_account)) - .show(); + private void goToLinphoneActivity() { + mPrefs.firstLaunchSuccessful(); + startActivity( + new Intent() + .setClass(this, LinphoneActivity.class) + .putExtra("isNewProxyConfig", true)); + finish(); } - protected void showAccountAlreadyExistsDialog() { - new AlertDialog.Builder(this) - .setTitle(getString(R.string.account_already_exist)) - .setMessage(getString(R.string.assistant_phone_number_unavailable)) - .show(); + public void setCoreListener() { + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.addListener(mListener); + } + if (mStatus != null) { + mStatus.setCoreListener(); + } } - protected void showGenericErrorDialog(AccountCreator.Status status) { - String message; + public void restartApplication() { + mPrefs.firstLaunchSuccessful(); - switch (status) { - // TODO - case PhoneNumberInvalid: - message = getString(R.string.phone_number_invalid); - break; - case WrongActivationCode: - message = getString(R.string.activation_code_invalid); - break; - case PhoneNumberOverused: - message = getString(R.string.phone_number_overuse); - break; - default: - message = getString(R.string.error_unknown); - break; + Intent mStartActivity = new Intent(this, LinphoneLauncherActivity.class); + PendingIntent mPendingIntent = + PendingIntent.getActivity( + this, + (int) System.currentTimeMillis(), + mStartActivity, + PendingIntent.FLAG_CANCEL_CURRENT); + AlarmManager mgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); + mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 500, mPendingIntent); + + finish(); + stopService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class)); + ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + am.killBackgroundProcesses(getString(R.string.sync_account_type)); + android.os.Process.killProcess(android.os.Process.myPid()); + } + + @Override + public void onIsAccountExist( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (status.equals(AccountCreator.Status.AccountExistWithAlias)) { + success(); + } else { + mIsLink = true; + displayCreateAccount(); + } + if (mAccountCreator != null) mAccountCreator.setListener(null); + } + + @Override + public void onCreateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onLinkAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAlias( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAccountActivated( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onRecoverAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAccountLinked( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAliasUsed( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onUpdateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + public CountryListAdapter getCountryListAdapter() { + return mCountryListAdapter; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mCurrentFragment == AssistantFragmentsEnum.QRCODE_READER) { + this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + } + + /** + * This class reads a JSON file containing Country-specific phone number description, and allows + * to present them into a ListView + */ + public class CountryListAdapter extends BaseAdapter implements Filterable { + + private LayoutInflater mInflater; + private final DialPlan[] allCountries; + private List filteredCountries; + private final Context context; + + CountryListAdapter(Context ctx) { + context = ctx; + allCountries = Factory.instance().getDialPlans(); + filteredCountries = new ArrayList<>(Arrays.asList(allCountries)); } - new AlertDialog.Builder(this) - .setTitle(getString(R.string.error)) - .setMessage(message) - .show(); - } - - protected void showCountryPickerDialog() { - if (mCountryPicker == null) { - mCountryPicker = new CountryPicker(this, this); - } - mCountryPickerDialog = - new AlertDialog.Builder(this).setView(mCountryPicker.getView()).show(); - } - - protected DialPlan getDialPlanForCurrentCountry() { - try { - TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); - String countryIso = tm.getNetworkCountryIso(); - return getDialPlanFromCountryCode(countryIso); - } catch (Exception e) { - Log.e("[Assistant] " + e); - } - return null; - } - - protected String getDevicePhoneNumber() { - try { - TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); - return tm.getLine1Number(); - } catch (Exception e) { - Log.e("[Assistant] " + e); - } - return null; - } - - protected DialPlan getDialPlanFromPrefix(String prefix) { - if (prefix == null || prefix.isEmpty()) return null; - - for (DialPlan c : Factory.instance().getDialPlans()) { - if (prefix.equalsIgnoreCase(c.getCountryCallingCode())) return c; - } - return null; - } - - protected DialPlan getDialPlanFromCountryCode(String countryCode) { - if (countryCode == null || countryCode.isEmpty()) return null; - - for (DialPlan c : Factory.instance().getDialPlans()) { - if (countryCode.equalsIgnoreCase(c.getIsoCountryCode())) return c; - } - return null; - } - - protected int arePhoneNumberAndPrefixOk(EditText prefixEditText, EditText phoneNumberEditText) { - String prefix = prefixEditText.getText().toString(); - if (prefix.startsWith("+")) { - prefix = prefix.substring(1); + public void setInflater(LayoutInflater inf) { + mInflater = inf; } - String phoneNumber = phoneNumberEditText.getText().toString(); - return mAccountCreator.setPhoneNumber(phoneNumber, prefix); - } - - protected String getErrorFromPhoneNumberStatus(int status) { - AccountCreator.PhoneNumberStatus phoneNumberStatus = - AccountCreator.PhoneNumberStatus.fromInt(status); - switch (phoneNumberStatus) { - case InvalidCountryCode: - return getString(R.string.country_code_invalid); - case TooShort: - return getString(R.string.phone_number_too_short); - case TooLong: - return getString(R.string.phone_number_too_long); - case Invalid: - return getString(R.string.phone_number_invalid); + public DialPlan getCountryFromCountryCode(String countryCode) { + countryCode = (countryCode.startsWith("+")) ? countryCode.substring(1) : countryCode; + for (DialPlan c : allCountries) { + if (c.getCountryCallingCode().compareTo(countryCode) == 0) return c; + } + return null; + } + + @Override + public int getCount() { + return filteredCountries.size(); + } + + @Override + public DialPlan getItem(int position) { + return filteredCountries.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view; + + if (convertView != null) { + view = convertView; + } else { + view = mInflater.inflate(R.layout.country_cell, parent, false); + } + + DialPlan c = filteredCountries.get(position); + + TextView name = view.findViewById(R.id.country_name); + name.setText(c.getCountry()); + + TextView dial_code = view.findViewById(R.id.country_prefix); + if (context != null) + dial_code.setText( + String.format( + context.getString(R.string.country_code), + c.getCountryCallingCode())); + + view.setTag(c); + return view; + } + + @Override + public Filter getFilter() { + return new Filter() { + @Override + protected FilterResults performFiltering(CharSequence constraint) { + ArrayList filteredCountries = new ArrayList<>(); + for (DialPlan c : allCountries) { + if (c.getCountry().toLowerCase().contains(constraint) + || c.getCountryCallingCode().contains(constraint)) { + filteredCountries.add(c); + } + } + FilterResults filterResults = new FilterResults(); + filterResults.values = filteredCountries; + return filterResults; + } + + @Override + @SuppressWarnings("unchecked") + protected void publishResults(CharSequence constraint, FilterResults results) { + filteredCountries = (List) results.values; + CountryListAdapter.this.notifyDataSetChanged(); + } + }; } - return null; } } diff --git a/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java b/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java new file mode 100644 index 000000000..699555cd6 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java @@ -0,0 +1,33 @@ +package org.linphone.assistant; +/* +AssistantFragmentsEnum.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +public enum AssistantFragmentsEnum { + WELCOME, + CREATE_ACCOUNT, + CREATE_ACCOUNT_ACTIVATION, + CREATE_ACCOUNT_CODE_ACTIVATION, + LINPHONE_LOGIN, + COUNTRY_CHOOSER, + LOGIN, + REMOTE_PROVISIONING, + ECHO_CANCELLER_CALIBRATION, + DOWNLOAD_CODEC, + QRCODE_READER +} diff --git a/app/src/main/java/org/linphone/assistant/CodecDownloaderFragment.java b/app/src/main/java/org/linphone/assistant/CodecDownloaderFragment.java new file mode 100644 index 000000000..4d4ec41ee --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/CodecDownloaderFragment.java @@ -0,0 +1,220 @@ +package org.linphone.assistant; + +/* +CodecDownloaderFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ProgressBar; +import android.widget.TextView; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.PayloadType; +import org.linphone.core.tools.OpenH264DownloadHelper; +import org.linphone.core.tools.OpenH264DownloadHelperListener; + +public class CodecDownloaderFragment extends Fragment { + private final Handler mHandler = new Handler(); + private TextView mQuestion; + private TextView mDownloading; + private TextView mDownloaded; + private Button mYes; + private Button mNo; + private Button mOk; + private ProgressBar mProgressBar; + private TextView mDownloadingInfo; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.assistant_codec_downloader, container, false); + + mQuestion = view.findViewById(R.id.question); + mDownloading = view.findViewById(R.id.downloading); + mDownloaded = view.findViewById(R.id.downloaded); + mYes = view.findViewById(R.id.answerYes); + mNo = view.findViewById(R.id.answerNo); + mOk = view.findViewById(R.id.answerOk); + mProgressBar = view.findViewById(R.id.progressBar); + mDownloadingInfo = view.findViewById(R.id.downloadingInfo); + + final OpenH264DownloadHelper codecDownloader = + LinphoneManager.getInstance().getOpenH264DownloadHelper(); + final OpenH264DownloadHelperListener codecListener = + new OpenH264DownloadHelperListener() { + + @Override + public void OnProgress(final int current, final int max) { + mHandler.post( + new Runnable() { + @Override + public void run() { + if (current <= max) { + hideAllItems(); + mDownloadingInfo.setText(current + " / " + max); + mDownloadingInfo.setVisibility(View.VISIBLE); + mDownloading.setVisibility(View.VISIBLE); + mProgressBar.setMax(max); + mProgressBar.setProgress(current); + mProgressBar.setVisibility(View.VISIBLE); + } else { + hideAllItems(); + mDownloaded.setVisibility(View.VISIBLE); + if (Build.VERSION.SDK_INT + >= Build.VERSION_CODES.LOLLIPOP_MR1) { + 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(); + mDownloaded.setText("Sorry an error has occurred."); + mDownloaded.setVisibility(View.VISIBLE); + mOk.setVisibility(View.VISIBLE); + enabledH264(false); + AssistantActivity.instance().endDownloadCodec(); + } + }); + } + }; + + codecDownloader.setOpenH264HelperListener(codecListener); + + mYes.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + hideAllItems(); + mProgressBar.setVisibility(View.VISIBLE); + codecDownloader.downloadCodec(); + } + }); + + mNo.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + enabledH264(false); + AssistantActivity.instance().endDownloadCodec(); + } + }); + hideAllItems(); + + if (savedInstanceState != null) { + if (savedInstanceState.containsKey("mQuestion")) + mQuestion.setVisibility((Integer) savedInstanceState.getSerializable("mQuestion")); + else mQuestion.setVisibility(View.VISIBLE); + + if (savedInstanceState.containsKey("mYes")) + mYes.setVisibility((Integer) savedInstanceState.getSerializable("mYes")); + else mYes.setVisibility(View.VISIBLE); + + if (savedInstanceState.containsKey("mNo")) + mNo.setVisibility((Integer) savedInstanceState.getSerializable("mNo")); + else mNo.setVisibility(View.VISIBLE); + + if (savedInstanceState.containsKey("mDownloading")) + mDownloading.setVisibility( + (Integer) savedInstanceState.getSerializable("mDownloading")); + + if (savedInstanceState.containsKey("mDownloaded")) + mDownloaded.setVisibility( + (Integer) savedInstanceState.getSerializable("mDownloaded")); + + if (savedInstanceState.containsKey("context_bar")) + mProgressBar.setVisibility( + (Integer) savedInstanceState.getSerializable("context_bar")); + + if (savedInstanceState.containsKey("mDownloadingInfo")) + mDownloadingInfo.setVisibility( + (Integer) savedInstanceState.getSerializable("mDownloadingInfo")); + + if (savedInstanceState.containsKey("mOk")) + mOk.setVisibility((Integer) savedInstanceState.getSerializable("mOk")); + } else { + mYes.setVisibility(View.VISIBLE); + mQuestion.setVisibility(View.VISIBLE); + mNo.setVisibility(View.VISIBLE); + } + + return view; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + if (mQuestion != null) outState.putSerializable("mQuestion", mQuestion.getVisibility()); + if (mDownloading != null) + outState.putSerializable("mDownloading", mDownloading.getVisibility()); + if (mDownloaded != null) + outState.putSerializable("mDownloaded", mDownloaded.getVisibility()); + if (mYes != null) outState.putSerializable("mYes", mYes.getVisibility()); + if (mNo != null) outState.putSerializable("mNo", mNo.getVisibility()); + if (mOk != null) outState.putSerializable("mOk", mOk.getVisibility()); + if (mProgressBar != null) + outState.putSerializable("context_bar", mProgressBar.getVisibility()); + if (mDownloadingInfo != null) + outState.putSerializable("mDownloadingInfo", mDownloadingInfo.getVisibility()); + super.onSaveInstanceState(outState); + } + + private void hideAllItems() { + if (mQuestion != null) mQuestion.setVisibility(View.INVISIBLE); + if (mDownloading != null) mDownloading.setVisibility(View.INVISIBLE); + if (mDownloaded != null) mDownloaded.setVisibility(View.INVISIBLE); + if (mYes != null) mYes.setVisibility(View.INVISIBLE); + if (mNo != null) mNo.setVisibility(View.INVISIBLE); + if (mOk != null) mOk.setVisibility(View.INVISIBLE); + if (mProgressBar != null) mProgressBar.setVisibility(View.INVISIBLE); + if (mDownloadingInfo != null) mDownloadingInfo.setVisibility(View.INVISIBLE); + } + + private void enabledH264(boolean enable) { + PayloadType h264 = null; + for (PayloadType pt : LinphoneManager.getLc().getVideoPayloadTypes()) { + if (pt.getMimeType().equals("H264")) h264 = pt; + } + + if (h264 != null) { + h264.enable(enable); + } + } +} diff --git a/app/src/main/java/org/linphone/assistant/CountryAdapter.java b/app/src/main/java/org/linphone/assistant/CountryAdapter.java deleted file mode 100644 index cdde6614d..000000000 --- a/app/src/main/java/org/linphone/assistant/CountryAdapter.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.linphone.assistant; - -/* -CountryAdapter.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.Filter; -import android.widget.Filterable; -import android.widget.TextView; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.linphone.R; -import org.linphone.core.DialPlan; -import org.linphone.core.Factory; - -public class CountryAdapter extends BaseAdapter implements Filterable { - private Context mContext; - private LayoutInflater mInflater; - private final DialPlan[] mAllCountries; - private List mFilteredCountries; - - public CountryAdapter(Context context, LayoutInflater inflater) { - mContext = context; - mInflater = inflater; - mAllCountries = Factory.instance().getDialPlans(); - mFilteredCountries = new ArrayList<>(Arrays.asList(mAllCountries)); - } - - @Override - public int getCount() { - return mFilteredCountries.size(); - } - - @Override - public DialPlan getItem(int position) { - return mFilteredCountries.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View view; - - if (convertView != null) { - view = convertView; - } else { - view = mInflater.inflate(R.layout.country_cell, parent, false); - } - - DialPlan c = mFilteredCountries.get(position); - - TextView name = view.findViewById(R.id.country_name); - name.setText(c.getCountry()); - - TextView dial_code = view.findViewById(R.id.country_prefix); - dial_code.setText( - String.format( - mContext.getString(R.string.country_code), c.getCountryCallingCode())); - - view.setTag(c); - return view; - } - - @Override - public Filter getFilter() { - return new Filter() { - @Override - protected FilterResults performFiltering(CharSequence constraint) { - List filteredCountries = new ArrayList<>(); - for (DialPlan c : mAllCountries) { - if (c.getCountry().toLowerCase().contains(constraint) - || c.getCountryCallingCode().contains(constraint)) { - filteredCountries.add(c); - } - } - FilterResults filterResults = new FilterResults(); - filterResults.values = filteredCountries; - return filterResults; - } - - @Override - @SuppressWarnings("unchecked") - protected void publishResults(CharSequence constraint, FilterResults results) { - mFilteredCountries = (List) results.values; - notifyDataSetChanged(); - } - }; - } -} diff --git a/app/src/main/java/org/linphone/assistant/CountryListFragment.java b/app/src/main/java/org/linphone/assistant/CountryListFragment.java new file mode 100644 index 000000000..34dbedca7 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/CountryListFragment.java @@ -0,0 +1,90 @@ +package org.linphone.assistant; + +/* +CountryListFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ListView; +import org.linphone.R; +import org.linphone.core.DialPlan; + +public class CountryListFragment extends Fragment + implements AdapterView.OnItemClickListener, View.OnClickListener { + private ListView mList; + private EditText mSearch; + private ImageView mClearSearchField; + private AssistantActivity.CountryListAdapter mAdapter; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.assistant_country_list, container, false); + mAdapter = AssistantActivity.instance().getCountryListAdapter(); + mAdapter.setInflater(inflater); + + mSearch = view.findViewById(R.id.search_country); + mClearSearchField = view.findViewById(R.id.clearSearchField); + mClearSearchField.setOnClickListener(this); + + mList = view.findViewById(R.id.countryList); + mList.setAdapter(mAdapter); + mList.setOnItemClickListener(this); + + mSearch.addTextChangedListener( + new TextWatcher() { + @Override + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mAdapter.getFilter().filter(s); + } + + @Override + public void afterTextChanged(Editable s) {} + }); + mSearch.setText(""); + + return view; + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + AssistantActivity.instance().country = (DialPlan) view.getTag(); + AssistantActivity.instance().onBackPressed(); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.clearSearchField) { + mSearch.setText(""); + } + } +} diff --git a/app/src/main/java/org/linphone/assistant/CountryPicker.java b/app/src/main/java/org/linphone/assistant/CountryPicker.java deleted file mode 100644 index bfeb075db..000000000 --- a/app/src/main/java/org/linphone/assistant/CountryPicker.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.linphone.assistant; - -/* -CountryPicker.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.Context; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.AdapterView; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.ListView; -import org.linphone.R; -import org.linphone.core.DialPlan; - -public class CountryPicker { - private Context mContext; - private LayoutInflater mInflater; - private CountryAdapter mAdapter; - private ListView mList; - private EditText mSearch; - private ImageView mClear; - private CountryPickedListener mListener; - - public CountryPicker(Context context, CountryPickedListener listener) { - mContext = context; - mListener = listener; - mInflater = LayoutInflater.from(mContext); - mAdapter = new CountryAdapter(mContext, mInflater); - } - - private View createView() { - View view = mInflater.inflate(R.layout.assistant_country_list, null, false); - - mList = view.findViewById(R.id.countryList); - mList.setAdapter(mAdapter); - mList.setOnItemClickListener( - new AdapterView.OnItemClickListener() { - @Override - public void onItemClick( - AdapterView parent, View view, int position, long id) { - DialPlan dp = null; - if (position > 0 && position < mAdapter.getCount()) { - dp = mAdapter.getItem(position); - } - - if (mListener != null) { - mListener.onCountryClicked(dp); - } - } - }); - - mSearch = view.findViewById(R.id.search_country); - mSearch.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - mAdapter.getFilter().filter(s); - } - }); - mSearch.setText(""); - - mClear = view.findViewById(R.id.clear_field); - mClear.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - mSearch.setText(""); - } - }); - - return view; - } - - public View getView() { - View view = createView(); - return view; - } - - public interface CountryPickedListener { - void onCountryClicked(DialPlan dialPlan); - } -} diff --git a/app/src/main/java/org/linphone/assistant/CreateAccountActivationFragment.java b/app/src/main/java/org/linphone/assistant/CreateAccountActivationFragment.java new file mode 100644 index 000000000..dc15184a9 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/CreateAccountActivationFragment.java @@ -0,0 +1,138 @@ +package org.linphone.assistant; +/* +CreateAccountActivationFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.AccountCreator; +import org.linphone.core.AccountCreatorListener; +import org.linphone.settings.LinphonePreferences; + +public class CreateAccountActivationFragment extends Fragment + implements OnClickListener, AccountCreatorListener { + private String mUsername, mPassword; + private Button mCheckAccount; + private TextView mEmail; + private AccountCreator mAccountCreator; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = + inflater.inflate( + R.layout.assistant_account_creation_email_activation, container, false); + + mAccountCreator = + LinphoneManager.getLc() + .createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); + mAccountCreator.setListener(this); + + mUsername = getArguments().getString("Username"); + mPassword = getArguments().getString("Password"); + + mAccountCreator.setUsername(mUsername); + mAccountCreator.setPassword(mPassword); + + mEmail = view.findViewById(R.id.send_email); + mEmail.setText(getArguments().getString("Email")); + + mCheckAccount = view.findViewById(R.id.assistant_check); + mCheckAccount.setOnClickListener(this); + return view; + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.assistant_check) { + mCheckAccount.setEnabled(false); + mAccountCreator.isAccountActivated(); + } + } + + @Override + public void onIsAccountExist( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onCreateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onLinkAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAlias( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAccountActivated( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(AccountCreator.Status.AccountNotActivated)) { + Toast.makeText( + getActivity(), + getString(R.string.assistant_account_not_validated), + Toast.LENGTH_LONG) + .show(); + } else if (status.equals(AccountCreator.Status.AccountActivated)) { + AssistantActivity.instance().linphoneLogIn(accountCreator); + AssistantActivity.instance().isAccountVerified(); + } else { + Toast.makeText( + getActivity(), + getString(R.string.wizard_server_unavailable), + Toast.LENGTH_LONG) + .show(); + } + mCheckAccount.setEnabled(true); + } + + @Override + public void onRecoverAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAccountLinked( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAliasUsed( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onUpdateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} +} diff --git a/app/src/main/java/org/linphone/assistant/CreateAccountCodeActivationFragment.java b/app/src/main/java/org/linphone/assistant/CreateAccountCodeActivationFragment.java new file mode 100644 index 000000000..8354458e3 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/CreateAccountCodeActivationFragment.java @@ -0,0 +1,227 @@ +package org.linphone.assistant; +/* +CreateAccountCodeActivationFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.AccountCreator; +import org.linphone.core.AccountCreatorListener; +import org.linphone.settings.LinphonePreferences; + +public class CreateAccountCodeActivationFragment extends Fragment + implements AccountCreatorListener { + private String mUsername, mPhone, mDialcode; + private TextView mTitle, mPhonenumber; + private EditText mCode; + private boolean mRecoverAccount = false, mLinkAccount = false; + private int mCodeLength, mAccountNumber; + private ImageView mBack; + private Button mCheckAccount; + private AccountCreator mAccountCreator; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = + inflater.inflate( + R.layout.assistant_account_creation_code_activation, container, false); + + mUsername = getArguments().getString("Username"); + mPhone = getArguments().getString("Phone"); + mDialcode = getArguments().getString("Dialcode"); + mRecoverAccount = getArguments().getBoolean("RecoverAccount"); + mLinkAccount = getArguments().getBoolean("LinkAccount"); + mAccountNumber = getArguments().getInt("AccountNumber"); + + mCodeLength = LinphonePreferences.instance().getCodeLength(); + mAccountCreator = + LinphoneManager.getLc() + .createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); + mAccountCreator.setListener(this); + mAccountCreator.setUsername(mUsername); + mAccountCreator.setPhoneNumber(mPhone, mDialcode); + + mBack = view.findViewById(R.id.back); + if (mBack != null) mBack.setVisibility(Button.INVISIBLE); + + mTitle = view.findViewById(R.id.title_account_activation); + if (mLinkAccount) { + mTitle.setText(getString(R.string.assistant_link_account)); + } else if (mRecoverAccount) { + mTitle.setText(getString(R.string.assistant_linphone_account)); + } + + mPhonenumber = view.findViewById(R.id.send_phone_number); + mPhonenumber.setText(mAccountCreator.getPhoneNumber()); + + mCode = view.findViewById(R.id.assistant_code); + mCode.addTextChangedListener( + new TextWatcher() { + @Override + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + if (s.length() == mCodeLength) { + mCheckAccount.setEnabled(true); + } else { + mCheckAccount.setEnabled(false); + } + } + }); + + mCheckAccount = view.findViewById(R.id.assistant_check); + mCheckAccount.setEnabled(false); + mCheckAccount.setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + mCheckAccount.setEnabled(false); + mAccountCreator.setActivationCode(mCode.getText().toString()); + if (mLinkAccount) { + linkAccount(); + } else { + activateAccount(); + } + } + }); + + return view; + } + + private void linkAccount() { + mAccountCreator.setUsername( + LinphonePreferences.instance().getAccountUsername(mAccountNumber)); + mAccountCreator.setHa1(LinphonePreferences.instance().getAccountHa1(mAccountNumber)); + mAccountCreator.activateAlias(); + } + + private void activateAccount() { + if (mAccountCreator.getUsername() == null) { + mAccountCreator.setUsername(mAccountCreator.getPhoneNumber()); + } + mAccountCreator.activateAccount(); + } + + @Override + public void onIsAccountExist( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onCreateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(AccountCreator.Status.AccountActivated)) { + mCheckAccount.setEnabled(true); + if (accountCreator.getUsername() != null) { + AssistantActivity.instance().linphoneLogIn(accountCreator); + if (!mRecoverAccount) { + AssistantActivity.instance().isAccountVerified(); + } else { + AssistantActivity.instance().success(); + } + } else { + AssistantActivity.instance().linphoneLogIn(accountCreator); + if (!mRecoverAccount) { + AssistantActivity.instance().isAccountVerified(); + } else { + AssistantActivity.instance().success(); + } + } + } else if (status.equals(AccountCreator.Status.RequestFailed)) { + Toast.makeText( + getActivity(), + getString(R.string.wizard_server_unavailable), + Toast.LENGTH_LONG) + .show(); + } else { + Toast.makeText( + getActivity(), + getString(R.string.assistant_error_confirmation_code), + Toast.LENGTH_LONG) + .show(); + AssistantActivity.instance().displayAssistantLinphoneLogin(mPhone, mDialcode); + } + } + + @Override + public void onLinkAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAlias( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(AccountCreator.Status.AccountActivated)) { + LinphonePreferences.instance() + .setPrefix( + mAccountNumber, + org.linphone.core.Utils.getPrefixFromE164( + accountCreator.getPhoneNumber())); + LinphonePreferences.instance().setLinkPopupTime(""); + AssistantActivity.instance().hideKeyboard(); + AssistantActivity.instance().success(); + } + } + + @Override + public void onIsAccountActivated( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onRecoverAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAccountLinked( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAliasUsed( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onUpdateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} +} diff --git a/app/src/main/java/org/linphone/assistant/CreateAccountFragment.java b/app/src/main/java/org/linphone/assistant/CreateAccountFragment.java new file mode 100644 index 000000000..37ac55e16 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/CreateAccountFragment.java @@ -0,0 +1,804 @@ +package org.linphone.assistant; +/* +CreateAccountFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.telephony.TelephonyManager; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +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.R; +import org.linphone.core.AccountCreator; +import org.linphone.core.AccountCreator.Status; +import org.linphone.core.AccountCreatorListener; +import org.linphone.core.DialPlan; +import org.linphone.settings.LinphonePreferences; +import org.linphone.utils.LinphoneUtils; + +public class CreateAccountFragment extends Fragment + implements CompoundButton.OnCheckedChangeListener, OnClickListener, AccountCreatorListener { + private final Pattern UPPER_CASE_REGEX = Pattern.compile("[A-Z]"); + + private EditText mPhoneNumberEdit, + mUsernameEdit, + mPasswordEdit, + mPasswordConfirmEdit, + mEmailEdit, + mDialCode; + private TextView mPhoneNumberError, + mPasswordError, + mPasswordConfirmError, + mEmailError, + mAssisstantTitle, + mSipUri, + mSkip, + mInstruction; + private ImageView mPhoneNumberInfo; + private boolean mPasswordOk = false; + private boolean mEmailOk = false; + private boolean mConfirmPasswordOk = false; + private boolean mLinkAccount = false; + private Button mCreateAccount, mSelectCountry; + private CheckBox mUseUsername, mUseEmail; + private String mAddressSip = ""; + private int mCountryCode; + private LinearLayout mPhoneNumberLayout, + mUsernameLayout, + mEmailLayout, + mPasswordLayout, + mPasswordConfirmLayout; + private AccountCreator mAccountCreator; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.assistant_account_creation, container, false); + + // Initialize mAccountCreator + mAccountCreator = + LinphoneManager.getLc() + .createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); + mAccountCreator.setListener(this); + mAccountCreator.setDomain(getString(R.string.default_domain)); + + mInstruction = view.findViewById(R.id.message_create_account); + + mCreateAccount = view.findViewById(R.id.assistant_create); + + mPhoneNumberLayout = view.findViewById(R.id.phone_number_layout); + mUsernameLayout = view.findViewById(R.id.username_layout); + mEmailLayout = view.findViewById(R.id.email_layout); + mPasswordLayout = view.findViewById(R.id.password_layout); + mPasswordConfirmLayout = view.findViewById(R.id.password_confirm_layout); + + mUseUsername = view.findViewById(R.id.use_username); + mUseEmail = view.findViewById(R.id.use_email); + + mUsernameEdit = view.findViewById(R.id.username); + + mPhoneNumberError = view.findViewById(R.id.phone_number_error); + mPhoneNumberEdit = view.findViewById(R.id.phone_number); + mSipUri = view.findViewById(R.id.sip_uri); + + mPhoneNumberInfo = view.findViewById(R.id.info_phone_number); + + mSelectCountry = view.findViewById(R.id.select_country); + mDialCode = view.findViewById(R.id.dial_code); + mAssisstantTitle = view.findViewById(R.id.assistant_title); + + mPasswordError = view.findViewById(R.id.password_error); + mPasswordEdit = view.findViewById(R.id.password); + + mPasswordConfirmError = view.findViewById(R.id.confirm_password_error); + mPasswordConfirmEdit = view.findViewById(R.id.confirm_password); + + mEmailError = view.findViewById(R.id.email_error); + mEmailEdit = view.findViewById(R.id.email); + + mSkip = view.findViewById(R.id.assistant_skip); + + // Phone number + if (getResources().getBoolean(R.bool.use_phone_number_validation)) { + getActivity().getApplicationContext(); + // Automatically get the country code from the phone + TelephonyManager tm = + (TelephonyManager) + getActivity() + .getApplicationContext() + .getSystemService(Context.TELEPHONY_SERVICE); + String countryIso = tm.getNetworkCountryIso(); + mCountryCode = org.linphone.core.Utils.getCccFromIso(countryIso.toUpperCase()); + + mPhoneNumberLayout.setVisibility(View.VISIBLE); + + mPhoneNumberInfo.setOnClickListener(this); + mSelectCountry.setOnClickListener(this); + + DialPlan c = AssistantActivity.instance().country; + if (c != null) { + mSelectCountry.setText(c.getCountry()); + mDialCode.setText( + c.getCountryCallingCode().contains("+") + ? c.getCountryCallingCode() + : "+" + c.getCountryCallingCode()); + } else { + c = + AssistantActivity.instance() + .getCountryListAdapter() + .getCountryFromCountryCode(String.valueOf(mCountryCode)); + if (c != null) { + mSelectCountry.setText(c.getCountry()); + mDialCode.setText( + c.getCountryCallingCode().contains("+") + ? c.getCountryCallingCode() + : "+" + c.getCountryCallingCode()); + } + } + + // Allow user to enter a username instead use the phone number as username + if (getResources().getBoolean(R.bool.assistant_allow_username)) { + mUseUsername.setVisibility(View.VISIBLE); + mUseUsername.setOnCheckedChangeListener(this); + } + addPhoneNumberHandler(mPhoneNumberEdit); + addPhoneNumberHandler(mDialCode); + } + + // Password & email address + if (getResources().getBoolean(R.bool.isTablet) + || !getResources().getBoolean(R.bool.use_phone_number_validation)) { + mUseEmail.setVisibility(View.VISIBLE); + mUseEmail.setOnCheckedChangeListener(this); + + if (getResources().getBoolean(R.bool.pre_fill_email_in_assistant)) { + Account[] accounts = + AccountManager.get(getActivity()).getAccountsByType("com.google"); + + for (Account account : accounts) { + if (isEmailCorrect(account.name)) { + String possibleEmail = account.name; + mEmailEdit.setText(possibleEmail); + mAccountCreator.setEmail(possibleEmail); + mEmailOk = true; + break; + } + } + } + + addPasswordHandler(mPasswordEdit); + addConfirmPasswordHandler(mPasswordEdit, mPasswordConfirmEdit); + addEmailHandler(mEmailEdit); + } + + // Hide phone number and display username/email/password + if (!getResources().getBoolean(R.bool.use_phone_number_validation)) { + mUseEmail.setVisibility(View.GONE); + mUseUsername.setVisibility(View.GONE); + + mUsernameLayout.setVisibility(View.VISIBLE); + mPasswordLayout.setVisibility(View.VISIBLE); + mPasswordConfirmLayout.setVisibility(View.VISIBLE); + mEmailLayout.setVisibility(View.VISIBLE); + } + + // Link account with phone number + if (getArguments().getBoolean("LinkPhoneNumber")) { + mLinkAccount = true; + mUseEmail.setVisibility(View.GONE); + mUseUsername.setVisibility(View.GONE); + + mUsernameLayout.setVisibility(View.GONE); + mPasswordLayout.setVisibility(View.GONE); + mPasswordConfirmLayout.setVisibility(View.GONE); + mEmailLayout.setVisibility(View.GONE); + + mSkip.setVisibility(View.VISIBLE); + mSkip.setOnClickListener(this); + + mCreateAccount.setText(getResources().getString(R.string.link_account)); + mAssisstantTitle.setText(getResources().getString(R.string.link_account)); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mAccountCreator.setLanguage(Locale.getDefault().toLanguageTag()); + } + + addUsernameHandler(mUsernameEdit); + + mCreateAccount.setEnabled(true); + mCreateAccount.setOnClickListener(this); + + return view; + } + + @Override + public void onPause() { + super.onPause(); + mAccountCreator.setListener(null); + } + + private String getUsername() { + if (mUsernameEdit != null) { + String username = mUsernameEdit.getText().toString(); + return username.toLowerCase(Locale.getDefault()); + } + return null; + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.use_username) { + if (isChecked) { + mUsernameLayout.setVisibility(View.VISIBLE); + onTextChanged2(); + } else { + mUsernameLayout.setVisibility(View.GONE); + mAccountCreator.setUsername(null); + onTextChanged2(); + } + } else if (buttonView.getId() == R.id.use_email) { + if (isChecked) { + mDialCode.setBackgroundResource(R.drawable.resizable_textfield); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); + mUseUsername.setEnabled(false); + mDialCode.setEnabled(false); + mSelectCountry.setEnabled(false); + mPhoneNumberEdit.setEnabled(false); + mEmailLayout.setVisibility(View.VISIBLE); + mPasswordLayout.setVisibility(View.VISIBLE); + mPasswordConfirmLayout.setVisibility(View.VISIBLE); + mUsernameLayout.setVisibility(View.VISIBLE); + mUseUsername.setVisibility(CheckBox.GONE); + mPhoneNumberLayout.setVisibility(LinearLayout.GONE); + mInstruction.setText(getString(R.string.assistant_create_account_part_email)); + } else { + if (!mUseUsername.isChecked()) { + mUsernameLayout.setVisibility(View.GONE); + } + mUseUsername.setEnabled(true); + mDialCode.setEnabled(true); + mSelectCountry.setEnabled(true); + mPhoneNumberEdit.setEnabled(true); + mEmailLayout.setVisibility(View.GONE); + mPasswordLayout.setVisibility(View.GONE); + mPasswordConfirmLayout.setVisibility(View.GONE); + mUseUsername.setVisibility(CheckBox.VISIBLE); + mPhoneNumberLayout.setVisibility(LinearLayout.VISIBLE); + mInstruction.setText(getString(R.string.assistant_create_account_part_1)); + } + } + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.select_country) { + AssistantActivity.instance().displayCountryChooser(); + } else if (id == R.id.assistant_skip) { + if (getArguments().getBoolean("LinkFromPref")) { + AssistantActivity.instance().finish(); + } else { + AssistantActivity.instance().success(); + } + } else if (id == R.id.info_phone_number) { + if (mLinkAccount) { + new AlertDialog.Builder(getActivity()) + .setTitle(getString(R.string.phone_number_info_title)) + .setMessage( + getString(R.string.phone_number_link_info_content) + + "\n" + + getString( + R.string + .phone_number_link_info_content_already_account)) + .show(); + } else { + new AlertDialog.Builder(getActivity()) + .setTitle(getString(R.string.phone_number_info_title)) + .setMessage(getString(R.string.phone_number_info_content)) + .show(); + } + } else if (id == R.id.assistant_create) { + mCreateAccount.setEnabled(false); + if (mLinkAccount) { + addAlias(); + } else { + if (mUseEmail.isChecked()) mAccountCreator.setPhoneNumber(null, null); + if (getUsername().length() > 0) { + mAccountCreator.isAccountExist(); + } else { + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForUsernameStatus( + AccountCreator.UsernameStatus.TooShort), + AssistantActivity.instance()); + mCreateAccount.setEnabled(true); + } + } + } + } + + private boolean isEmailCorrect(String email) { + Pattern emailPattern = Patterns.EMAIL_ADDRESS; + return emailPattern.matcher(email).matches(); + } + + private boolean isPasswordCorrect(String password) { + return password.length() >= 1; + } + + private void addAlias() { + mAccountCreator.setUsername( + LinphonePreferences.instance() + .getAccountUsername( + LinphonePreferences.instance().getDefaultAccountIndex())); + int status = + mAccountCreator.setPhoneNumber( + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode)); + boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt(); + if (isOk) { + mAccountCreator.linkAccount(); + } else { + mCreateAccount.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForPhoneNumberStatus(status), AssistantActivity.instance()); + LinphoneUtils.displayError( + isOk, mPhoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); + } + } + + private void createAccount() { + if ((getResources().getBoolean(R.bool.isTablet) + || !getResources().getBoolean(R.bool.use_phone_number_validation)) + && mUseEmail.isChecked()) { + AccountCreator.EmailStatus emailStatus; + AccountCreator.PasswordStatus passwordStatus; + + passwordStatus = mAccountCreator.setPassword(mPasswordEdit.getText().toString()); + emailStatus = mAccountCreator.setEmail(mEmailEdit.getText().toString()); + + if (!mEmailOk) { + LinphoneUtils.displayError( + false, mEmailError, LinphoneUtils.errorForEmailStatus(emailStatus)); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForEmailStatus(emailStatus), + AssistantActivity.instance()); + } else if (!mPasswordOk) { + LinphoneUtils.displayError( + false, + mPasswordError, + LinphoneUtils.errorForPasswordStatus(passwordStatus)); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForPasswordStatus(passwordStatus), + AssistantActivity.instance()); + } else if (!mConfirmPasswordOk) { + String msg; + if (mPasswordConfirmEdit + .getText() + .toString() + .equals(mPasswordEdit.getText().toString())) { + msg = getString(R.string.wizard_password_incorrect); + } else { + msg = getString(R.string.wizard_passwords_unmatched); + } + LinphoneUtils.displayError(false, mPasswordError, msg); + LinphoneUtils.displayErrorAlert(msg, AssistantActivity.instance()); + } else { + mAccountCreator.createAccount(); + } + } else { + if (mPhoneNumberEdit.length() > 0 || mDialCode.length() > 1) { + int phoneStatus; + boolean isOk; + phoneStatus = + mAccountCreator.setPhoneNumber( + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode)); + isOk = phoneStatus == AccountCreator.PhoneNumberStatus.Ok.toInt(); + if (!mUseUsername.isChecked() && mAccountCreator.getUsername() == null) { + mAccountCreator.setUsername(mAccountCreator.getPhoneNumber()); + } else { + mAccountCreator.setUsername(mUsernameEdit.getText().toString()); + mAccountCreator.setPhoneNumber( + mPhoneNumberEdit.getText().toString(), mDialCode.getText().toString()); + } + if (isOk) { + mAccountCreator.createAccount(); + } else { + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForPhoneNumberStatus(phoneStatus), + AssistantActivity.instance()); + LinphoneUtils.displayError( + isOk, + mPhoneNumberError, + LinphoneUtils.errorForPhoneNumberStatus(phoneStatus)); + } + } else { + LinphoneUtils.displayErrorAlert( + getString(R.string.assistant_create_account_part_1), + AssistantActivity.instance()); + } + } + mCreateAccount.setEnabled(true); + } + + private int getPhoneNumberStatus() { + int status = + mAccountCreator.setPhoneNumber( + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode)); + mAddressSip = mAccountCreator.getPhoneNumber(); + return status; + } + + private void onTextChanged2() { + String msg = ""; + mAccountCreator.setUsername(getUsername()); + + if (!mUseEmail.isChecked() + && getResources().getBoolean(R.bool.use_phone_number_validation)) { + int status = getPhoneNumberStatus(); + boolean isOk = (status == AccountCreator.PhoneNumberStatus.Ok.toInt()); + LinphoneUtils.displayError( + isOk, mPhoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); + + // Username or phone number + if (getResources().getBoolean(R.bool.assistant_allow_username) + && mUseUsername.isChecked()) { + mAddressSip = getUsername(); + } + + if (!isOk) { + if (status == AccountCreator.PhoneNumberStatus.InvalidCountryCode.toInt()) { + mDialCode.setBackgroundResource(R.drawable.resizable_textfield_error); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); + } else { + mDialCode.setBackgroundResource(R.drawable.resizable_textfield); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield_error); + } + + } else { + mDialCode.setBackgroundResource(R.drawable.resizable_textfield); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); + if (!mLinkAccount && mAddressSip.length() > 0) { + msg = + getResources() + .getString( + R.string + .assistant_create_account_phone_number_address) + + " <" + + mAddressSip + + "@" + + getResources().getString(R.string.default_domain) + + ">"; + } + } + } else { + mAddressSip = getUsername(); + if (mAddressSip.length() > 0) { + msg = + getResources() + .getString( + R.string + .assistant_create_account_phone_number_address) + + " "; + } + } + mSipUri.setText(msg); + } + + private void addPhoneNumberHandler(final EditText field) { + field.addTextChangedListener( + new TextWatcher() { + public void afterTextChanged(Editable s) { + if (field.equals(mDialCode)) { + DialPlan c = + AssistantActivity.instance() + .getCountryListAdapter() + .getCountryFromCountryCode( + mDialCode.getText().toString()); + if (c != null) { + AssistantActivity.instance().country = c; + mSelectCountry.setText(c.getCountry()); + } else { + mSelectCountry.setText(R.string.select_your_country); + } + } + } + + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + public void onTextChanged(CharSequence s, int start, int count, int after) { + onTextChanged2(); + } + }); + } + + private void addUsernameHandler(final EditText field) { + field.addTextChangedListener( + new TextWatcher() { + public void afterTextChanged(Editable s) { + Matcher matcher = UPPER_CASE_REGEX.matcher(s); + while (matcher.find()) { + 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 onTextChanged(CharSequence s, int start, int count, int after) { + onTextChanged2(); + } + }); + } + + private void addEmailHandler(final EditText field) { + field.addTextChangedListener( + new TextWatcher() { + public void afterTextChanged(Editable s) { + mEmailOk = false; + AccountCreator.EmailStatus status = + mAccountCreator.setEmail(field.getText().toString()); + if (status.equals(AccountCreator.EmailStatus.Ok)) { + mEmailOk = true; + LinphoneUtils.displayError(mEmailOk, mEmailError, ""); + } else { + LinphoneUtils.displayError( + mEmailOk, + mEmailError, + LinphoneUtils.errorForEmailStatus(status)); + } + } + + public void beforeTextChanged( + 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) { + TextWatcher passwordListener = + new TextWatcher() { + public void afterTextChanged(Editable s) { + mPasswordOk = false; + AccountCreator.PasswordStatus status = + mAccountCreator.setPassword(field1.getText().toString()); + if (isPasswordCorrect(field1.getText().toString())) { + mPasswordOk = true; + LinphoneUtils.displayError(mPasswordOk, mPasswordError, ""); + } else { + LinphoneUtils.displayError( + mPasswordOk, + mPasswordError, + LinphoneUtils.errorForPasswordStatus(status)); + } + } + + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + public void onTextChanged(CharSequence s, int start, int count, int after) {} + }; + + field1.addTextChangedListener(passwordListener); + } + + private void addConfirmPasswordHandler(final EditText field1, final EditText field2) { + TextWatcher passwordListener = + new TextWatcher() { + public void afterTextChanged(Editable s) { + mConfirmPasswordOk = false; + if (field1.getText().toString().equals(field2.getText().toString())) { + mConfirmPasswordOk = true; + if (!isPasswordCorrect(field1.getText().toString())) { + LinphoneUtils.displayError( + mPasswordOk, + mPasswordError, + getString(R.string.wizard_password_incorrect)); + } else { + LinphoneUtils.displayError( + mConfirmPasswordOk, mPasswordConfirmError, ""); + } + } else { + LinphoneUtils.displayError( + mConfirmPasswordOk, + mPasswordConfirmError, + getString(R.string.wizard_passwords_unmatched)); + } + } + + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + public void onTextChanged(CharSequence s, int start, int count, int after) {} + }; + field1.addTextChangedListener(passwordListener); + field2.addTextChangedListener(passwordListener); + } + + @Override + public void onIsAccountExist(AccountCreator accountCreator, final Status status, String resp) { + if (status.equals(Status.AccountExist) || status.equals(Status.AccountExistWithAlias)) { + if (mUseEmail.isChecked()) { + mCreateAccount.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); + } else { + accountCreator.isAliasUsed(); + } + } else { + createAccount(); + } + } + + @Override + public void onCreateAccount(AccountCreator accountCreator, Status status, String resp) { + if (status.equals(Status.AccountCreated)) { + if (mUseEmail.isChecked() + || !getResources().getBoolean(R.bool.use_phone_number_validation)) { + AssistantActivity.instance() + .displayAssistantConfirm( + getUsername(), + mPasswordEdit.getText().toString(), + mEmailEdit.getText().toString()); + } else { + AssistantActivity.instance() + .displayAssistantCodeConfirm( + getUsername(), + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode), + false); + } + } else { + mCreateAccount.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); + } + } + + @Override + public void onActivateAccount(AccountCreator accountCreator, Status status, String resp) {} + + @Override + public void onLinkAccount(AccountCreator accountCreator, Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(Status.RequestOk)) { + AssistantActivity.instance() + .displayAssistantCodeConfirm( + getUsername(), + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode), + false); + } + } + + @Override + public void onActivateAlias(AccountCreator accountCreator, Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(Status.RequestOk)) { + AssistantActivity.instance() + .displayAssistantCodeConfirm( + getUsername(), + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode), + false); + } + } + + @Override + public void onIsAccountActivated(AccountCreator accountCreator, Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(Status.AccountNotActivated)) { + if (getResources().getBoolean(R.bool.isTablet) + || !getResources().getBoolean(R.bool.use_phone_number_validation)) { + // mAccountCreator.activateAccount(); // Resend email TODO + } else { + accountCreator.recoverAccount(); // Resend SMS + } + } else { + mCreateAccount.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); + } + } + + @Override + public void onRecoverAccount(AccountCreator accountCreator, Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(Status.RequestOk)) { + AssistantActivity.instance() + .displayAssistantCodeConfirm( + getUsername(), + mPhoneNumberEdit.getText().toString(), + mDialCode.getText().toString(), + false); + } else { + mCreateAccount.setEnabled(true); + // SMS error + LinphoneUtils.displayErrorAlert( + getString(R.string.request_failed), AssistantActivity.instance()); + } + } + + @Override + public void onIsAccountLinked(AccountCreator accountCreator, Status status, String resp) {} + + @Override + public void onIsAliasUsed(AccountCreator ac, Status status, String resp) { + if (AssistantActivity.instance() == null) { + return; + } + if (status.equals(Status.AliasIsAccount) || status.equals(Status.AliasExist)) { + if (mAccountCreator.getPhoneNumber() != null + && mAccountCreator.getUsername() != null + && mAccountCreator.getPhoneNumber().compareTo(mAccountCreator.getUsername()) + == 0) { + mAccountCreator.isAccountActivated(); + } else { + mCreateAccount.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); + } + } else { + mAccountCreator.isAccountActivated(); + } + } + + @Override + public void onUpdateAccount(AccountCreator accountCreator, Status status, String resp) {} +} diff --git a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java deleted file mode 100644 index d3f53fe31..000000000 --- a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.linphone.assistant; - -/* -EchoCancellerCalibrationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.Manifest; -import android.content.Context; -import android.content.pm.PackageManager; -import android.media.AudioManager; -import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.core.app.ActivityCompat; -import org.linphone.LinphoneManager; -import org.linphone.R; -import org.linphone.core.Core; -import org.linphone.core.CoreListenerStub; -import org.linphone.core.EcCalibratorStatus; -import org.linphone.core.tools.Log; -import org.linphone.settings.LinphonePreferences; - -public class EchoCancellerCalibrationAssistantActivity extends AssistantActivity { - private static final int RECORD_AUDIO_PERMISSION_RESULT = 1; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_echo_canceller_calibration); - } - - @Override - protected void onStart() { - super.onStart(); - - checkRecordAudioPermissionForEchoCancellerCalibration(); - } - - @Override - protected void onResume() { - super.onResume(); - - LinphonePreferences.instance().setEchoCancellationCalibrationDone(true); - if (isRecordAudioPermissionGranted()) { - startEchoCancellerCalibration(); - } else { - goToLinphoneActivity(); - } - } - - @Override - public void onRequestPermissionsResult( - int requestCode, String[] permissions, final int[] grantResults) { - for (int i = 0; i < permissions.length; i++) { - Log.i( - "[Permission] " - + permissions[i] - + " has been " - + (grantResults[i] == PackageManager.PERMISSION_GRANTED - ? "granted" - : "denied")); - } - - switch (requestCode) { - case RECORD_AUDIO_PERMISSION_RESULT: - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - startEchoCancellerCalibration(); - } else { - // TODO: permission denied, display something to the user - } - break; - } - } - - private boolean isRecordAudioPermissionGranted() { - int permissionGranted = - getPackageManager() - .checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()); - Log.i( - "[Permission] Manifest.permission.RECORD_AUDIO is " - + (permissionGranted == PackageManager.PERMISSION_GRANTED - ? "granted" - : "denied")); - - return permissionGranted == PackageManager.PERMISSION_GRANTED; - } - - private void checkRecordAudioPermissionForEchoCancellerCalibration() { - if (!isRecordAudioPermissionGranted()) { - Log.i("[Permission] Asking for " + Manifest.permission.RECORD_AUDIO); - ActivityCompat.requestPermissions( - this, - new String[] {Manifest.permission.RECORD_AUDIO}, - RECORD_AUDIO_PERMISSION_RESULT); - } - } - - private void startEchoCancellerCalibration() { - LinphoneManager.getLc() - .addListener( - new CoreListenerStub() { - @Override - public void onEcCalibrationResult( - Core core, EcCalibratorStatus status, int delayMs) { - if (status == EcCalibratorStatus.InProgress) return; - core.removeListener(this); - LinphoneManager.getInstance().routeAudioToReceiver(); - goToLinphoneActivity(); - - ((AudioManager) getSystemService(Context.AUDIO_SERVICE)) - .setMode(AudioManager.MODE_NORMAL); - } - }); - LinphoneManager.getInstance().startEcCalibration(); - } -} diff --git a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationFragment.java b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationFragment.java new file mode 100644 index 000000000..bd463dccc --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationFragment.java @@ -0,0 +1,117 @@ +package org.linphone.assistant; + +/* +EchoCancellerCalibrationFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.Core; +import org.linphone.core.CoreListenerStub; +import org.linphone.core.EcCalibratorStatus; +import org.linphone.core.XmlRpcArgType; +import org.linphone.core.XmlRpcRequest; +import org.linphone.core.XmlRpcRequestListener; +import org.linphone.core.XmlRpcSession; +import org.linphone.core.tools.Log; +import org.linphone.settings.LinphonePreferences; + +public class EchoCancellerCalibrationFragment extends Fragment implements XmlRpcRequestListener { + private final Handler mHandler = new Handler(); + private boolean mSendEcCalibrationResult = false; + private CoreListenerStub mListener; + private XmlRpcSession mXmlRpcSession; + private XmlRpcRequest mXmlRpcRequest; + private Runnable mRunFinished; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.assistant_ec_calibration, container, false); + + mListener = + new CoreListenerStub() { + @Override + public void onEcCalibrationResult( + Core lc, EcCalibratorStatus status, int delay_ms) { + lc.removeListener(mListener); + LinphoneManager.getInstance().routeAudioToReceiver(); + if (mSendEcCalibrationResult) { + sendEcCalibrationResult(status, delay_ms); + } else { + AssistantActivity.instance().isEchoCalibrationFinished(); + } + } + }; + mRunFinished = + new Runnable() { + public void run() { + AssistantActivity.instance().isEchoCalibrationFinished(); + } + }; + + mXmlRpcSession = + LinphoneManager.getLcIfManagerNotDestroyedOrNull() + .createXmlRpcSession(LinphonePreferences.instance().getXmlrpcUrl()); + mXmlRpcRequest = + mXmlRpcSession.createRequest(XmlRpcArgType.None, "add_ec_calibration_result"); + mXmlRpcRequest.setListener(this); + + LinphoneManager.getLc().addListener(mListener); + LinphoneManager.getInstance().startEcCalibration(); + return view; + } + + public void enableEcCalibrationResultSending(boolean enabled) { + mSendEcCalibrationResult = enabled; + } + + @Override + public void onResponse(XmlRpcRequest request) { + mHandler.post(mRunFinished); + } + + private void sendEcCalibrationResult(EcCalibratorStatus status, int delayMs) { + 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); + mXmlRpcRequest.addStringArg(Build.MANUFACTURER); + mXmlRpcRequest.addStringArg(Build.MODEL); + mXmlRpcRequest.addStringArg(status.toString()); + mXmlRpcRequest.addIntArg(delayMs); + mXmlRpcRequest.addIntArg(hasBuiltInEchoCanceler ? 1 : 0); + mXmlRpcSession.sendRequest(mXmlRpcRequest); + } +} diff --git a/app/src/main/java/org/linphone/assistant/EmailAccountCreationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/EmailAccountCreationAssistantActivity.java deleted file mode 100644 index c0f856742..000000000 --- a/app/src/main/java/org/linphone/assistant/EmailAccountCreationAssistantActivity.java +++ /dev/null @@ -1,270 +0,0 @@ -package org.linphone.assistant; - -/* -EmailAccountCreationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.content.Intent; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Patterns; -import android.view.View; -import android.widget.EditText; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; -import org.linphone.core.tools.Log; - -public class EmailAccountCreationAssistantActivity extends AssistantActivity { - private EditText mUsername, mPassword, mPasswordConfirm, mEmail; - private TextView mCreate, mUsernameError, mPasswordError, mPasswordConfirmError, mEmailError; - - private AccountCreatorListenerStub mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_email_account_creation); - - mUsernameError = findViewById(R.id.username_error); - mPasswordError = findViewById(R.id.password_error); - mPasswordConfirmError = findViewById(R.id.confirm_password_error); - mEmailError = findViewById(R.id.email_error); - - mUsername = findViewById(R.id.assistant_username); - mUsername.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - AccountCreator.UsernameStatus status = - mAccountCreator.setUsername(s.toString()); - mUsernameError.setVisibility( - status == AccountCreator.UsernameStatus.Ok - ? View.INVISIBLE - : View.VISIBLE); - switch (status) { - case Invalid: - mUsernameError.setText(getString(R.string.username_invalid_size)); - break; - case InvalidCharacters: - mUsernameError.setText(getString(R.string.invalid_characters)); - break; - case TooLong: - mUsernameError.setText(getString(R.string.username_too_long)); - break; - case TooShort: - mUsernameError.setText(getString(R.string.username_too_short)); - break; - } - updateCreateButton(); - } - }); - - mPassword = findViewById(R.id.assistant_password); - mPassword.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - AccountCreator.PasswordStatus status = - mAccountCreator.setPassword(s.toString()); - mPasswordError.setVisibility( - status == AccountCreator.PasswordStatus.Ok - ? View.INVISIBLE - : View.VISIBLE); - - mPasswordConfirmError.setVisibility( - s.toString().equals(mPasswordConfirm.getText().toString()) - ? View.INVISIBLE - : View.VISIBLE); - - switch (status) { - case InvalidCharacters: - mPasswordError.setText(getString(R.string.invalid_characters)); - break; - case TooLong: - mPasswordError.setText(getString(R.string.password_too_long)); - break; - case TooShort: - mPasswordError.setText(getString(R.string.password_too_short)); - break; - } - updateCreateButton(); - } - }); - - mPasswordConfirm = findViewById(R.id.assistant_password_confirmation); - mPasswordConfirm.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - mPasswordConfirmError.setVisibility( - s.toString().equals(mPassword.getText().toString()) - ? View.INVISIBLE - : View.VISIBLE); - updateCreateButton(); - } - }); - - mEmail = findViewById(R.id.assistant_email); - mEmail.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - AccountCreator.EmailStatus status = mAccountCreator.setEmail(s.toString()); - mEmailError.setVisibility( - status == AccountCreator.EmailStatus.Ok - ? View.INVISIBLE - : View.VISIBLE); - updateCreateButton(); - } - }); - - mCreate = findViewById(R.id.assistant_create); - mCreate.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - enableButtonsAndFields(false); - mAccountCreator.setDomain(getString(R.string.default_domain)); - - AccountCreator.Status status = mAccountCreator.isAccountExist(); - if (status != AccountCreator.Status.RequestOk) { - enableButtonsAndFields(true); - Log.e("[Email Account Creation] isAccountExists returned " + status); - showGenericErrorDialog(status); - } - } - }); - mCreate.setEnabled(false); - - mListener = - new AccountCreatorListenerStub() { - public void onIsAccountExist( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Email Account Creation] onIsAccountExist status is " + status); - if (status.equals(AccountCreator.Status.AccountExist) - || status.equals(AccountCreator.Status.AccountExistWithAlias)) { - showAccountAlreadyExistsDialog(); - enableButtonsAndFields(true); - } else if (status.equals(AccountCreator.Status.AccountNotExist)) { - status = mAccountCreator.createAccount(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Email Account Creation] createAccount returned " + status); - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } else { - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - - @Override - public void onCreateAccount( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Email Account Creation] onCreateAccount status is " + status); - if (status.equals(AccountCreator.Status.AccountCreated)) { - startActivity( - new Intent( - EmailAccountCreationAssistantActivity.this, - EmailAccountValidationAssistantActivity.class)); - } else { - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - }; - } - - private void enableButtonsAndFields(boolean enable) { - mUsername.setEnabled(enable); - mPassword.setEnabled(enable); - mPasswordConfirm.setEnabled(enable); - mEmail.setEnabled(enable); - mCreate.setEnabled(enable); - } - - private void updateCreateButton() { - mCreate.setEnabled( - mUsername.getText().length() > 0 - && mPassword.getText().toString().length() > 0 - && mEmail.getText().toString().length() > 0 - && mEmailError.getVisibility() == View.INVISIBLE - && mUsernameError.getVisibility() == View.INVISIBLE - && mPasswordError.getVisibility() == View.INVISIBLE - && mPasswordConfirmError.getVisibility() == View.INVISIBLE); - } - - @Override - protected void onResume() { - super.onResume(); - - mAccountCreator.addListener(mListener); - - if (getResources().getBoolean(R.bool.pre_fill_email_in_assistant)) { - Account[] accounts = AccountManager.get(this).getAccountsByType("com.google"); - for (Account account : accounts) { - if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { - String possibleEmail = account.name; - mEmail.setText(possibleEmail); - break; - } - } - } - } - - @Override - protected void onPause() { - super.onPause(); - mAccountCreator.removeListener(mListener); - } -} diff --git a/app/src/main/java/org/linphone/assistant/EmailAccountValidationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/EmailAccountValidationAssistantActivity.java deleted file mode 100644 index 4d7bb92aa..000000000 --- a/app/src/main/java/org/linphone/assistant/EmailAccountValidationAssistantActivity.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.linphone.assistant; - -/* -PhoneAccountValidationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.os.Bundle; -import android.view.View; -import android.widget.TextView; -import android.widget.Toast; -import androidx.annotation.Nullable; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; -import org.linphone.core.tools.Log; - -public class EmailAccountValidationAssistantActivity extends AssistantActivity { - private TextView mEmail, mFinishCreation; - - private AccountCreatorListenerStub mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_email_account_validation); - - mEmail = findViewById(R.id.send_email); - mEmail.setText(mAccountCreator.getEmail()); - - mFinishCreation = findViewById(R.id.assistant_check); - mFinishCreation.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - mFinishCreation.setEnabled(false); - - AccountCreator.Status status = mAccountCreator.isAccountActivated(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Email Account Validation] activateAccount returned " + status); - mFinishCreation.setEnabled(true); - showGenericErrorDialog(status); - } - } - }); - - mListener = - new AccountCreatorListenerStub() { - @Override - public void onIsAccountActivated( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i( - "[Email Account Validation] onIsAccountActivated status is " - + status); - if (status.equals(AccountCreator.Status.AccountActivated)) { - createProxyConfigAndLeaveAssistant(); - } else if (status.equals(AccountCreator.Status.AccountNotActivated)) { - Toast.makeText( - EmailAccountValidationAssistantActivity.this, - getString(R.string.assistant_account_not_validated), - Toast.LENGTH_LONG) - .show(); - mFinishCreation.setEnabled(true); - } else { - showGenericErrorDialog(status); - mFinishCreation.setEnabled(true); - } - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - mAccountCreator.addListener(mListener); - - // Prevent user to go back, it won't be able to come back here after... - mBack.setEnabled(false); - } - - @Override - protected void onPause() { - super.onPause(); - mAccountCreator.removeListener(mListener); - } -} diff --git a/app/src/main/java/org/linphone/assistant/GenericConnectionAssistantActivity.java b/app/src/main/java/org/linphone/assistant/GenericConnectionAssistantActivity.java deleted file mode 100644 index 107e24f40..000000000 --- a/app/src/main/java/org/linphone/assistant/GenericConnectionAssistantActivity.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.linphone.assistant; - -/* -GenericConnectionAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.widget.EditText; -import android.widget.RadioGroup; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.LinphoneManager; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.TransportType; -import org.linphone.settings.LinphonePreferences; - -public class GenericConnectionAssistantActivity extends AssistantActivity implements TextWatcher { - private TextView mLogin; - private EditText mUsername, mPassword, mDomain, mDisplayName; - private RadioGroup mTransport; - - private AccountCreator mAccountCreator; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_generic_connection); - - mLogin = findViewById(R.id.assistant_login); - mLogin.setEnabled(false); - mLogin.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - configureAccount(); - } - }); - - mUsername = findViewById(R.id.assistant_username); - mUsername.addTextChangedListener(this); - mDisplayName = findViewById(R.id.assistant_display_name); - mDisplayName.addTextChangedListener(this); - mPassword = findViewById(R.id.assistant_password); - mPassword.addTextChangedListener(this); - mDomain = findViewById(R.id.assistant_domain); - mDomain.addTextChangedListener(this); - mTransport = findViewById(R.id.assistant_transports); - - mAccountCreator = - LinphoneManager.getLcIfManagerNotDestroyedOrNull() - .createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); - } - - private void configureAccount() { - mAccountCreator.setUsername(mUsername.getText().toString()); - mAccountCreator.setDomain(mDomain.getText().toString()); - mAccountCreator.setPassword(mPassword.getText().toString()); - mAccountCreator.setDisplayName(mDisplayName.getText().toString()); - // TODO: mUserId - - switch (mTransport.getCheckedRadioButtonId()) { - case R.id.transport_udp: - mAccountCreator.setTransport(TransportType.Udp); - break; - case R.id.transport_tcp: - mAccountCreator.setTransport(TransportType.Tcp); - break; - case R.id.transport_tls: - mAccountCreator.setTransport(TransportType.Tls); - break; - } - - createProxyConfigAndLeaveAssistant(); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - mLogin.setEnabled( - !mUsername.getText().toString().isEmpty() - && !mDomain.getText().toString().isEmpty()); - } - - @Override - public void afterTextChanged(Editable s) {} -} diff --git a/app/src/main/java/org/linphone/assistant/LinphoneLoginFragment.java b/app/src/main/java/org/linphone/assistant/LinphoneLoginFragment.java new file mode 100644 index 000000000..c58cd133d --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/LinphoneLoginFragment.java @@ -0,0 +1,426 @@ +package org.linphone.assistant; +/* +LinphoneLoginFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.telephony.TelephonyManager; +import android.text.Editable; +import android.text.Html; +import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import java.util.Locale; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.AccountCreator; +import org.linphone.core.AccountCreatorListener; +import org.linphone.core.DialPlan; +import org.linphone.settings.LinphonePreferences; +import org.linphone.utils.LinphoneUtils; + +public class LinphoneLoginFragment extends Fragment + implements CompoundButton.OnCheckedChangeListener, + OnClickListener, + TextWatcher, + AccountCreatorListener { + private EditText mLogin, mPassword, mPhoneNumberEdit, mDialCode; + private Button mApply, mSelectCountry; + private CheckBox mUseUsername; + private LinearLayout mPhoneNumberLayout, mUsernameLayout, mPasswordLayout; + private TextView mForgotPassword, mMessagePhoneNumber, mPhoneNumberError; + private AccountCreator mAccountCreator; + private int mCountryCode; + private String mPhone, mUsername, mPwd; + private ImageView mPhoneNumberInfo; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.assistant_linphone_login, container, false); + + mAccountCreator = + LinphoneManager.getLc() + .createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); + mAccountCreator.setListener(this); + + mLogin = view.findViewById(R.id.assistant_username); + mLogin.addTextChangedListener(this); + + mDialCode = view.findViewById(R.id.dial_code); + + mPhoneNumberEdit = view.findViewById(R.id.phone_number); + mPhoneNumberLayout = view.findViewById(R.id.phone_number_layout); + mPhoneNumberError = view.findViewById(R.id.phone_number_error_2); + + mPhoneNumberInfo = view.findViewById(R.id.info_phone_number); + + mUseUsername = view.findViewById(R.id.use_username); + mUsernameLayout = view.findViewById(R.id.username_layout); + mPasswordLayout = view.findViewById(R.id.password_layout); + mPassword = view.findViewById(R.id.assistant_password); + mMessagePhoneNumber = view.findViewById(R.id.message_phone_number); + + mForgotPassword = view.findViewById(R.id.forgot_password); + mSelectCountry = view.findViewById(R.id.select_country); + + mApply = view.findViewById(R.id.assistant_apply); + mApply.setEnabled(true); + mApply.setOnClickListener(this); + + // Phone number + if (getResources().getBoolean(R.bool.use_phone_number_validation)) { + mMessagePhoneNumber.setText(getString(R.string.assistant_create_account_part_1)); + mPhone = getArguments().getString("Phone"); + String prefix = getArguments().getString("Dialcode"); + + getActivity().getApplicationContext(); + // Automatically get the country code from the mPhone + TelephonyManager tm = + (TelephonyManager) + getActivity() + .getApplicationContext() + .getSystemService(Context.TELEPHONY_SERVICE); + String countryIso = tm.getNetworkCountryIso(); + mCountryCode = org.linphone.core.Utils.getCccFromIso(countryIso.toUpperCase()); + + DialPlan c = AssistantActivity.instance().country; + if (c != null) { + mSelectCountry.setText(c.getCountry()); + mDialCode.setText( + c.getCountryCallingCode().contains("+") + ? c.getCountryCallingCode() + : "+" + c.getCountryCallingCode()); + } else { + c = + AssistantActivity.instance() + .getCountryListAdapter() + .getCountryFromCountryCode(String.valueOf(mCountryCode)); + if (c != null) { + mSelectCountry.setText(c.getCountry()); + mDialCode.setText( + c.getCountryCallingCode().contains("+") + ? c.getCountryCallingCode() + : "+" + c.getCountryCallingCode()); + } + } + + mPhoneNumberLayout.setVisibility(View.VISIBLE); + mSelectCountry.setOnClickListener(this); + mPhoneNumberInfo.setOnClickListener(this); + + // Allow user to enter a mUsername instead use the mPhone number as mUsername + if (getResources().getBoolean(R.bool.assistant_allow_username)) { + mUseUsername.setVisibility(View.VISIBLE); + mUseUsername.setOnCheckedChangeListener(this); + } + + if (mPhone != null) mPhoneNumberEdit.setText(mPhone); + if (prefix != null) mDialCode.setText("+" + prefix); + } + + if (getResources().getBoolean(R.bool.assistant_allow_username)) { + mUseUsername.setVisibility(View.VISIBLE); + mUseUsername.setOnCheckedChangeListener(this); + mPassword.addTextChangedListener(this); + mForgotPassword.setText( + Html.fromHtml( + "" + + getString(R.string.forgot_password) + + "")); + mForgotPassword.setMovementMethod(LinkMovementMethod.getInstance()); + } + + // Hide mPhone number and display mUsername/email/mPassword + if (!getResources().getBoolean(R.bool.use_phone_number_validation)) { + mPhoneNumberLayout.setVisibility(View.GONE); + mUseUsername.setVisibility(View.GONE); + + mUsernameLayout.setVisibility(View.VISIBLE); + mPasswordLayout.setVisibility(View.VISIBLE); + } + + // When we come from generic mLogin fragment + mUsername = getArguments().getString("Username"); + mPwd = getArguments().getString("Password"); + if (mUsername != null && mPwd != null) { + mUseUsername.setChecked(true); + onCheckedChanged(mUseUsername, true); + mLogin.setText(mUsername); + mPassword.setText(mPwd); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mAccountCreator.setLanguage(Locale.getDefault().toLanguageTag()); + } + + addPhoneNumberHandler(mDialCode); + addPhoneNumberHandler(mPhoneNumberEdit); + + return view; + } + + private void linphoneLogIn() { + if (mLogin.getText() == null + || mLogin.length() == 0 + || mPassword.getText() == null + || mPassword.length() == 0) { + LinphoneUtils.displayErrorAlert( + getString(R.string.first_launch_no_login_password), + AssistantActivity.instance()); + mApply.setEnabled(true); + return; + } + mAccountCreator.setUsername(mLogin.getText().toString()); + mAccountCreator.setPassword(mPassword.getText().toString()); + mAccountCreator.setDomain(getString(R.string.default_domain)); + mAccountCreator.isAccountExist(); + } + + private int getPhoneNumberStatus() { + mAccountCreator.setDomain(getString(R.string.default_domain)); + return mAccountCreator.setPhoneNumber( + mPhoneNumberEdit.getText().toString(), LinphoneUtils.getCountryCode(mDialCode)); + } + + private void addPhoneNumberHandler(final EditText field) { + field.addTextChangedListener( + new TextWatcher() { + public void afterTextChanged(Editable s) { + if (field.equals(mDialCode)) { + DialPlan c = + AssistantActivity.instance() + .getCountryListAdapter() + .getCountryFromCountryCode( + mDialCode.getText().toString()); + if (c != null) { + AssistantActivity.instance().country = c; + mSelectCountry.setText(c.getCountry()); + } else { + mSelectCountry.setText(R.string.select_your_country); + } + } + } + + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + public void onTextChanged(CharSequence s, int start, int count, int after) { + onTextChanged2(); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.assistant_apply) { + mApply.setEnabled(false); + if (mUseUsername == null || !mUseUsername.isChecked()) { + recoverAccount(); + } else { + linphoneLogIn(); + } + } else if (id == R.id.info_phone_number) { + new AlertDialog.Builder(getActivity()) + .setTitle(getString(R.string.phone_number_info_title)) + .setMessage(getString(R.string.phone_number_link_info_content)) + .show(); + } else if (id == R.id.select_country) { + AssistantActivity.instance().displayCountryChooser(); + } + } + + private void recoverAccount() { + if (mPhoneNumberEdit.getText().length() > 0 || mDialCode.getText().length() > 1) { + int status = getPhoneNumberStatus(); + boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt(); + if (isOk) { + mAccountCreator.isAliasUsed(); + } else { + mApply.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForPhoneNumberStatus(status), + AssistantActivity.instance()); + LinphoneUtils.displayError( + isOk, mPhoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); + } + } else { + mApply.setEnabled(true); + LinphoneUtils.displayErrorAlert( + getString(R.string.assistant_create_account_part_1), + AssistantActivity.instance()); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + private void onTextChanged2() { + int status = getPhoneNumberStatus(); + boolean isOk = status == AccountCreator.PhoneNumberStatus.Ok.toInt(); + LinphoneUtils.displayError( + isOk, mPhoneNumberError, LinphoneUtils.errorForPhoneNumberStatus(status)); + if (!isOk) { + if ((1 == (status & AccountCreator.PhoneNumberStatus.InvalidCountryCode.toInt()))) { + mDialCode.setBackgroundResource(R.drawable.resizable_textfield_error); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); + } else { + mDialCode.setBackgroundResource(R.drawable.resizable_textfield); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield_error); + } + } else { + mAccountCreator.setPhoneNumber( + mPhoneNumberEdit.getText().toString(), mDialCode.getText().toString()); + mDialCode.setBackgroundResource(R.drawable.resizable_textfield); + mPhoneNumberEdit.setBackgroundResource(R.drawable.resizable_textfield); + } + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + onTextChanged2(); + } + + @Override + public void afterTextChanged(Editable s) {} + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (buttonView.getId() == R.id.use_username) { + if (isChecked) { + mUsernameLayout.setVisibility(View.VISIBLE); + mPasswordLayout.setVisibility(View.VISIBLE); + mPhoneNumberEdit.setVisibility(EditText.GONE); + mPhoneNumberLayout.setVisibility(LinearLayout.GONE); + mMessagePhoneNumber.setText(getString(R.string.assistant_linphone_login_desc)); + } else { + mUsernameLayout.setVisibility(View.GONE); + mPasswordLayout.setVisibility(View.GONE); + mPhoneNumberEdit.setVisibility(EditText.VISIBLE); + mPhoneNumberLayout.setVisibility(LinearLayout.VISIBLE); + mMessagePhoneNumber.setText(getString(R.string.assistant_create_account_part_1)); + } + } + } + + @Override + public void onIsAccountExist( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (AssistantActivity.instance() == null) { + mApply.setEnabled(true); + return; + } + if (status.equals(AccountCreator.Status.AccountExist) + || status.equals(AccountCreator.Status.AccountExistWithAlias)) { + AssistantActivity.instance().linphoneLogIn(accountCreator); + } else { + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); + } + mApply.setEnabled(true); + } + + @Override + public void onCreateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onLinkAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onActivateAlias( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAccountActivated( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onRecoverAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (AssistantActivity.instance() == null) { + mApply.setEnabled(true); + return; + } + if (status.equals(AccountCreator.Status.ServerError)) { + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(AccountCreator.Status.RequestFailed), + AssistantActivity.instance()); + mApply.setEnabled(true); + } else { + AssistantActivity.instance() + .displayAssistantCodeConfirm( + accountCreator.getUsername(), + mPhoneNumberEdit.getText().toString(), + LinphoneUtils.getCountryCode(mDialCode), + true); + } + } + + @Override + public void onIsAccountLinked( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} + + @Override + public void onIsAliasUsed( + AccountCreator accountCreator, AccountCreator.Status status, String resp) { + if (AssistantActivity.instance() == null) { + mApply.setEnabled(true); + return; + } + if (status.equals(AccountCreator.Status.AliasIsAccount) + || status.equals(AccountCreator.Status.AliasExist)) { + accountCreator.recoverAccount(); + } else { + mApply.setEnabled(true); + LinphoneUtils.displayErrorAlert( + LinphoneUtils.errorForStatus(status), AssistantActivity.instance()); + } + } + + @Override + public void onUpdateAccount( + AccountCreator accountCreator, AccountCreator.Status status, String resp) {} +} diff --git a/app/src/main/java/org/linphone/assistant/LoginFragment.java b/app/src/main/java/org/linphone/assistant/LoginFragment.java new file mode 100644 index 000000000..e8465685e --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/LoginFragment.java @@ -0,0 +1,125 @@ +package org.linphone.assistant; +/* +LoginFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioGroup; +import android.widget.Toast; +import org.linphone.R; +import org.linphone.core.TransportType; + +public class LoginFragment extends Fragment implements OnClickListener, TextWatcher { + private EditText mLogin, mUserid, mPassword, mDomain, mDisplayName; + private RadioGroup mTransports; + private Button mApply; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.assistant_login, container, false); + + mLogin = view.findViewById(R.id.assistant_username); + mLogin.addTextChangedListener(this); + mDisplayName = view.findViewById(R.id.assistant_display_name); + mDisplayName.addTextChangedListener(this); + mUserid = view.findViewById(R.id.assistant_userid); + mUserid.addTextChangedListener(this); + mPassword = view.findViewById(R.id.assistant_password); + mPassword.addTextChangedListener(this); + mDomain = view.findViewById(R.id.assistant_domain); + mDomain.addTextChangedListener(this); + mTransports = view.findViewById(R.id.assistant_transports); + mApply = view.findViewById(R.id.assistant_apply); + mApply.setEnabled(false); + mApply.setOnClickListener(this); + + return view; + } + + @Override + public void onClick(View v) { + int id = v.getId(); + + if (id == R.id.assistant_apply) { + if (mLogin.getText() == null + || mLogin.length() == 0 + || mPassword.getText() == null + || mPassword.length() == 0 + || mDomain.getText() == null + || mDomain.length() == 0) { + Toast.makeText( + getActivity(), + getString(R.string.first_launch_no_login_password), + Toast.LENGTH_LONG) + .show(); + return; + } + + TransportType transport; + if (mTransports.getCheckedRadioButtonId() == R.id.transport_udp) { + transport = TransportType.Udp; + } else { + if (mTransports.getCheckedRadioButtonId() == R.id.transport_tcp) { + transport = TransportType.Tcp; + } else { + transport = TransportType.Tls; + } + } + + if (mDomain.getText().toString().compareTo(getString(R.string.default_domain)) == 0) { + AssistantActivity.instance() + .displayLoginLinphone( + mLogin.getText().toString(), mPassword.getText().toString()); + } else { + AssistantActivity.instance() + .genericLogIn( + mLogin.getText().toString(), + mUserid.getText().toString(), + mPassword.getText().toString(), + mDisplayName.getText().toString(), + null, + mDomain.getText().toString(), + transport); + } + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mApply.setEnabled( + !mLogin.getText().toString().isEmpty() + && !mPassword.getText().toString().isEmpty() + && !mDomain.getText().toString().isEmpty()); + } + + @Override + public void afterTextChanged(Editable s) {} +} diff --git a/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java b/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java deleted file mode 100644 index c9ab0d7fe..000000000 --- a/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.linphone.assistant; - -/* -MenuAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.Intent; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.R; -import org.linphone.core.tools.Log; -import org.linphone.settings.LinphonePreferences; - -public class MenuAssistantActivity extends AssistantActivity { - private TextView mAccountCreation, mAccountConnection, mGenericConnection, mRemoteConfiguration; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_menu); - - Log.e("###"); - - mAccountCreation = findViewById(R.id.account_creation); - mAccountCreation.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent; - if (getResources().getBoolean(R.bool.isTablet) - || !getResources().getBoolean(R.bool.use_phone_number_validation)) { - intent = - new Intent( - MenuAssistantActivity.this, - EmailAccountCreationAssistantActivity.class); - } else { - intent = - new Intent( - MenuAssistantActivity.this, - PhoneAccountCreationAssistantActivity.class); - } - startActivity(intent); - } - }); - - mAccountConnection = findViewById(R.id.account_connection); - mAccountConnection.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - startActivity( - new Intent( - MenuAssistantActivity.this, - AccountConnectionAssistantActivity.class)); - } - }); - if (getResources().getBoolean(R.bool.hide_linphone_accounts_in_assistant)) { - mAccountConnection.setVisibility(View.GONE); - } - - mGenericConnection = findViewById(R.id.generic_connection); - mGenericConnection.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - startActivity( - new Intent( - MenuAssistantActivity.this, - GenericConnectionAssistantActivity.class)); - } - }); - if (getResources().getBoolean(R.bool.hide_generic_accounts_in_assistant)) { - mGenericConnection.setVisibility(View.GONE); - } - - mRemoteConfiguration = findViewById(R.id.remote_configuration); - mRemoteConfiguration.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - startActivity( - new Intent( - MenuAssistantActivity.this, - RemoteConfigurationAssistantActivity.class)); - } - }); - if (getResources().getBoolean(R.bool.hide_remote_provisioning_in_assistant)) { - mRemoteConfiguration.setVisibility(View.GONE); - } - - if (getResources().getBoolean(R.bool.assistant_use_linphone_login_as_first_fragment)) { - startActivity( - new Intent( - MenuAssistantActivity.this, AccountConnectionAssistantActivity.class)); - finish(); - } else if (getResources() - .getBoolean(R.bool.assistant_use_generic_login_as_first_fragment)) { - startActivity( - new Intent( - MenuAssistantActivity.this, GenericConnectionAssistantActivity.class)); - finish(); - } else if (getResources() - .getBoolean(R.bool.assistant_use_create_linphone_account_as_first_fragment)) { - startActivity( - new Intent( - MenuAssistantActivity.this, - PhoneAccountCreationAssistantActivity.class)); - finish(); - } - } - - @Override - protected void onResume() { - super.onResume(); - if (!getResources() - .getBoolean(R.bool.forbid_to_leave_assistant_before_account_configuration)) { - mBack.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - LinphonePreferences.instance().firstLaunchSuccessful(); - goToLinphoneActivity(); - } - }); - } else { - mBack.setEnabled(false); - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - if (getResources() - .getBoolean(R.bool.forbid_to_leave_assistant_before_account_configuration)) { - // Do nothing - return true; - } else { - LinphonePreferences.instance().firstLaunchSuccessful(); - goToLinphoneActivity(); - return true; - } - } - return super.onKeyDown(keyCode, event); - } -} diff --git a/app/src/main/java/org/linphone/assistant/OpenH264DownloadAssistantActivity.java b/app/src/main/java/org/linphone/assistant/OpenH264DownloadAssistantActivity.java deleted file mode 100644 index 316a1da30..000000000 --- a/app/src/main/java/org/linphone/assistant/OpenH264DownloadAssistantActivity.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.linphone.assistant; - -/* -OpenH264DownloadAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.os.Bundle; -import android.view.View; -import android.widget.ProgressBar; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.LinphoneManager; -import org.linphone.R; -import org.linphone.core.Core; -import org.linphone.core.PayloadType; -import org.linphone.core.tools.Log; -import org.linphone.core.tools.OpenH264DownloadHelper; -import org.linphone.core.tools.OpenH264DownloadHelperListener; -import org.linphone.settings.LinphonePreferences; - -public class OpenH264DownloadAssistantActivity extends AssistantActivity { - private TextView mYes, mNo; - private ProgressBar mProgress; - - private OpenH264DownloadHelper mHelper; - private OpenH264DownloadHelperListener mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_openh264_codec_download); - mHelper = LinphoneManager.getInstance().getOpenH264DownloadHelper(); - LinphonePreferences.instance().setOpenH264CodecDownloadEnabled(false); - - mProgress = findViewById(R.id.progress_bar); - - mYes = findViewById(R.id.answer_yes); - mYes.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - mYes.setEnabled(false); - mNo.setEnabled(false); - Log.e("[OpenH264 Downloader] Start download"); - mProgress.setVisibility(View.VISIBLE); - mHelper.downloadCodec(); - } - }); - - mNo = findViewById(R.id.answer_no); - mNo.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - mYes.setEnabled(false); - mNo.setEnabled(false); - Log.e("[OpenH264 Downloader] Download refused"); - goToLinphoneActivity(); - } - }); - - mListener = - new OpenH264DownloadHelperListener() { - @Override - public void OnProgress(int current, int max) { - if (current < max) { - mProgress.setMax(max); - mProgress.setProgress(current); - } else { - Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); - if (core != null) { - core.reloadMsPlugins(getApplicationInfo().nativeLibraryDir); - enableH264(); - } - - goToLinphoneActivity(); - } - } - - @Override - public void OnError(String s) { - Log.e("[OpenH264 Downloader] " + s); - mYes.setEnabled(true); - mNo.setEnabled(true); - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - mHelper.setOpenH264HelperListener(mListener); - } - - @Override - protected void onPause() { - mHelper.setOpenH264HelperListener(null); - super.onPause(); - } - - private void enableH264() { - for (PayloadType pt : LinphoneManager.getLc().getVideoPayloadTypes()) { - if (pt.getMimeType().equals("H264")) { - pt.enable(true); - break; - } - } - } -} diff --git a/app/src/main/java/org/linphone/assistant/PhoneAccountCreationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/PhoneAccountCreationAssistantActivity.java deleted file mode 100644 index d5f5a9886..000000000 --- a/app/src/main/java/org/linphone/assistant/PhoneAccountCreationAssistantActivity.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.linphone.assistant; - -/* -PhoneAccountCreationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.Intent; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; -import org.linphone.core.DialPlan; -import org.linphone.core.tools.Log; - -public class PhoneAccountCreationAssistantActivity extends AssistantActivity { - private TextView mCountryPicker, mError, mSipUri, mCreate; - private EditText mPrefix, mPhoneNumber; - private ImageView mPhoneNumberInfos; - - private AccountCreatorListenerStub mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_phone_account_creation); - - mCountryPicker = findViewById(R.id.select_country); - mCountryPicker.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - showCountryPickerDialog(); - } - }); - - mError = findViewById(R.id.phone_number_error); - - mSipUri = findViewById(R.id.sip_uri); - - mCreate = findViewById(R.id.assistant_create); - mCreate.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - enableButtonsAndFields(false); - - mAccountCreator.setUsername(mAccountCreator.getPhoneNumber()); - mAccountCreator.setDomain(getString(R.string.default_domain)); - - AccountCreator.Status status = mAccountCreator.isAccountExist(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Phone Account Creation] isAccountExists returned " + status); - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - }); - mCreate.setEnabled(false); - - mPrefix = findViewById(R.id.dial_code); - mPrefix.setText("+"); - mPrefix.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - String prefix = s.toString(); - if (prefix.startsWith("+")) { - prefix = prefix.substring(1); - } - DialPlan dp = getDialPlanFromPrefix(prefix); - if (dp != null) { - mCountryPicker.setText(dp.getCountry()); - } - - updateCreateButtonAndDisplayError(); - } - }); - - mPhoneNumber = findViewById(R.id.phone_number); - mPhoneNumber.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - updateCreateButtonAndDisplayError(); - } - }); - - mPhoneNumberInfos = findViewById(R.id.info_phone_number); - mPhoneNumberInfos.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - showPhoneNumberDialog(); - } - }); - - mListener = - new AccountCreatorListenerStub() { - public void onIsAccountExist( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Phone Account Creation] onIsAccountExist status is " + status); - if (status.equals(AccountCreator.Status.AccountExist) - || status.equals(AccountCreator.Status.AccountExistWithAlias)) { - showAccountAlreadyExistsDialog(); - enableButtonsAndFields(true); - } else if (status.equals(AccountCreator.Status.AccountNotExist)) { - status = mAccountCreator.createAccount(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Phone Account Creation] createAccount returned " + status); - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } else { - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - - @Override - public void onCreateAccount( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Phone Account Creation] onCreateAccount status is " + status); - if (status.equals(AccountCreator.Status.AccountCreated)) { - startActivity( - new Intent( - PhoneAccountCreationAssistantActivity.this, - PhoneAccountValidationAssistantActivity.class)); - } else { - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - - mAccountCreator.addListener(mListener); - - DialPlan dp = getDialPlanForCurrentCountry(); - displayDialPlan(dp); - - String phoneNumber = getDevicePhoneNumber(); - if (phoneNumber != null) { - mPhoneNumber.setText(phoneNumber); - } - } - - @Override - protected void onPause() { - super.onPause(); - mAccountCreator.removeListener(mListener); - } - - @Override - public void onCountryClicked(DialPlan dialPlan) { - super.onCountryClicked(dialPlan); - displayDialPlan(dialPlan); - } - - private void enableButtonsAndFields(boolean enable) { - mPrefix.setEnabled(enable); - mPhoneNumber.setEnabled(enable); - mCreate.setEnabled(enable); - } - - private void updateCreateButtonAndDisplayError() { - if (mPrefix.getText().toString().isEmpty() || mPhoneNumber.getText().toString().isEmpty()) - return; - - int status = arePhoneNumberAndPrefixOk(mPrefix, mPhoneNumber); - if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) { - mCreate.setEnabled(true); - mError.setText(""); - mError.setVisibility(View.INVISIBLE); - } else { - mCreate.setEnabled(false); - mError.setText(getErrorFromPhoneNumberStatus(status)); - mError.setVisibility(View.VISIBLE); - } - - String username = mAccountCreator.getPhoneNumber(); - if (username != null) { - String sip = - getString(R.string.assistant_create_account_phone_number_address) - + " "; - mSipUri.setText(sip); - } - } - - private void displayDialPlan(DialPlan dp) { - if (dp != null) { - mPrefix.setText("+" + dp.getCountryCallingCode()); - mCountryPicker.setText(dp.getCountry()); - } - } -} diff --git a/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java b/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java deleted file mode 100644 index f812e923a..000000000 --- a/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java +++ /dev/null @@ -1,275 +0,0 @@ -package org.linphone.assistant; - -/* -PhoneAccountLinkingAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.Intent; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; -import androidx.annotation.Nullable; -import org.linphone.LinphoneManager; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; -import org.linphone.core.Address; -import org.linphone.core.AuthInfo; -import org.linphone.core.Core; -import org.linphone.core.DialPlan; -import org.linphone.core.ProxyConfig; -import org.linphone.core.tools.Log; - -public class PhoneAccountLinkingAssistantActivity extends AssistantActivity { - private TextView mCountryPicker, mError, mLink; - private EditText mPrefix, mPhoneNumber; - private ImageView mPhoneNumberInfos; - - private AccountCreatorListenerStub mListener; - private ProxyConfig mProxyConfig; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_phone_account_linking); - - if (getIntent() != null && getIntent().hasExtra("AccountNumber")) { - int proxyConfigIndex = getIntent().getExtras().getInt("AccountNumber"); - Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); - if (core == null) { - Log.e("[Account Linking] Core not available"); - unexpectedError(); - } - - ProxyConfig[] proxyConfigs = core.getProxyConfigList(); - if (proxyConfigIndex >= 0 && proxyConfigIndex < proxyConfigs.length) { - mProxyConfig = proxyConfigs[proxyConfigIndex]; - - Address identity = mProxyConfig.getIdentityAddress(); - if (identity == null) { - Log.e("[Account Linking] Proxy doesn't have an identity address"); - unexpectedError(); - } - mAccountCreator.setUsername(identity.getUsername()); - - AuthInfo authInfo = mProxyConfig.findAuthInfo(); - if (authInfo == null) { - Log.e("[Account Linking] Auth info not found"); - unexpectedError(); - } - mAccountCreator.setHa1(authInfo.getHa1()); - - mAccountCreator.setDomain(getString(R.string.default_domain)); - } else { - Log.e("[Account Linking] Proxy config index out of bounds: " + proxyConfigIndex); - unexpectedError(); - } - } else { - Log.e("[Account Linking] Proxy config index not found"); - unexpectedError(); - } - - mCountryPicker = findViewById(R.id.select_country); - mCountryPicker.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - showCountryPickerDialog(); - } - }); - - mError = findViewById(R.id.phone_number_error); - - mLink = findViewById(R.id.assistant_link); - mLink.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - enableButtonsAndFields(false); - - AccountCreator.Status status = mAccountCreator.isAliasUsed(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Phone Account Linking] isAliasUsed returned " + status); - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - }); - mLink.setEnabled(false); - - mPrefix = findViewById(R.id.dial_code); - mPrefix.setText("+"); - mPrefix.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - String prefix = s.toString(); - if (prefix.startsWith("+")) { - prefix = prefix.substring(1); - } - DialPlan dp = getDialPlanFromPrefix(prefix); - if (dp != null) { - mCountryPicker.setText(dp.getCountry()); - } - - updateCreateButtonAndDisplayError(); - } - }); - - mPhoneNumber = findViewById(R.id.phone_number); - mPhoneNumber.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - updateCreateButtonAndDisplayError(); - } - }); - - mPhoneNumberInfos = findViewById(R.id.info_phone_number); - mPhoneNumberInfos.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - showPhoneNumberDialog(); - } - }); - - mListener = - new AccountCreatorListenerStub() { - @Override - public void onIsAliasUsed( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Phone Account Linking] onIsAliasUsed status is " + status); - if (status.equals(AccountCreator.Status.AliasNotExist)) { - status = mAccountCreator.linkAccount(); - if (status != AccountCreator.Status.RequestOk) { - Log.e("[Phone Account Linking] linkAccount returned " + status); - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } else { - if (status.equals(AccountCreator.Status.AliasIsAccount) - || status.equals(AccountCreator.Status.AliasExist)) { - showAccountAlreadyExistsDialog(); - } else { - showGenericErrorDialog(status); - } - enableButtonsAndFields(true); - } - } - - @Override - public void onLinkAccount( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Phone Account Linking] onLinkAccount status is " + status); - if (status.equals(AccountCreator.Status.RequestOk)) { - Intent intent = - new Intent( - PhoneAccountLinkingAssistantActivity.this, - PhoneAccountValidationAssistantActivity.class); - intent.putExtra("isLinkingVerification", true); - startActivity(intent); - } else { - enableButtonsAndFields(true); - showGenericErrorDialog(status); - } - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - - mAccountCreator.addListener(mListener); - - DialPlan dp = getDialPlanForCurrentCountry(); - displayDialPlan(dp); - - String phoneNumber = getDevicePhoneNumber(); - if (phoneNumber != null) { - mPhoneNumber.setText(phoneNumber); - } - } - - @Override - protected void onPause() { - super.onPause(); - mAccountCreator.removeListener(mListener); - } - - @Override - public void onCountryClicked(DialPlan dialPlan) { - super.onCountryClicked(dialPlan); - displayDialPlan(dialPlan); - } - - private void enableButtonsAndFields(boolean enable) { - mPrefix.setEnabled(enable); - mPhoneNumber.setEnabled(enable); - mLink.setEnabled(enable); - } - - private void updateCreateButtonAndDisplayError() { - if (mPrefix.getText().toString().isEmpty() || mPhoneNumber.getText().toString().isEmpty()) - return; - - int status = arePhoneNumberAndPrefixOk(mPrefix, mPhoneNumber); - if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) { - mLink.setEnabled(true); - mError.setText(""); - mError.setVisibility(View.INVISIBLE); - } else { - mLink.setEnabled(false); - mError.setText(getErrorFromPhoneNumberStatus(status)); - mError.setVisibility(View.VISIBLE); - } - } - - private void displayDialPlan(DialPlan dp) { - if (dp != null) { - mPrefix.setText("+" + dp.getCountryCallingCode()); - mCountryPicker.setText(dp.getCountry()); - } - } - - private void unexpectedError() { - Toast.makeText(this, R.string.error_unknown, Toast.LENGTH_SHORT).show(); - finish(); - } -} diff --git a/app/src/main/java/org/linphone/assistant/PhoneAccountValidationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/PhoneAccountValidationAssistantActivity.java deleted file mode 100644 index 1af31cc27..000000000 --- a/app/src/main/java/org/linphone/assistant/PhoneAccountValidationAssistantActivity.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.linphone.assistant; - -/* -PhoneAccountValidationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.widget.EditText; -import android.widget.TextView; -import androidx.annotation.Nullable; -import org.linphone.R; -import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; -import org.linphone.core.tools.Log; -import org.linphone.settings.LinphonePreferences; - -public class PhoneAccountValidationAssistantActivity extends AssistantActivity { - private TextView mPhoneNumber, mFinishCreation; - private EditText mSmsCode; - private ClipboardManager mClipboard; - - private int mActivationCodeLength; - private boolean mIsLogin, mIsLinking; - private AccountCreatorListenerStub mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_phone_account_validation); - - mIsLogin = mIsLinking = false; - if (getIntent() != null && getIntent().getBooleanExtra("isLoginVerification", false)) { - findViewById(R.id.title_account_creation).setVisibility(View.VISIBLE); - mIsLogin = true; - } else if (getIntent() != null - && getIntent().getBooleanExtra("isLinkingVerification", false)) { - mIsLinking = true; - findViewById(R.id.title_account_linking).setVisibility(View.VISIBLE); - } else { - findViewById(R.id.title_account_activation).setVisibility(View.VISIBLE); - } - - mActivationCodeLength = - getResources().getInteger(R.integer.phone_number_validation_code_length); - - mPhoneNumber = findViewById(R.id.phone_number); - mPhoneNumber.setText(mAccountCreator.getPhoneNumber()); - - mSmsCode = findViewById(R.id.sms_code); - mSmsCode.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - mFinishCreation.setEnabled(s.length() == mActivationCodeLength); - } - }); - - mFinishCreation = findViewById(R.id.finish_account_creation); - mFinishCreation.setEnabled(false); - mFinishCreation.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - mFinishCreation.setEnabled(false); - mAccountCreator.setActivationCode(mSmsCode.getText().toString()); - - AccountCreator.Status status; - if (mIsLinking) { - status = mAccountCreator.activateAlias(); - } else { - status = mAccountCreator.activateAccount(); - } - if (status != AccountCreator.Status.RequestOk) { - Log.e( - "[Phone Account Validation] " - + (mIsLinking - ? "linkAccount" - : "activateAccount" + " returned ") - + status); - mFinishCreation.setEnabled(true); - showGenericErrorDialog(status); - } - } - }); - - mListener = - new AccountCreatorListenerStub() { - @Override - public void onActivateAccount( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Phone Account Validation] onActivateAccount status is " + status); - if (status.equals(AccountCreator.Status.AccountActivated)) { - createProxyConfigAndLeaveAssistant(); - } else { - mFinishCreation.setEnabled(true); - showGenericErrorDialog(status); - - if (status.equals(AccountCreator.Status.WrongActivationCode)) { - // TODO - } - } - } - - @Override - public void onActivateAlias( - AccountCreator creator, AccountCreator.Status status, String resp) { - Log.i("[Phone Account Validation] onActivateAlias status is " + status); - if (status.equals(AccountCreator.Status.AccountActivated)) { - LinphonePreferences.instance().setLinkPopupTime(""); - goToLinphoneActivity(); - } else { - mFinishCreation.setEnabled(true); - showGenericErrorDialog(status); - - if (status.equals(AccountCreator.Status.WrongActivationCode)) { - // TODO - } - } - } - }; - - mClipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - mClipboard.addPrimaryClipChangedListener( - new ClipboardManager.OnPrimaryClipChangedListener() { - @Override - public void onPrimaryClipChanged() { - ClipData data = mClipboard.getPrimaryClip(); - if (data != null && data.getItemCount() > 0) { - String clip = data.getItemAt(0).getText().toString(); - if (clip.length() == mActivationCodeLength) { - mSmsCode.setText(clip); - } - } - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - mAccountCreator.addListener(mListener); - - // Prevent user to go back, it won't be able to come back here after... - mBack.setEnabled(false); - } - - @Override - protected void onPause() { - super.onPause(); - mAccountCreator.removeListener(mListener); - } -} diff --git a/app/src/main/java/org/linphone/assistant/QrCodeConfigurationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/QrCodeFragment.java similarity index 77% rename from app/src/main/java/org/linphone/assistant/QrCodeConfigurationAssistantActivity.java rename to app/src/main/java/org/linphone/assistant/QrCodeFragment.java index 6bbee59d2..95a06104a 100644 --- a/app/src/main/java/org/linphone/assistant/QrCodeConfigurationAssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/QrCodeFragment.java @@ -1,8 +1,8 @@ package org.linphone.assistant; /* -QrCodeConfigurationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France +QrCodeFragment.java +Copyright (C) 2018 Belledonne Communications, Grenoble, France This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,46 +19,46 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import android.app.Activity; -import android.content.Intent; +import android.app.Fragment; import android.os.Bundle; +import android.view.LayoutInflater; import android.view.TextureView; -import androidx.annotation.Nullable; +import android.view.View; +import android.view.ViewGroup; import org.linphone.LinphoneManager; import org.linphone.R; import org.linphone.core.Core; import org.linphone.core.CoreListenerStub; import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; -public class QrCodeConfigurationAssistantActivity extends AssistantActivity { +public class QrCodeFragment extends Fragment { private TextureView mQrcodeView; - private CoreListenerStub mListener; @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.qrcode, container, false); - setContentView(R.layout.assistant_qr_code_remote_configuration); + mQrcodeView = view.findViewById(R.id.qrcodeCaptureSurface); - mQrcodeView = findViewById(R.id.qr_code_capture_texture); + LinphoneManager.getLc().setNativePreviewWindowId(mQrcodeView); mListener = new CoreListenerStub() { @Override public void onQrcodeFound(Core lc, String result) { - Intent resultIntent = new Intent(); - resultIntent.putExtra("URL", result); - setResult(Activity.RESULT_OK, resultIntent); - finish(); + enableQrcodeReader(false); + AssistantActivity.instance().displayRemoteProvisioning(result); } }; + + return view; } private void enableQrcodeReader(boolean enable) { LinphoneManager.getLc().enableQrcodeVideoPreview(enable); LinphoneManager.getLc().enableVideoPreview(enable); - if (enable) { LinphoneManager.getLc().addListener(mListener); } else { @@ -79,7 +79,6 @@ public class QrCodeConfigurationAssistantActivity extends AssistantActivity { } private void launchQrcodeReader() { - LinphoneManager.getLc().setNativePreviewWindowId(mQrcodeView); setBackCamera(); enableQrcodeReader(true); @@ -87,13 +86,14 @@ public class QrCodeConfigurationAssistantActivity extends AssistantActivity { @Override public void onResume() { - super.onResume(); launchQrcodeReader(); + super.onResume(); } @Override public void onPause() { enableQrcodeReader(false); + // setBackCamera(false); super.onPause(); } } diff --git a/app/src/main/java/org/linphone/assistant/RemoteConfigurationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/RemoteConfigurationAssistantActivity.java deleted file mode 100644 index a5b3999bb..000000000 --- a/app/src/main/java/org/linphone/assistant/RemoteConfigurationAssistantActivity.java +++ /dev/null @@ -1,203 +0,0 @@ -package org.linphone.assistant; - -/* -RemoteConfigurationAssistantActivity.java -Copyright (C) 2019 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import android.Manifest; -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Patterns; -import android.view.View; -import android.widget.EditText; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; -import androidx.annotation.Nullable; -import androidx.core.app.ActivityCompat; -import org.linphone.LinphoneManager; -import org.linphone.R; -import org.linphone.core.ConfiguringState; -import org.linphone.core.Core; -import org.linphone.core.CoreListenerStub; -import org.linphone.core.tools.Log; -import org.linphone.settings.LinphonePreferences; - -public class RemoteConfigurationAssistantActivity extends AssistantActivity { - private static final int QR_CODE_ACTIVITY_RESULT = 1; - private static final int CAMERA_PERMISSION_RESULT = 2; - - private TextView mFetchAndApply, mQrCode; - private EditText mRemoteConfigurationUrl; - private RelativeLayout mWaitLayout; - - private CoreListenerStub mListener; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.assistant_remote_configuration); - - mWaitLayout = findViewById(R.id.waitScreen); - mWaitLayout.setVisibility(View.GONE); - - mFetchAndApply = findViewById(R.id.fetch_and_apply_remote_configuration); - mFetchAndApply.setEnabled(false); - mFetchAndApply.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - String url = mRemoteConfigurationUrl.getText().toString(); - if (Patterns.WEB_URL.matcher(url).matches()) { - mWaitLayout.setVisibility(View.VISIBLE); - mFetchAndApply.setEnabled(false); - LinphonePreferences.instance().setRemoteProvisioningUrl(url); - LinphoneManager.getLc().getConfig().sync(); - Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); - if (core != null) { - core.addListener(mListener); - } - LinphoneManager.getInstance().restartCore(); - } else { - // TODO improve error text - Toast.makeText( - RemoteConfigurationAssistantActivity.this, - getString(R.string.remote_provisioning_failure), - Toast.LENGTH_LONG) - .show(); - } - } - }); - - mRemoteConfigurationUrl = findViewById(R.id.remote_configuration_url); - mRemoteConfigurationUrl.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged( - CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - mFetchAndApply.setEnabled(!s.toString().isEmpty()); - } - - @Override - public void afterTextChanged(Editable s) {} - }); - mRemoteConfigurationUrl.setText(LinphonePreferences.instance().getRemoteProvisioningUrl()); - - mQrCode = findViewById(R.id.qr_code); - mQrCode.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - if (checkCameraPermissionForQrCode()) { - startActivityForResult( - new Intent( - RemoteConfigurationAssistantActivity.this, - QrCodeConfigurationAssistantActivity.class), - QR_CODE_ACTIVITY_RESULT); - } - } - }); - - mListener = - new CoreListenerStub() { - @Override - public void onConfiguringStatus( - Core core, ConfiguringState status, String message) { - core.removeListener(mListener); - mWaitLayout.setVisibility(View.GONE); - mFetchAndApply.setEnabled(true); - - if (status == ConfiguringState.Successful) { - LinphonePreferences.instance().firstLaunchSuccessful(); - goToLinphoneActivity(); - } else if (status == ConfiguringState.Failed) { - Toast.makeText( - RemoteConfigurationAssistantActivity.this, - getString(R.string.remote_provisioning_failure), - Toast.LENGTH_LONG) - .show(); - } - } - }; - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - if (requestCode == QR_CODE_ACTIVITY_RESULT - && resultCode == Activity.RESULT_OK - && data != null) { - String url = data.getStringExtra("URL"); - mRemoteConfigurationUrl.setText(url); - } - super.onActivityResult(requestCode, resultCode, data); - } - - private boolean checkCameraPermissionForQrCode() { - int permissionGranted = - getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()); - Log.i( - "[Permission] Manifest.permission.CAMERA is " - + (permissionGranted == PackageManager.PERMISSION_GRANTED - ? "granted" - : "denied")); - - if (permissionGranted != PackageManager.PERMISSION_GRANTED) { - Log.i("[Permission] Asking for " + Manifest.permission.CAMERA); - ActivityCompat.requestPermissions( - this, new String[] {Manifest.permission.CAMERA}, CAMERA_PERMISSION_RESULT); - return false; - } - return true; - } - - @Override - public void onRequestPermissionsResult( - int requestCode, String[] permissions, final int[] grantResults) { - for (int i = 0; i < permissions.length; i++) { - Log.i( - "[Permission] " - + permissions[i] - + " has been " - + (grantResults[i] == PackageManager.PERMISSION_GRANTED - ? "granted" - : "denied")); - } - - switch (requestCode) { - case CAMERA_PERMISSION_RESULT: - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - startActivityForResult( - new Intent( - RemoteConfigurationAssistantActivity.this, - QrCodeConfigurationAssistantActivity.class), - QR_CODE_ACTIVITY_RESULT); - } else { - // TODO: permission denied, display something to the user - } - break; - } - } -} diff --git a/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java b/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java new file mode 100644 index 000000000..1660f1757 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java @@ -0,0 +1,217 @@ +package org.linphone.assistant; +/* +RemoteProvisioningActivity.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.Toast; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import org.linphone.LinphoneLauncherActivity; +import org.linphone.LinphoneManager; +import org.linphone.LinphoneService; +import org.linphone.R; +import org.linphone.core.ConfiguringState; +import org.linphone.core.Core; +import org.linphone.core.CoreListenerStub; +import org.linphone.core.tools.Log; +import org.linphone.settings.LinphonePreferences; +import org.linphone.utils.ThemableActivity; + +public class RemoteProvisioningActivity extends ThemableActivity { + private final Handler mHandler = new Handler(); + private String mConfigUriParam = null; + private ProgressBar mSpinner; + private CoreListenerStub mListener; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.remote_provisioning); + mSpinner = findViewById(R.id.spinner); + + mListener = + new CoreListenerStub() { + @Override + public void onConfiguringStatus( + Core lc, final ConfiguringState state, String message) { + if (mSpinner != null) mSpinner.setVisibility(View.GONE); + if (state == ConfiguringState.Successful) { + goToLinphoneActivity(); + } else if (state == ConfiguringState.Failed) { + Toast.makeText( + RemoteProvisioningActivity.this, + R.string.remote_provisioning_failure, + Toast.LENGTH_LONG) + .show(); + } + } + }; + } + + @Override + protected void onResume() { + super.onResume(); + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.addListener(mListener); + } + LinphonePreferences.instance().setContext(this); + + checkIntentForConfigUri(getIntent()); + } + + @Override + protected void onPause() { + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.removeListener(mListener); + } + super.onPause(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + checkIntentForConfigUri(intent); + } + + private void checkIntentForConfigUri(final Intent intent) { + new Thread( + new Runnable() { + + @Override + public void run() { + Uri openUri = intent.getData(); + if (openUri != null) { + // We expect something like + // linphone-config://http://linphone.org/config.xml + mConfigUriParam = + openUri.getEncodedSchemeSpecificPart() + .substring(2); // Removes the linphone-config:// + try { + mConfigUriParam = + URLDecoder.decode(mConfigUriParam, "UTF-8"); + } catch (UnsupportedEncodingException e) { + Log.e(e); + } + Log.d("Using config uri: " + mConfigUriParam); + } + + if (mConfigUriParam == null) { + if (!LinphonePreferences.instance() + .isFirstRemoteProvisioning()) { + mHandler.post( + new Runnable() { + @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( + mConfigUriParam); + } + }); + } + } + } + }) + .start(); + } + + private void displayDialogConfirmation() { + new AlertDialog.Builder(RemoteProvisioningActivity.this) + .setTitle(getString(R.string.remote_provisioning_again_title)) + .setMessage(getString(R.string.remote_provisioning_again_message)) + .setPositiveButton( + R.string.accept, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + setRemoteProvisioningAddressAndRestart(mConfigUriParam); + } + }) + .setNegativeButton( + R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + goToLinphoneActivity(); + } + }) + .show(); + } + + private void setRemoteProvisioningAddressAndRestart(final String configUri) { + if (mSpinner != null) mSpinner.setVisibility(View.VISIBLE); + + LinphonePreferences.instance().setContext(this); // Needed, else the next call will crash + LinphonePreferences.instance().setRemoteProvisioningUrl(configUri); + + LinphoneManager.getLc().getConfig().sync(); + LinphoneManager.getInstance().restartCore(); + } + + private void goToLinphoneActivity() { + if (LinphoneService.isReady()) { + LinphoneService.instance() + .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)); + } else { + finish(); + } + } +} diff --git a/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java b/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java new file mode 100644 index 000000000..e710ac213 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java @@ -0,0 +1,85 @@ +package org.linphone.assistant; +/* +RemoteProvisioningFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.settings.LinphonePreferences; + +public class RemoteProvisioningFragment extends Fragment implements OnClickListener, TextWatcher { + private EditText mRemoteProvisioningUrl; + private Button mApply, mQrcode; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.assistant_remote_provisioning, container, false); + + mRemoteProvisioningUrl = view.findViewById(R.id.assistant_remote_provisioning_url); + mRemoteProvisioningUrl.addTextChangedListener(this); + mQrcode = view.findViewById(R.id.assistant_qrcode); + mQrcode.setOnClickListener(this); + mApply = view.findViewById(R.id.assistant_apply); + mApply.setEnabled(false); + mApply.setOnClickListener(this); + + if (getArguments() != null && !getArguments().getString("RemoteUrl").isEmpty()) { + mRemoteProvisioningUrl.setText(getArguments().getString("RemoteUrl")); + } + + return view; + } + + @Override + public void onClick(View v) { + int id = v.getId(); + + if (id == R.id.assistant_apply) { + String url = mRemoteProvisioningUrl.getText().toString(); + AssistantActivity.instance().displayRemoteProvisioningInProgressDialog(); + LinphonePreferences.instance().setRemoteProvisioningUrl(url); + LinphoneManager.getLc().getConfig().sync(); + LinphoneManager.getInstance().restartCore(); + AssistantActivity.instance().setCoreListener(); + } else if (id == R.id.assistant_qrcode) { + AssistantActivity.instance().displayQRCodeReader(); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mApply.setEnabled(!mRemoteProvisioningUrl.getText().toString().isEmpty()); + } + + @Override + public void afterTextChanged(Editable s) {} +} diff --git a/app/src/main/java/org/linphone/assistant/RemoteProvisioningLoginActivity.java b/app/src/main/java/org/linphone/assistant/RemoteProvisioningLoginActivity.java new file mode 100644 index 000000000..0869985a3 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/RemoteProvisioningLoginActivity.java @@ -0,0 +1,143 @@ +package org.linphone.assistant; +/* +RemoteProvisioningLoginActivity.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.ConfiguringState; +import org.linphone.core.Core; +import org.linphone.core.CoreListenerStub; +import org.linphone.settings.LinphonePreferences; +import org.linphone.utils.ThemableActivity; +import org.linphone.xmlrpc.XmlRpcHelper; +import org.linphone.xmlrpc.XmlRpcListenerBase; + +public class RemoteProvisioningLoginActivity extends ThemableActivity implements OnClickListener { + private EditText mLogin, mPassword, mDomain; + private Button mConnect; + private CoreListenerStub mListener; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.assistant_remote_provisioning_login); + + mLogin = findViewById(R.id.assistant_username); + mPassword = findViewById(R.id.assistant_password); + mDomain = findViewById(R.id.assistant_domain); + + mConnect = findViewById(R.id.assistant_connect); + mConnect.setOnClickListener(this); + + String defaultDomain = getIntent().getStringExtra("Domain"); + if (defaultDomain != null) { + mDomain.setText(defaultDomain); + mDomain.setEnabled(false); + } + + mListener = + new CoreListenerStub() { + @Override + public void onConfiguringStatus( + Core lc, final ConfiguringState state, String message) { + if (state == ConfiguringState.Successful) { + // TODO + } else if (state == ConfiguringState.Failed) { + Toast.makeText( + RemoteProvisioningLoginActivity.this, + R.string.remote_provisioning_failure, + Toast.LENGTH_LONG) + .show(); + } + } + }; + } + + private void cancelWizard() { + if (getResources().getBoolean(R.bool.allow_cancel_remote_provisioning_login_activity)) { + LinphonePreferences.instance().disableProvisioningLoginView(); + setResult(Activity.RESULT_CANCELED); + finish(); + } + } + + private void storeAccount(String username, String password, String domain) { + XmlRpcHelper xmlRpcHelper = new XmlRpcHelper(); + xmlRpcHelper.getRemoteProvisioningFilenameAsync( + new XmlRpcListenerBase() { + @Override + public void onRemoteProvisioningFilenameSent(String result) { + LinphonePreferences.instance().setRemoteProvisioningUrl(result); + LinphoneManager.getInstance().restartCore(); + } + }, + username, + password, + domain); + + LinphonePreferences.instance().firstLaunchSuccessful(); + setResult(Activity.RESULT_OK); + finish(); + } + + @Override + protected void onResume() { + super.onResume(); + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.addListener(mListener); + } + } + + @Override + protected void onPause() { + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.removeListener(mListener); + } + super.onPause(); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + + if (id == R.id.cancel) { + cancelWizard(); + } + if (id == R.id.assistant_connect) { + storeAccount( + mLogin.getText().toString(), + mPassword.getText().toString(), + mDomain.getText().toString()); + } + } + + @Override + public void onBackPressed() { + cancelWizard(); + } +} diff --git a/app/src/main/java/org/linphone/assistant/WelcomeFragment.java b/app/src/main/java/org/linphone/assistant/WelcomeFragment.java new file mode 100644 index 000000000..089b8f328 --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/WelcomeFragment.java @@ -0,0 +1,78 @@ +package org.linphone.assistant; +/* +WelcomeFragment.java +Copyright (C) 2017 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.TextView; +import org.linphone.R; + +public class WelcomeFragment extends Fragment implements OnClickListener { + private TextView mCreateAccount, mLogLinphoneAccount, mLogGenericAccount, mRemoteProvisioning; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.assistant_welcome, container, false); + + mCreateAccount = view.findViewById(R.id.create_account); + mCreateAccount.setOnClickListener(this); + + mLogLinphoneAccount = view.findViewById(R.id.login_linphone); + if (getResources().getBoolean(R.bool.hide_linphone_accounts_in_assistant)) { + mLogLinphoneAccount.setVisibility(View.GONE); + } else { + mLogLinphoneAccount.setOnClickListener(this); + } + + mLogGenericAccount = view.findViewById(R.id.login_generic); + if (getResources().getBoolean(R.bool.hide_generic_accounts_in_assistant)) { + mLogGenericAccount.setVisibility(View.GONE); + } else { + mLogGenericAccount.setOnClickListener(this); + } + + mRemoteProvisioning = view.findViewById(R.id.remote_provisioning); + if (getResources().getBoolean(R.bool.hide_remote_provisioning_in_assistant)) { + mRemoteProvisioning.setVisibility(View.GONE); + } else { + mRemoteProvisioning.setOnClickListener(this); + } + + return view; + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.login_generic) { + AssistantActivity.instance().displayLoginGeneric(); + } else if (id == R.id.login_linphone) { + AssistantActivity.instance().displayLoginLinphone(null, null); + } else if (id == R.id.create_account) { + AssistantActivity.instance().displayCreateAccount(); + } else if (id == R.id.remote_provisioning) { + AssistantActivity.instance().displayRemoteProvisioning(""); + } + } +} diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index 0e8d1772c..da23aeaff 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -27,6 +27,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -170,6 +171,10 @@ public class CallActivity extends LinphoneGenericActivity super.onCreate(savedInstanceState); sInstance = this; + if (getResources().getBoolean(R.bool.orientation_portrait_only)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); Compatibility.setShowWhenLocked(this, true); diff --git a/app/src/main/java/org/linphone/call/CallIncomingActivity.java b/app/src/main/java/org/linphone/call/CallIncomingActivity.java index 068aa110e..62f6adb83 100644 --- a/app/src/main/java/org/linphone/call/CallIncomingActivity.java +++ b/app/src/main/java/org/linphone/call/CallIncomingActivity.java @@ -23,6 +23,7 @@ import android.Manifest; import android.app.KeyguardManager; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.KeyEvent; @@ -78,6 +79,10 @@ public class CallIncomingActivity extends LinphoneGenericActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (getResources().getBoolean(R.bool.orientation_portrait_only)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + Compatibility.setShowWhenLocked(this, true); Compatibility.setTurnScreenOn(this, true); diff --git a/app/src/main/java/org/linphone/call/CallOutgoingActivity.java b/app/src/main/java/org/linphone/call/CallOutgoingActivity.java index 55fa13bcc..9fc3e45e9 100644 --- a/app/src/main/java/org/linphone/call/CallOutgoingActivity.java +++ b/app/src/main/java/org/linphone/call/CallOutgoingActivity.java @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import android.Manifest; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.Gravity; @@ -62,6 +63,10 @@ public class CallOutgoingActivity extends LinphoneGenericActivity implements OnC protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (getResources().getBoolean(R.bool.orientation_portrait_only)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.call_outgoing); diff --git a/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java b/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java index 1f75c9927..7e1be930d 100644 --- a/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java @@ -516,6 +516,9 @@ public class ChatRoomCreationFragment extends Fragment mShareInfos, mSecurityToggle.isChecked()); } + } else if (id == R.id.clearSearchField) { + mSearchField.setQuery("", false); + mSearchAdapter.searchContacts(""); } else if (id == R.id.contactChatDelete) { ContactAddress ca = (ContactAddress) view.getTag(); addOrRemoveContactFromSelection(ca); diff --git a/app/src/main/java/org/linphone/fragments/StatusFragment.java b/app/src/main/java/org/linphone/fragments/StatusFragment.java index 0a3b2f67b..e80ddc749 100644 --- a/app/src/main/java/org/linphone/fragments/StatusFragment.java +++ b/app/src/main/java/org/linphone/fragments/StatusFragment.java @@ -40,6 +40,7 @@ import org.linphone.LinphoneActivity; import org.linphone.LinphoneManager; import org.linphone.LinphoneService; import org.linphone.R; +import org.linphone.assistant.AssistantActivity; import org.linphone.call.CallActivity; import org.linphone.call.CallIncomingActivity; import org.linphone.call.CallOutgoingActivity; @@ -164,6 +165,8 @@ public class StatusFragment extends Fragment { ((LinphoneActivity) activity).updateStatusFragment(this); } else if (activity instanceof CallActivity) { ((CallActivity) activity).updateStatusFragment(this); + } else if (activity instanceof AssistantActivity) { + ((AssistantActivity) activity).updateStatusFragment(this); } mIsInCall = activity instanceof CallActivity @@ -173,6 +176,18 @@ public class StatusFragment extends Fragment { return view; } + public void setCoreListener() { + Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + lc.addListener(mListener); + + ProxyConfig lpc = lc.getDefaultProxyConfig(); + if (lpc != null) { + mListener.onRegistrationStateChanged(lc, lpc, lpc.getState(), null); + } + } + } + @Override public void onDetach() { super.onDetach(); diff --git a/app/src/main/java/org/linphone/settings/AccountSettingsFragment.java b/app/src/main/java/org/linphone/settings/AccountSettingsFragment.java index 5625c5fb5..f89373c81 100644 --- a/app/src/main/java/org/linphone/settings/AccountSettingsFragment.java +++ b/app/src/main/java/org/linphone/settings/AccountSettingsFragment.java @@ -32,7 +32,7 @@ import java.util.List; import org.linphone.LinphoneActivity; import org.linphone.LinphoneManager; import org.linphone.R; -import org.linphone.assistant.PhoneAccountLinkingAssistantActivity; +import org.linphone.assistant.AssistantActivity; import org.linphone.core.AVPFMode; import org.linphone.core.Address; import org.linphone.core.AuthInfo; @@ -546,9 +546,9 @@ public class AccountSettingsFragment extends Fragment { @Override public void onClicked() { Intent assistant = new Intent(); - assistant.setClass( - LinphoneActivity.instance(), - PhoneAccountLinkingAssistantActivity.class); + assistant.setClass(LinphoneActivity.instance(), AssistantActivity.class); + assistant.putExtra("LinkPhoneNumber", true); + assistant.putExtra("FromPref", true); assistant.putExtra("AccountNumber", mAccountIndex); startActivity(assistant); } diff --git a/app/src/main/java/org/linphone/settings/LinphonePreferences.java b/app/src/main/java/org/linphone/settings/LinphonePreferences.java index 787f43e1f..402a134ed 100644 --- a/app/src/main/java/org/linphone/settings/LinphonePreferences.java +++ b/app/src/main/java/org/linphone/settings/LinphonePreferences.java @@ -164,6 +164,13 @@ public class LinphonePreferences { return (proxyConf != null) ? proxyConf.getDomain() : ""; } + public void setPrefix(int n, String prefix) { + ProxyConfig prxCfg = getProxyConfig(n); + prxCfg.edit(); + prxCfg.setDialPrefix(prefix); + prxCfg.done(); + } + public boolean isFriendlistsubscriptionEnabled() { if (getConfig().getBool("app", "friendlist_subscription_enabled", false)) { // Old setting, do migration @@ -228,6 +235,21 @@ public class LinphonePreferences { public boolean isAccountEnabled(int n) { return getProxyConfig(n).registerEnabled(); } + + public void resetDefaultProxyConfig() { + if (getLc() == null) return; + int count = getLc().getProxyConfigList().length; + for (int i = 0; i < count; i++) { + if (isAccountEnabled(i)) { + getLc().setDefaultProxyConfig(getProxyConfig(i)); + break; + } + } + + if (getLc().getDefaultProxyConfig() == null) { + getLc().setDefaultProxyConfig(getProxyConfig(0)); + } + } // End of accounts settings // Audio settings @@ -798,8 +820,20 @@ public class LinphonePreferences { LinphoneManager.getInstance().initTunnelFromConf(); } + public boolean isProvisioningLoginViewEnabled() { + + return (getConfig() != null) && getConfig().getBool("app", "show_login_view", false); + } // End of tunnel settings + public void disableProvisioningLoginView() { + if (isProvisioningLoginViewEnabled()) { // Only do it if it was previously enabled + getConfig().setBool("app", "show_login_view", false); + } else { + Log.w("Remote provisioning login view wasn't enabled, ignoring"); + } + } + public boolean isFirstRemoteProvisioning() { return getConfig().getBool("app", "first_remote_provisioning", true); } @@ -987,6 +1021,10 @@ public class LinphonePreferences { getConfig().setInt("app", "auto_answer_delay", time); } + public int getCodeLength() { + return getConfig().getInt("app", "activation_code_length", 0); + } + public void disableFriendsStorage() { getConfig().setBool("misc", "store_friends", false); } @@ -1038,20 +1076,4 @@ public class LinphonePreferences { public void setDeviceName(String name) { getConfig().setString("app", "device_name", name); } - - public boolean isEchoCancellationCalibrationDone() { - return getConfig().getBool("app", "echo_cancellation_calibration_done", false); - } - - public void setEchoCancellationCalibrationDone(boolean done) { - getConfig().setBool("app", "echo_cancellation_calibration_done", done); - } - - public boolean isOpenH264CodecDownloadEnabled() { - return getConfig().getBool("app", "open_h264_download_enabled", true); - } - - public void setOpenH264CodecDownloadEnabled(boolean enable) { - getConfig().setBool("app", "open_h264_download_enabled", enable); - } } diff --git a/app/src/main/java/org/linphone/settings/SettingsFragment.java b/app/src/main/java/org/linphone/settings/SettingsFragment.java index 5080c133f..f383c818c 100644 --- a/app/src/main/java/org/linphone/settings/SettingsFragment.java +++ b/app/src/main/java/org/linphone/settings/SettingsFragment.java @@ -153,11 +153,6 @@ public class SettingsFragment extends Fragment { mTunnel.setVisibility(core.tunnelAvailable() ? View.VISIBLE : View.GONE); initAccounts(core); } - - if (getResources().getBoolean(R.bool.hide_accounts)) { - mAccounts.setVisibility(View.GONE); - mAccountsHeader.setVisibility(View.GONE); - } } private void initAccounts(Core core) { diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.java b/app/src/main/java/org/linphone/utils/LinphoneUtils.java index defa58a2a..70d4fe5cd 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.java +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.java @@ -33,6 +33,8 @@ import android.text.Spanned; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; @@ -43,6 +45,7 @@ import java.util.regex.Pattern; import org.linphone.LinphoneManager; import org.linphone.LinphoneService; import org.linphone.R; +import org.linphone.core.AccountCreator; import org.linphone.core.Address; import org.linphone.core.Call; import org.linphone.core.Call.State; @@ -313,6 +316,112 @@ public final class LinphoneUtils { return sipAddress; } + public static void displayError(boolean isOk, TextView error, String errorText) { + if (isOk) { + error.setVisibility(View.INVISIBLE); + error.setText(""); + } else { + error.setVisibility(View.VISIBLE); + error.setText(errorText); + } + } + + public static String errorForPhoneNumberStatus(int status) { + Context ctxt = getContext(); + if (ctxt != null) { + if (AccountCreator.PhoneNumberStatus.InvalidCountryCode.toInt() + == (status & AccountCreator.PhoneNumberStatus.InvalidCountryCode.toInt())) + return ctxt.getString(R.string.country_code_invalid); + if (AccountCreator.PhoneNumberStatus.TooShort.toInt() + == (status & AccountCreator.PhoneNumberStatus.TooShort.toInt())) + return ctxt.getString(R.string.phone_number_too_short); + if (AccountCreator.PhoneNumberStatus.TooLong.toInt() + == (status & AccountCreator.PhoneNumberStatus.TooLong.toInt())) + return ctxt.getString(R.string.phone_number_too_long); + if (AccountCreator.PhoneNumberStatus.Invalid.toInt() + == (status & AccountCreator.PhoneNumberStatus.Invalid.toInt())) + return ctxt.getString(R.string.phone_number_invalid); + } + return null; + } + + public static String errorForEmailStatus(AccountCreator.EmailStatus status) { + Context ctxt = getContext(); + if (ctxt != null) { + if (status.equals(AccountCreator.EmailStatus.InvalidCharacters) + || status.equals(AccountCreator.EmailStatus.Malformed)) + return ctxt.getString(R.string.invalid_email); + } + return null; + } + + public static String errorForUsernameStatus(AccountCreator.UsernameStatus status) { + Context ctxt = getContext(); + if (ctxt != null) { + if (status.equals(AccountCreator.UsernameStatus.InvalidCharacters)) + return ctxt.getString(R.string.invalid_username); + if (status.equals(AccountCreator.UsernameStatus.TooShort)) + return ctxt.getString(R.string.username_too_short); + if (status.equals(AccountCreator.UsernameStatus.TooLong)) + return ctxt.getString(R.string.username_too_long); + if (status.equals(AccountCreator.UsernameStatus.Invalid)) + return ctxt.getString(R.string.username_invalid_size); + if (status.equals(AccountCreator.UsernameStatus.InvalidCharacters)) + return ctxt.getString(R.string.invalid_display_name); + } + return null; + } + + public static String errorForPasswordStatus(AccountCreator.PasswordStatus status) { + Context ctxt = getContext(); + if (ctxt != null) { + if (status.equals(AccountCreator.PasswordStatus.TooShort)) + return ctxt.getString(R.string.password_too_short); + if (status.equals(AccountCreator.PasswordStatus.TooLong)) + return ctxt.getString(R.string.password_too_long); + } + return null; + } + + public static String errorForStatus(AccountCreator.Status status) { + Context ctxt = getContext(); + Log.e("Status error " + status.name()); + if (ctxt != null) { + if (status.equals(AccountCreator.Status.RequestFailed)) + return ctxt.getString(R.string.request_failed); + if (status.equals(AccountCreator.Status.ServerError)) + return ctxt.getString(R.string.wizard_failed); + if (status.equals(AccountCreator.Status.AccountExist) + || status.equals(AccountCreator.Status.AccountExistWithAlias)) + return ctxt.getString(R.string.account_already_exist); + if (status.equals(AccountCreator.Status.AliasIsAccount) + || status.equals(AccountCreator.Status.AliasExist)) + return ctxt.getString(R.string.assistant_phone_number_unavailable); + if (status.equals(AccountCreator.Status.AccountNotExist)) + return ctxt.getString(R.string.assistant_error_bad_credentials); + if (status.equals(AccountCreator.Status.AliasNotExist)) + return ctxt.getString(R.string.phone_number_not_exist); + if (status.equals(AccountCreator.Status.AliasNotExist) + || status.equals(AccountCreator.Status.AccountNotActivated) + || status.equals(AccountCreator.Status.AccountAlreadyActivated) + || status.equals(AccountCreator.Status.AccountActivated) + || status.equals(AccountCreator.Status.AccountNotCreated) + || status.equals(AccountCreator.Status.RequestOk)) return ""; + } + return null; + } + + public static String getCountryCode(EditText dialCode) { + if (dialCode != null) { + String code = dialCode.getText().toString(); + if (code != null && code.startsWith("+")) { + code = code.substring(1); + } + return code; + } + return null; + } + public static void displayErrorAlert(String msg, Context ctxt) { if (ctxt != null && msg != null) { AlertDialog.Builder builder = new AlertDialog.Builder(ctxt); @@ -375,6 +484,12 @@ public final class LinphoneUtils { imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } + private static Context getContext() { + if (sContext == null && LinphoneManager.isInstanciated()) + sContext = LinphoneManager.getInstance().getContext(); + return sContext; + } + public static ArrayList removeEmptyOneToOneChatRooms(ChatRoom[] rooms) { ArrayList newRooms = new ArrayList<>(); for (ChatRoom room : rooms) { diff --git a/app/src/main/java/org/linphone/utils/ThemableActivity.java b/app/src/main/java/org/linphone/utils/ThemableActivity.java index 79e9caa3a..871607a51 100644 --- a/app/src/main/java/org/linphone/utils/ThemableActivity.java +++ b/app/src/main/java/org/linphone/utils/ThemableActivity.java @@ -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. */ -import android.content.pm.ActivityInfo; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import org.linphone.R; @@ -33,10 +32,6 @@ public class ThemableActivity extends AppCompatActivity { setTheme(R.style.LinphoneStyleDark); } - if (getResources().getBoolean(R.bool.orientation_portrait_only)) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } - super.onCreate(savedInstanceState); } } diff --git a/app/src/main/res/layout-land/assistant_codec_downloader.xml b/app/src/main/res/layout-land/assistant_codec_downloader.xml new file mode 100644 index 000000000..1d28702ba --- /dev/null +++ b/app/src/main/res/layout-land/assistant_codec_downloader.xml @@ -0,0 +1,103 @@ + + + + + + + + + +