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 New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch