added dialogs for rate limiting and out of date version
This commit is contained in:
parent
584cf43b3d
commit
52ecd9347c
|
@ -104,7 +104,7 @@ android {
|
|||
quick {
|
||||
dimension "mode"
|
||||
applicationId = "im.conversations.quick"
|
||||
resValue "string", "app_name", "Quick Conversations"
|
||||
resValue "string", "app_name", "Quicksy"
|
||||
resValue "string", "applicationId", applicationId
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,11 @@ public abstract class AbstractGenerator {
|
|||
}
|
||||
|
||||
public String getIdentityName() {
|
||||
return mXmppConnectionService.getString(R.string.app_name) + " " + getIdentityVersion();
|
||||
return mXmppConnectionService.getString(R.string.app_name) + ' ' + getIdentityVersion();
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
return mXmppConnectionService.getString(R.string.app_name) + '/' + getIdentityVersion();
|
||||
}
|
||||
|
||||
String getIdentityType() {
|
||||
|
|
|
@ -288,7 +288,7 @@ public class HttpDownloadConnection implements Transferable {
|
|||
}
|
||||
connection.setUseCaches(false);
|
||||
Log.d(Config.LOGTAG, "url: " + connection.getURL().toString());
|
||||
connection.setRequestProperty("User-Agent", mXmppConnectionService.getIqGenerator().getIdentityName());
|
||||
connection.setRequestProperty("User-Agent", mXmppConnectionService.getIqGenerator().getUserAgent());
|
||||
if (connection instanceof HttpsURLConnection) {
|
||||
mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive);
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ public class HttpDownloadConnection implements Transferable {
|
|||
mHttpConnectionManager.setupTrustManager((HttpsURLConnection) connection, interactive);
|
||||
}
|
||||
connection.setUseCaches(false);
|
||||
connection.setRequestProperty("User-Agent", mXmppConnectionService.getIqGenerator().getIdentityName());
|
||||
connection.setRequestProperty("User-Agent", mXmppConnectionService.getIqGenerator().getUserAgent());
|
||||
final boolean tryResume = file.exists() && file.getKey() == null && file.getSize() > 0;
|
||||
long resumeSize = 0;
|
||||
long expected = file.getExpectedSize();
|
||||
|
|
|
@ -166,7 +166,7 @@ public class HttpUploadConnection implements Transferable {
|
|||
connection.setUseCaches(false);
|
||||
connection.setRequestMethod("PUT");
|
||||
connection.setFixedLengthStreamingMode(expectedFileSize);
|
||||
connection.setRequestProperty("User-Agent",mXmppConnectionService.getIqGenerator().getIdentityName());
|
||||
connection.setRequestProperty("User-Agent",mXmppConnectionService.getIqGenerator().getUserAgent());
|
||||
if(slot.getHeaders() != null) {
|
||||
for(HashMap.Entry<String,String> entry : slot.getHeaders().entrySet()) {
|
||||
connection.setRequestProperty(entry.getKey(),entry.getValue());
|
||||
|
|
|
@ -754,7 +754,7 @@
|
|||
<string name="choose_a_country">Choose a country</string>
|
||||
<string name="phone_number">phone number</string>
|
||||
<string name="verify_your_phone_number">Verify your phone number</string>
|
||||
<string name="enter_country_code_and_phone_number">Quick Conversations will send an SMS message (carrier charges may apply) to verify your phone number. Enter your country code and phone number:</string>
|
||||
<string name="enter_country_code_and_phone_number">Quicksy will send an SMS message (carrier charges may apply) to verify your phone number. Enter your country code and phone number:</string>
|
||||
<string name="we_will_be_verifying"><![CDATA[We will be verifying the phone number<br/><br/><b>%s</b><br/><br/>Is this OK, or would you like to edit the number?]]></string>
|
||||
<string name="not_a_valid_phone_number">%s is not a valid phone number.</string>
|
||||
<string name="please_enter_your_phone_number">Please enter your phone number.</string>
|
||||
|
@ -783,4 +783,9 @@
|
|||
<string name="invalid_user_input">Invalid user input</string>
|
||||
<string name="temporarily_unavailable">Temporarily unavailable. Try again later.</string>
|
||||
<string name="no_network_connection">No network connection.</string>
|
||||
<string name="try_again_in_x">Please try again in %s</string>
|
||||
<string name="rate_limited">You are rate limited</string>
|
||||
<string name="too_many_attempts">Too many attempts</string>
|
||||
<string name="the_app_is_out_of_date">You are using an out of date version of this app.</string>
|
||||
<string name="update">Update</string>
|
||||
</resources>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package eu.siacs.conversations.services;
|
||||
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
|
@ -10,11 +12,12 @@ 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.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
@ -40,6 +43,8 @@ public class QuickConversationsService {
|
|||
|
||||
private static final String BASE_URL = "http://venus.fritz.box:4567";
|
||||
|
||||
private static final String INSTALLATION_ID = "eu.siacs.conversations.installation-id";
|
||||
|
||||
private final XmppConnectionService service;
|
||||
|
||||
private final Set<OnVerificationRequested> mOnVerificationRequested = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
|
@ -78,14 +83,6 @@ public class QuickConversationsService {
|
|||
|
||||
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 {
|
||||
|
@ -96,6 +93,7 @@ public class QuickConversationsService {
|
|||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setConnectTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||
connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||
setHeader(connection);
|
||||
final int code = connection.getResponseCode();
|
||||
if (code == 200) {
|
||||
createAccountAndWait(phoneNumber, 0L);
|
||||
|
@ -150,16 +148,6 @@ public class QuickConversationsService {
|
|||
}
|
||||
|
||||
public void verify(final 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)) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
|
@ -172,6 +160,7 @@ public class QuickConversationsService {
|
|||
connection.setReadTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", Plain.getMessage(account.getUsername(), pin));
|
||||
setHeader(connection);
|
||||
final OutputStream os = connection.getOutputStream();
|
||||
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
|
||||
writer.write(account.getPassword());
|
||||
|
@ -217,6 +206,25 @@ public class QuickConversationsService {
|
|||
}
|
||||
}
|
||||
|
||||
private void setHeader(HttpURLConnection connection) {
|
||||
connection.setRequestProperty("User-Agent", service.getIqGenerator().getUserAgent());
|
||||
connection.setRequestProperty("Installation-Id", getInstallationId());
|
||||
connection.setRequestProperty("Accept-Language", Locale.getDefault().getLanguage());
|
||||
}
|
||||
|
||||
private String getInstallationId() {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(service);
|
||||
String id = preferences.getString(INSTALLATION_ID, null);
|
||||
if (id != null) {
|
||||
return id;
|
||||
} else {
|
||||
id = UUID.randomUUID().toString();
|
||||
preferences.edit().putString(INSTALLATION_ID, id).apply();
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getApiErrorCode(Exception e) {
|
||||
if (!service.hasInternetConnection()) {
|
||||
return API_ERROR_AIRPLANE_MODE;
|
||||
|
@ -227,7 +235,7 @@ public class QuickConversationsService {
|
|||
} else if (e instanceof SSLHandshakeException) {
|
||||
return API_ERROR_SSL_HANDSHAKE;
|
||||
} else {
|
||||
Log.d(Config.LOGTAG,e.getClass().getName());
|
||||
Log.d(Config.LOGTAG, e.getClass().getName());
|
||||
return API_ERROR_OTHER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,23 +4,20 @@ import android.app.AlertDialog;
|
|||
import android.content.Intent;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.databinding.ActivityEnterNumberBinding;
|
||||
import eu.siacs.conversations.services.QuickConversationsService;
|
||||
import eu.siacs.conversations.ui.drawable.TextDrawable;
|
||||
import eu.siacs.conversations.ui.util.ApiErrorDialogHelper;
|
||||
import eu.siacs.conversations.ui.util.ApiDialogHelper;
|
||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||
import io.michaelrocks.libphonenumber.android.NumberParseException;
|
||||
import io.michaelrocks.libphonenumber.android.PhoneNumberUtil;
|
||||
|
@ -180,7 +177,7 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
|
|||
public void onVerificationRequestFailed(int code) {
|
||||
runOnUiThread(() -> {
|
||||
setRequestingVerificationState(false);
|
||||
ApiErrorDialogHelper.create(this, code).show();
|
||||
ApiDialogHelper.createError(this, code).show();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import eu.siacs.conversations.R;
|
|||
import eu.siacs.conversations.databinding.ActivityVerifyBinding;
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.services.QuickConversationsService;
|
||||
import eu.siacs.conversations.ui.util.ApiErrorDialogHelper;
|
||||
import eu.siacs.conversations.ui.util.ApiDialogHelper;
|
||||
import eu.siacs.conversations.ui.util.PinEntryWrapper;
|
||||
import eu.siacs.conversations.utils.AccountUtils;
|
||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||
|
@ -286,7 +286,7 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
|||
builder.setPositiveButton(R.string.ok, null);
|
||||
builder.create().show();
|
||||
} else {
|
||||
ApiErrorDialogHelper.create(this, code).show();
|
||||
ApiDialogHelper.createError(this, code).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -299,7 +299,10 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
|||
@Override
|
||||
public void onVerificationRetryAt(long timestamp) {
|
||||
this.retryVerificationAfter = timestamp;
|
||||
runOnUiThread(() -> setVerifyingState(false));
|
||||
runOnUiThread(() -> {
|
||||
ApiDialogHelper.createTooManyAttempts(this).show();
|
||||
setVerifyingState(false);
|
||||
});
|
||||
mHandler.removeCallbacks(VERIFICATION_TIMEOUT_UPDATER);
|
||||
runOnUiThread(VERIFICATION_TIMEOUT_UPDATER);
|
||||
}
|
||||
|
@ -309,7 +312,7 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
|||
public void onVerificationRequestFailed(int code) {
|
||||
runOnUiThread(() -> {
|
||||
setRequestingVerificationState(false);
|
||||
ApiErrorDialogHelper.create(this, code).show();
|
||||
ApiDialogHelper.createError(this, code).show();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -328,7 +331,10 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP
|
|||
@Override
|
||||
public void onVerificationRequestedRetryAt(long timestamp) {
|
||||
this.retrySmsAfter = timestamp;
|
||||
runOnUiThread(() -> setRequestingVerificationState(false));
|
||||
runOnUiThread(() -> {
|
||||
ApiDialogHelper.createRateLimited(this, timestamp).show();
|
||||
setRequestingVerificationState(false);
|
||||
});
|
||||
mHandler.removeCallbacks(SMS_TIMEOUT_UPDATER);
|
||||
runOnUiThread(SMS_TIMEOUT_UPDATER);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package eu.siacs.conversations.ui.util;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.services.QuickConversationsService;
|
||||
import eu.siacs.conversations.utils.TimeframeUtils;
|
||||
|
||||
public class ApiDialogHelper {
|
||||
|
||||
public static Dialog createError(final Context context, final int code) {
|
||||
@StringRes final int res;
|
||||
switch (code) {
|
||||
case QuickConversationsService.API_ERROR_AIRPLANE_MODE:
|
||||
res = R.string.no_network_connection;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_OTHER:
|
||||
res = R.string.unknown_api_error_network;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_CONNECT:
|
||||
res = R.string.unable_to_connect_to_server;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_SSL_HANDSHAKE:
|
||||
res = R.string.unable_to_establish_secure_connection;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_UNKNOWN_HOST:
|
||||
res = R.string.unable_to_find_server;
|
||||
break;
|
||||
case 400:
|
||||
res = R.string.invalid_user_input;
|
||||
break;
|
||||
case 403:
|
||||
res = R.string.the_app_is_out_of_date;
|
||||
break;
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
res = R.string.temporarily_unavailable;
|
||||
break;
|
||||
default:
|
||||
res = R.string.unknown_api_error_response;
|
||||
}
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage(res);
|
||||
if (code == 403 && resolvable(context, getMarketViewIntent(context))) {
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setPositiveButton(R.string.update, (dialog, which) -> context.startActivity(getMarketViewIntent(context)));
|
||||
} else {
|
||||
builder.setPositiveButton(R.string.ok, null);
|
||||
}
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
public static Dialog createRateLimited(final Context context, final long timestamp) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.rate_limited);
|
||||
builder.setMessage(context.getString(R.string.try_again_in_x, TimeframeUtils.resolve(context, timestamp - SystemClock.elapsedRealtime())));
|
||||
builder.setPositiveButton(R.string.ok, null);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
public static Dialog createTooManyAttempts(final Context context) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage(R.string.too_many_attempts);
|
||||
builder.setPositiveButton(R.string.ok, null);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private static Intent getMarketViewIntent(Context context) {
|
||||
return new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName()));
|
||||
}
|
||||
|
||||
private static boolean resolvable(Context context, Intent intent) {
|
||||
return context.getPackageManager().queryIntentActivities(intent, 0).size() > 0;
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package eu.siacs.conversations.ui.util;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.services.QuickConversationsService;
|
||||
|
||||
public class ApiErrorDialogHelper {
|
||||
|
||||
public static Dialog create(Context context, int code) {
|
||||
@StringRes final int res;
|
||||
switch (code) {
|
||||
case QuickConversationsService.API_ERROR_AIRPLANE_MODE:
|
||||
res = R.string.no_network_connection;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_OTHER:
|
||||
res = R.string.unknown_api_error_network;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_CONNECT:
|
||||
res = R.string.unable_to_connect_to_server;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_SSL_HANDSHAKE:
|
||||
res = R.string.unable_to_establish_secure_connection;
|
||||
break;
|
||||
case QuickConversationsService.API_ERROR_UNKNOWN_HOST:
|
||||
res = R.string.unable_to_find_server;
|
||||
break;
|
||||
case 400:
|
||||
res = R.string.invalid_user_input;
|
||||
break;
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
res = R.string.temporarily_unavailable;
|
||||
break;
|
||||
default:
|
||||
res = R.string.unknown_api_error_response;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage(res);
|
||||
builder.setPositiveButton(R.string.ok, null);
|
||||
return builder.create();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue