create api calls
This commit is contained in:
parent
31eb89e2fb
commit
2fa629d113
|
@ -24,7 +24,11 @@ public class Plain extends SaslMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientFirstMessage() {
|
public String getClientFirstMessage() {
|
||||||
final String sasl = '\u0000' + account.getUsername() + '\u0000' + account.getPassword();
|
return getMessage(account.getUsername(), account.getPassword());
|
||||||
return Base64.encodeToString(sasl.getBytes(Charset.defaultCharset()), Base64.NO_WRAP);
|
}
|
||||||
|
|
||||||
|
public static String getMessage(String username, String password) {
|
||||||
|
final String message = '\u0000' + username + '\u0000' + password;
|
||||||
|
return Base64.encodeToString(message.getBytes(Charset.defaultCharset()), Base64.NO_WRAP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,9 +760,11 @@
|
||||||
<string name="please_enter_your_phone_number">Please enter your phone number.</string>
|
<string name="please_enter_your_phone_number">Please enter your phone number.</string>
|
||||||
<string name="search_countries">Search countries</string>
|
<string name="search_countries">Search countries</string>
|
||||||
<string name="verify_x">Verify %s</string>
|
<string name="verify_x">Verify %s</string>
|
||||||
<string name="we_have_sent_you_an_sms"><![CDATA[We have sent you an SMS to <b>%s</b>.]]></string>
|
<string name="we_have_sent_you_an_sms_to_x"><![CDATA[We have sent you an SMS to <b>%s</b>.]]></string>
|
||||||
|
<string name="we_have_sent_you_the_sms_again">We have sent you the SMS again.</string>
|
||||||
<string name="please_enter_pin_below">Please enter the 6 digit pin below.</string>
|
<string name="please_enter_pin_below">Please enter the 6 digit pin below.</string>
|
||||||
<string name="resend_sms">Resend SMS</string>
|
<string name="resend_sms">Resend SMS</string>
|
||||||
|
<string name="resend_sms_in">Resend SMS (%s)</string>
|
||||||
<string name="back">back</string>
|
<string name="back">back</string>
|
||||||
<string name="possible_pin">Automatically pasted possible pin from clipboard.</string>
|
<string name="possible_pin">Automatically pasted possible pin from clipboard.</string>
|
||||||
<string name="please_enter_pin">Please enter your 6 digit pin.</string>
|
<string name="please_enter_pin">Please enter your 6 digit pin.</string>
|
||||||
|
@ -770,4 +772,5 @@
|
||||||
<string name="yes">Yes</string>
|
<string name="yes">Yes</string>
|
||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
<string name="verifying">Verifying…</string>
|
<string name="verifying">Verifying…</string>
|
||||||
|
<string name="requesting_sms">Requesting SMS…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
package eu.siacs.conversations.services;
|
package eu.siacs.conversations.services;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -10,7 +19,9 @@ import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
import eu.siacs.conversations.crypto.sasl.Plain;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||||
import io.michaelrocks.libphonenumber.android.Phonenumber;
|
import io.michaelrocks.libphonenumber.android.Phonenumber;
|
||||||
|
@ -18,12 +29,20 @@ import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class QuickConversationsService {
|
public class QuickConversationsService {
|
||||||
|
|
||||||
|
|
||||||
|
public static final int API_ERROR_OTHER = -1;
|
||||||
|
public static final int API_ERROR_UNKNOWN_HOST = -2;
|
||||||
|
public static final int API_ERROR_CONNECT = -3;
|
||||||
|
|
||||||
|
private static final String BASE_URL = "https://venus.fritz.box:4567";
|
||||||
|
|
||||||
private final XmppConnectionService service;
|
private final XmppConnectionService service;
|
||||||
|
|
||||||
private final Set<OnVerificationRequested> mOnVerificationRequested = Collections.newSetFromMap(new WeakHashMap<>());
|
private final Set<OnVerificationRequested> mOnVerificationRequested = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
private final Set<OnVerification> mOnVerification = Collections.newSetFromMap(new WeakHashMap<>());
|
private final Set<OnVerification> mOnVerification = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
|
|
||||||
private final AtomicBoolean mVerificationInProgress = new AtomicBoolean(false);
|
private final AtomicBoolean mVerificationInProgress = new AtomicBoolean(false);
|
||||||
|
private final AtomicBoolean mVerificationRequestInProgress = new AtomicBoolean(false);
|
||||||
|
|
||||||
QuickConversationsService(XmppConnectionService xmppConnectionService) {
|
QuickConversationsService(XmppConnectionService xmppConnectionService) {
|
||||||
this.service = xmppConnectionService;
|
this.service = xmppConnectionService;
|
||||||
|
@ -54,31 +73,136 @@ public class QuickConversationsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestVerification(Phonenumber.PhoneNumber phoneNumber) {
|
public void requestVerification(Phonenumber.PhoneNumber phoneNumber) {
|
||||||
|
final String e164 = PhoneNumberUtilWrapper.normalize(service, phoneNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /authentication/+phoneNumber
|
||||||
|
*
|
||||||
|
* - returns too many requests, (sms ist unterwegs), retry after seconden -- auf jeden fall in nächste activity (verify activity) weiter leiten weil es sein kann das sms noch ankommt
|
||||||
|
* - returns OK; success (auch in activity weiter lassen. aber ohne error paramater; dh send again button is activ; und vielleicht kurzer toast bzw snackbar
|
||||||
|
* - returns invalid request user error wenn die phone number falsch ist
|
||||||
|
*/
|
||||||
|
if (mVerificationRequestInProgress.compareAndSet(false, true)) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
Thread.sleep(5000);
|
||||||
|
|
||||||
|
final URL url = new URL(BASE_URL + "/authentication/" + e164);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||||
|
connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||||
|
final int code = connection.getResponseCode();
|
||||||
|
if (code == 200) {
|
||||||
|
createAccountAndWait(phoneNumber, 0L);
|
||||||
|
} else if (code == 429) {
|
||||||
|
createAccountAndWait(phoneNumber, retryAfter(connection));
|
||||||
|
} else {
|
||||||
|
synchronized (mOnVerificationRequested) {
|
||||||
|
for (OnVerificationRequested onVerificationRequested : mOnVerificationRequested) {
|
||||||
|
onVerificationRequested.onVerificationRequestFailed(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
final int code = getApiErrorCode(e);
|
||||||
|
synchronized (mOnVerificationRequested) {
|
||||||
|
for (OnVerificationRequested onVerificationRequested : mOnVerificationRequested) {
|
||||||
|
onVerificationRequested.onVerificationRequestFailed(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
mVerificationRequestInProgress.set(false);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAccountAndWait(Phonenumber.PhoneNumber phoneNumber, final long timestamp) {
|
||||||
String local = PhoneNumberUtilWrapper.normalize(service, phoneNumber);
|
String local = PhoneNumberUtilWrapper.normalize(service, phoneNumber);
|
||||||
Log.d(Config.LOGTAG,"requesting verification for "+PhoneNumberUtilWrapper.normalize(service,phoneNumber));
|
Log.d(Config.LOGTAG, "requesting verification for " + PhoneNumberUtilWrapper.normalize(service, phoneNumber));
|
||||||
Account account = new Account(Jid.of(local,"quick.conversations.im",null), CryptoHelper.createPassword(new SecureRandom()));
|
Jid jid = Jid.of(local, "quick.conversations.im", null);
|
||||||
account.setOption(Account.OPTION_DISABLED, true);
|
Account account = AccountUtils.getFirst(service);
|
||||||
account.setOption(Account.OPTION_UNVERIFIED, true);
|
if (account == null || !account.getJid().asBareJid().equals(jid.asBareJid())) {
|
||||||
service.createAccount(account);
|
if (account != null) {
|
||||||
|
service.deleteAccount(account);
|
||||||
|
}
|
||||||
|
account = new Account(jid, CryptoHelper.createPassword(new SecureRandom()));
|
||||||
|
account.setOption(Account.OPTION_DISABLED, true);
|
||||||
|
account.setOption(Account.OPTION_UNVERIFIED, true);
|
||||||
|
service.createAccount(account);
|
||||||
|
}
|
||||||
synchronized (mOnVerificationRequested) {
|
synchronized (mOnVerificationRequested) {
|
||||||
for(OnVerificationRequested onVerificationRequested : mOnVerificationRequested) {
|
for (OnVerificationRequested onVerificationRequested : mOnVerificationRequested) {
|
||||||
onVerificationRequested.onVerificationRequested();
|
if (timestamp <= 0) {
|
||||||
|
onVerificationRequested.onVerificationRequested();
|
||||||
|
} else {
|
||||||
|
onVerificationRequested.onVerificationRequestedRetryAt(timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verify(Account account, String pin) {
|
public void verify(Account account, String pin) {
|
||||||
|
/**
|
||||||
|
* POST /password
|
||||||
|
* authentication gesetzt mit telephone nummber und verification code
|
||||||
|
* body = password
|
||||||
|
*
|
||||||
|
* retry after, too many requests
|
||||||
|
* code wrong
|
||||||
|
* OK (weiterleiten auf publish avatar activity
|
||||||
|
*
|
||||||
|
*/
|
||||||
if (mVerificationInProgress.compareAndSet(false, true)) {
|
if (mVerificationInProgress.compareAndSet(false, true)) {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
synchronized (mOnVerification) {
|
|
||||||
for (OnVerification onVerification : mOnVerification) {
|
final URL url = new URL(BASE_URL + "/password");
|
||||||
onVerification.onVerificationFailed();
|
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||||
|
connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Authorization", Plain.getMessage(account.getUsername(), pin));
|
||||||
|
final OutputStream os = connection.getOutputStream();
|
||||||
|
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
|
||||||
|
writer.write(account.getPassword());
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
os.close();
|
||||||
|
connection.connect();
|
||||||
|
final int code = connection.getResponseCode();
|
||||||
|
if (code == 200) {
|
||||||
|
synchronized (mOnVerification) {
|
||||||
|
for (OnVerification onVerification : mOnVerification) {
|
||||||
|
onVerification.onVerificationSucceeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (code == 429) {
|
||||||
|
final long retryAfter = retryAfter(connection);
|
||||||
|
synchronized (mOnVerification) {
|
||||||
|
for (OnVerification onVerification : mOnVerification) {
|
||||||
|
onVerification.onVerificationRetryAt(retryAfter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (mOnVerification) {
|
||||||
|
for (OnVerification onVerification : mOnVerification) {
|
||||||
|
onVerification.onVerificationFailed(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
final int code = getApiErrorCode(e);
|
||||||
|
synchronized (mOnVerification) {
|
||||||
|
for (OnVerification onVerification : mOnVerification) {
|
||||||
|
onVerification.onVerificationFailed(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
} finally {
|
||||||
mVerificationInProgress.set(false);
|
mVerificationInProgress.set(false);
|
||||||
}
|
}
|
||||||
|
@ -86,17 +210,46 @@ public class QuickConversationsService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getApiErrorCode(Exception e) {
|
||||||
|
if (e instanceof UnknownHostException) {
|
||||||
|
return API_ERROR_UNKNOWN_HOST;
|
||||||
|
} else if (e instanceof ConnectException) {
|
||||||
|
return API_ERROR_CONNECT;
|
||||||
|
} else {
|
||||||
|
Log.d(Config.LOGTAG,e.getClass().getName());
|
||||||
|
return API_ERROR_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long retryAfter(HttpURLConnection connection) {
|
||||||
|
try {
|
||||||
|
return SystemClock.elapsedRealtime() + (Long.parseLong(connection.getHeaderField("Retry-After")) * 1000L);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isVerifying() {
|
public boolean isVerifying() {
|
||||||
return mVerificationInProgress.get();
|
return mVerificationInProgress.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRequestingVerification() {
|
||||||
|
return mVerificationRequestInProgress.get();
|
||||||
|
}
|
||||||
|
|
||||||
public interface OnVerificationRequested {
|
public interface OnVerificationRequested {
|
||||||
void onVerificationRequestFailed(int code);
|
void onVerificationRequestFailed(int code);
|
||||||
|
|
||||||
void onVerificationRequested();
|
void onVerificationRequested();
|
||||||
|
|
||||||
|
void onVerificationRequestedRetryAt(long timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnVerification {
|
public interface OnVerification {
|
||||||
void onVerificationFailed();
|
void onVerificationFailed(int code);
|
||||||
|
|
||||||
void onVerificationSucceeded();
|
void onVerificationSucceeded();
|
||||||
|
|
||||||
|
void onVerificationRetryAt(long timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,10 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
||||||
private static final int REQUEST_CHOOSE_COUNTRY = 0x1234;
|
private static final int REQUEST_CHOOSE_COUNTRY = 0x1234;
|
||||||
|
|
||||||
private ActivityEnterNumberBinding binding;
|
private ActivityEnterNumberBinding binding;
|
||||||
|
|
||||||
private String region = null;
|
private String region = null;
|
||||||
|
private boolean requestingVerification = false;
|
||||||
|
|
||||||
private final TextWatcher countryCodeTextWatcher = new TextWatcher() {
|
private final TextWatcher countryCodeTextWatcher = new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
@ -78,6 +81,7 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
String region = savedInstanceState != null ? savedInstanceState.getString("region") : null;
|
String region = savedInstanceState != null ? savedInstanceState.getString("region") : null;
|
||||||
|
boolean requestingVerification = savedInstanceState != null && savedInstanceState.getBoolean("requesting_verification", false);
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
this.region = region;
|
this.region = region;
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,6 +95,7 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
||||||
setSupportActionBar((Toolbar) this.binding.toolbar);
|
setSupportActionBar((Toolbar) this.binding.toolbar);
|
||||||
this.binding.countryCode.addTextChangedListener(this.countryCodeTextWatcher);
|
this.binding.countryCode.addTextChangedListener(this.countryCodeTextWatcher);
|
||||||
this.binding.countryCode.setText(String.valueOf(PhoneNumberUtilWrapper.getInstance(this).getCountryCodeForRegion(this.region)));
|
this.binding.countryCode.setText(String.valueOf(PhoneNumberUtilWrapper.getInstance(this).getCountryCodeForRegion(this.region)));
|
||||||
|
setRequestingVerificationState(requestingVerification);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -98,6 +103,7 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
||||||
if (this.region != null) {
|
if (this.region != null) {
|
||||||
savedInstanceState.putString("region", this.region);
|
savedInstanceState.putString("region", this.region);
|
||||||
}
|
}
|
||||||
|
savedInstanceState.putBoolean("requesting_verification", this.requestingVerification);
|
||||||
super.onSaveInstanceState(savedInstanceState);
|
super.onSaveInstanceState(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,9 +148,19 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPhoneNumberEntered(Phonenumber.PhoneNumber phoneNumber) {
|
private void onPhoneNumberEntered(Phonenumber.PhoneNumber phoneNumber) {
|
||||||
|
setRequestingVerificationState(true);
|
||||||
xmppConnectionService.getQuickConversationsService().requestVerification(phoneNumber);
|
xmppConnectionService.getQuickConversationsService().requestVerification(phoneNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setRequestingVerificationState(boolean requesting) {
|
||||||
|
this.requestingVerification = requesting;
|
||||||
|
this.binding.countryCode.setEnabled(!requesting);
|
||||||
|
this.binding.country.setEnabled(!requesting);
|
||||||
|
this.binding.number.setEnabled(!requesting);
|
||||||
|
this.binding.next.setEnabled(!requesting);
|
||||||
|
this.binding.next.setText(requesting ? R.string.requesting_sms : R.string.next);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
@ -160,13 +176,25 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVerificationRequestFailed(int code) {
|
public void onVerificationRequestFailed(int code) {
|
||||||
|
runOnUiThread(()->{
|
||||||
|
setRequestingVerificationState(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVerificationRequested() {
|
public void onVerificationRequested() {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
startActivity(new Intent(this,VerifyActivity.class));
|
startActivity(new Intent(this, VerifyActivity.class));
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVerificationRequestedRetryAt(long timestamp) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
Intent intent = new Intent(this, VerifyActivity.class);
|
||||||
|
intent.putExtra(VerifyActivity.EXTRA_RETRY_SMS_AFTER, timestamp);
|
||||||
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,15 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.databinding.ActivityVerifyBinding;
|
import eu.siacs.conversations.databinding.ActivityVerifyBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
@ -20,10 +24,14 @@ import eu.siacs.conversations.services.QuickConversationsService;
|
||||||
import eu.siacs.conversations.ui.util.PinEntryWrapper;
|
import eu.siacs.conversations.ui.util.PinEntryWrapper;
|
||||||
import eu.siacs.conversations.utils.AccountUtils;
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||||
|
import eu.siacs.conversations.utils.TimeframeUtils;
|
||||||
|
import io.michaelrocks.libphonenumber.android.NumberParseException;
|
||||||
|
|
||||||
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
|
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
|
||||||
|
|
||||||
public class VerifyActivity extends XmppActivity implements ClipboardManager.OnPrimaryClipChangedListener, QuickConversationsService.OnVerification {
|
public class VerifyActivity extends XmppActivity implements ClipboardManager.OnPrimaryClipChangedListener, QuickConversationsService.OnVerification, QuickConversationsService.OnVerificationRequested {
|
||||||
|
|
||||||
|
public static final String EXTRA_RETRY_SMS_AFTER = "retry_sms_after";
|
||||||
|
|
||||||
private ActivityVerifyBinding binding;
|
private ActivityVerifyBinding binding;
|
||||||
private Account account;
|
private Account account;
|
||||||
|
@ -31,14 +39,43 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
private ClipboardManager clipboardManager;
|
private ClipboardManager clipboardManager;
|
||||||
private String pasted = null;
|
private String pasted = null;
|
||||||
private boolean verifying = false;
|
private boolean verifying = false;
|
||||||
|
private boolean requestingVerification = false;
|
||||||
|
private long retrySmsAfter = 0;
|
||||||
|
|
||||||
|
private final Handler mHandler = new Handler();
|
||||||
|
|
||||||
|
|
||||||
|
private final Runnable SMS_TIMEOUT_UPDATER = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (setTimeoutLabelInResendButton()) {
|
||||||
|
mHandler.postDelayed(this,300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private boolean setTimeoutLabelInResendButton() {
|
||||||
|
if (retrySmsAfter != 0) {
|
||||||
|
long remaining = retrySmsAfter - SystemClock.elapsedRealtime();
|
||||||
|
if (remaining >= 0) {
|
||||||
|
binding.resendSms.setEnabled(false);
|
||||||
|
binding.resendSms.setText(getString(R.string.resend_sms_in, TimeframeUtils.resolve(VerifyActivity.this,remaining)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.resendSms.setEnabled(true);
|
||||||
|
binding.resendSms.setText(R.string.resend_sms);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
String pin = savedInstanceState != null ? savedInstanceState.getString("pin") : null;
|
String pin = savedInstanceState != null ? savedInstanceState.getString("pin") : null;
|
||||||
boolean verifying = savedInstanceState != null && savedInstanceState.getBoolean("verifying");
|
boolean verifying = savedInstanceState != null && savedInstanceState.getBoolean("verifying");
|
||||||
|
boolean requestingVerification = savedInstanceState != null && savedInstanceState.getBoolean("requesting_verification", false);
|
||||||
this.pasted = savedInstanceState != null ? savedInstanceState.getString("pasted") : null;
|
this.pasted = savedInstanceState != null ? savedInstanceState.getString("pasted") : null;
|
||||||
|
this.retrySmsAfter = savedInstanceState != null ? savedInstanceState.getLong(EXTRA_RETRY_SMS_AFTER,0L) : 0L;
|
||||||
this.binding = DataBindingUtil.setContentView(this, R.layout.activity_verify);
|
this.binding = DataBindingUtil.setContentView(this, R.layout.activity_verify);
|
||||||
setSupportActionBar((Toolbar) this.binding.toolbar);
|
setSupportActionBar((Toolbar) this.binding.toolbar);
|
||||||
this.pinEntryWrapper = new PinEntryWrapper(binding.pinBox);
|
this.pinEntryWrapper = new PinEntryWrapper(binding.pinBox);
|
||||||
|
@ -47,8 +84,10 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
}
|
}
|
||||||
binding.back.setOnClickListener(this::onBackButton);
|
binding.back.setOnClickListener(this::onBackButton);
|
||||||
binding.next.setOnClickListener(this::onNextButton);
|
binding.next.setOnClickListener(this::onNextButton);
|
||||||
|
binding.resendSms.setOnClickListener(this::onResendSmsButton);
|
||||||
clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
setVerifyingState(verifying);
|
setVerifyingState(verifying);
|
||||||
|
setRequestingVerificationState(requestingVerification);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBackButton(View view) {
|
private void onBackButton(View view) {
|
||||||
|
@ -88,6 +127,15 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onResendSmsButton(View view) {
|
||||||
|
try {
|
||||||
|
xmppConnectionService.getQuickConversationsService().requestVerification(PhoneNumberUtilWrapper.toPhoneNumber(this, account.getJid()));
|
||||||
|
setRequestingVerificationState(true);
|
||||||
|
} catch (NumberParseException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setVerifyingState(boolean verifying) {
|
private void setVerifyingState(boolean verifying) {
|
||||||
this.verifying = verifying;
|
this.verifying = verifying;
|
||||||
this.binding.back.setText(verifying ? R.string.cancel : R.string.back);
|
this.binding.back.setText(verifying ? R.string.cancel : R.string.back);
|
||||||
|
@ -99,6 +147,17 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
this.binding.progressBar.setIndeterminate(verifying);
|
this.binding.progressBar.setIndeterminate(verifying);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setRequestingVerificationState(boolean requesting) {
|
||||||
|
this.requestingVerification = requesting;
|
||||||
|
if (requesting) {
|
||||||
|
this.binding.resendSms.setEnabled(false);
|
||||||
|
this.binding.resendSms.setText(R.string.requesting_sms);
|
||||||
|
} else {
|
||||||
|
setTimeoutLabelInResendButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void refreshUiReal() {
|
protected void refreshUiReal() {
|
||||||
|
|
||||||
|
@ -107,18 +166,22 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
@Override
|
@Override
|
||||||
void onBackendConnected() {
|
void onBackendConnected() {
|
||||||
xmppConnectionService.getQuickConversationsService().addOnVerificationListener(this);
|
xmppConnectionService.getQuickConversationsService().addOnVerificationListener(this);
|
||||||
|
xmppConnectionService.getQuickConversationsService().addOnVerificationRequestedListener(this);
|
||||||
this.account = AccountUtils.getFirst(xmppConnectionService);
|
this.account = AccountUtils.getFirst(xmppConnectionService);
|
||||||
if (this.account == null) {
|
if (this.account == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.binding.weHaveSent.setText(Html.fromHtml(getString(R.string.we_have_sent_you_an_sms, PhoneNumberUtilWrapper.prettyPhoneNumber(this, this.account.getJid()))));
|
this.binding.weHaveSent.setText(Html.fromHtml(getString(R.string.we_have_sent_you_an_sms_to_x, PhoneNumberUtilWrapper.toFormattedPhoneNumber(this, this.account.getJid()))));
|
||||||
setVerifyingState(xmppConnectionService.getQuickConversationsService().isVerifying());
|
setVerifyingState(xmppConnectionService.getQuickConversationsService().isVerifying());
|
||||||
|
setRequestingVerificationState(xmppConnectionService.getQuickConversationsService().isRequestingVerification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle savedInstanceState) {
|
public void onSaveInstanceState(Bundle savedInstanceState) {
|
||||||
savedInstanceState.putString("pin", this.pinEntryWrapper.getPin());
|
savedInstanceState.putString("pin", this.pinEntryWrapper.getPin());
|
||||||
savedInstanceState.putBoolean("verifying", this.verifying);
|
savedInstanceState.putBoolean("verifying", this.verifying);
|
||||||
|
savedInstanceState.putBoolean("requesting_verification", this.requestingVerification);
|
||||||
|
savedInstanceState.putLong(EXTRA_RETRY_SMS_AFTER, this.retrySmsAfter);
|
||||||
if (this.pasted != null) {
|
if (this.pasted != null) {
|
||||||
savedInstanceState.putString("pasted", this.pasted);
|
savedInstanceState.putString("pasted", this.pasted);
|
||||||
}
|
}
|
||||||
|
@ -129,14 +192,19 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
clipboardManager.addPrimaryClipChangedListener(this);
|
clipboardManager.addPrimaryClipChangedListener(this);
|
||||||
|
if (this.retrySmsAfter > 0) {
|
||||||
|
mHandler.post(SMS_TIMEOUT_UPDATER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
mHandler.removeCallbacks(SMS_TIMEOUT_UPDATER);
|
||||||
clipboardManager.removePrimaryClipChangedListener(this);
|
clipboardManager.removePrimaryClipChangedListener(this);
|
||||||
if (xmppConnectionService != null) {
|
if (xmppConnectionService != null) {
|
||||||
xmppConnectionService.getQuickConversationsService().removeOnVerificationListener(this);
|
xmppConnectionService.getQuickConversationsService().removeOnVerificationListener(this);
|
||||||
|
xmppConnectionService.getQuickConversationsService().removeOnVerificationRequestedListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,14 +242,49 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVerificationFailed() {
|
public void onVerificationFailed(int code) {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
setVerifyingState(false);
|
setVerifyingState(false);
|
||||||
});
|
});
|
||||||
|
Log.d(Config.LOGTAG,"code="+code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVerificationSucceeded() {
|
public void onVerificationSucceeded() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVerificationRetryAt(long timestamp) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//send sms again button callback
|
||||||
|
@Override
|
||||||
|
public void onVerificationRequestFailed(int code) {
|
||||||
|
runOnUiThread(()->{
|
||||||
|
setRequestingVerificationState(false);
|
||||||
|
});
|
||||||
|
Log.d(Config.LOGTAG,"code="+code);
|
||||||
|
}
|
||||||
|
|
||||||
|
//send sms again button callback
|
||||||
|
@Override
|
||||||
|
public void onVerificationRequested() {
|
||||||
|
runOnUiThread(()-> {
|
||||||
|
setRequestingVerificationState(false);
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setMessage(R.string.we_have_sent_you_the_sms_again);
|
||||||
|
builder.setPositiveButton(R.string.ok, null);
|
||||||
|
builder.create().show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVerificationRequestedRetryAt(long timestamp) {
|
||||||
|
this.retrySmsAfter = timestamp;
|
||||||
|
runOnUiThread(()-> setRequestingVerificationState(false));
|
||||||
|
mHandler.removeCallbacks(SMS_TIMEOUT_UPDATER);
|
||||||
|
runOnUiThread(SMS_TIMEOUT_UPDATER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,16 +41,18 @@ public class PhoneNumberUtilWrapper {
|
||||||
return locale.getCountry();
|
return locale.getCountry();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String prettyPhoneNumber(Context context, Jid jid) {
|
public static String toFormattedPhoneNumber(Context context, Jid jid) {
|
||||||
PhoneNumberUtil phoneNumberUtil = getInstance(context);
|
|
||||||
try {
|
try {
|
||||||
Phonenumber.PhoneNumber phoneNumber = phoneNumberUtil.parse(jid.getEscapedLocal(), "de");
|
return getInstance(context).format(toPhoneNumber(context, jid), PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);
|
||||||
return phoneNumberUtil.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return jid.getEscapedLocal();
|
return jid.getEscapedLocal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Phonenumber.PhoneNumber toPhoneNumber(Context context, Jid jid) throws NumberParseException {
|
||||||
|
return getInstance(context).parse(jid.getEscapedLocal(), "de");
|
||||||
|
}
|
||||||
|
|
||||||
public static String normalize(Context context, String number) throws NumberParseException {
|
public static String normalize(Context context, String number) throws NumberParseException {
|
||||||
return normalize(context, getInstance(context).parse(number, getUserCountry(context)));
|
return normalize(context, getInstance(context).parse(number, getUserCountry(context)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
android:id="@+id/we_have_sent"
|
android:id="@+id/we_have_sent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/we_have_sent_you_an_sms"
|
android:text="@string/we_have_sent_you_an_sms_to_x"
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Subhead" />
|
android:textAppearance="@style/TextAppearance.Conversations.Subhead" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
Loading…
Reference in a new issue