Prompt user to rate app

Closes #2841

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2015-03-31 12:34:49 -07:00
parent 0c7dba6d43
commit 0efdada928
4 changed files with 112 additions and 0 deletions

View File

@ -279,6 +279,13 @@
<string name="PassphrasePromptActivity_ok_button_content_description">Submit passphrase</string> <string name="PassphrasePromptActivity_ok_button_content_description">Submit passphrase</string>
<string name="PassphrasePromptActivity_invalid_passphrase_exclamation">Invalid passphrase!</string> <string name="PassphrasePromptActivity_invalid_passphrase_exclamation">Invalid passphrase!</string>
<!-- RatingManager -->
<string name="RatingManager_rate_this_app">Rate this app</string>
<string name="RatingManager_if_you_enjoy_using_this_app_please_take_a_moment">If you enjoy using this app, please take a moment to help us by rating it.</string>
<string name="RatingManager_rate_now">Rate now!</string>
<string name="RatingManager_no_thanks">No thanks</string>
<string name="RatingManager_later">Later</string>
<!-- ReceiveKeyActivity --> <!-- ReceiveKeyActivity -->
<string name="ReceiveKeyActivity_the_signature_on_this_key_exchange_is_different">The <string name="ReceiveKeyActivity_the_signature_on_this_key_exchange_is_different">The
signature on this key exchange is different than what you\'ve previously received from this signature on this key exchange is different than what you\'ve previously received from this

View File

@ -30,6 +30,7 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import org.thoughtcrime.securesms.components.RatingManager;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
@ -69,6 +70,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
initializeContactUpdatesReceiver(); initializeContactUpdatesReceiver();
DirectoryRefreshListener.schedule(this); DirectoryRefreshListener.schedule(this);
RatingManager.showRatingDialogIfNecessary(this);
} }
@Override @Override

View File

@ -0,0 +1,85 @@
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.util.Log;
import com.afollestad.materialdialogs.MaterialDialog;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.util.concurrent.TimeUnit;
public class RatingManager {
private static final int DAYS_SINCE_INSTALL_THRESHOLD = 7;
private static final int DAYS_UNTIL_REPROMPT_THRESHOLD = 4;
private static final String TAG = RatingManager.class.getSimpleName();
public static void showRatingDialogIfNecessary(Context context) {
if (!TextSecurePreferences.isRatingEnabled(context)) return;
long daysSinceInstall = getDaysSinceInstalled(context);
long laterTimestamp = TextSecurePreferences.getRatingLaterTimestamp(context);
if (daysSinceInstall >= DAYS_SINCE_INSTALL_THRESHOLD &&
System.currentTimeMillis() >= laterTimestamp)
{
showRatingDialog(context);
}
}
private static void showRatingDialog(final Context context) {
new MaterialDialog.Builder(context)
.title(context.getString(R.string.RatingManager_rate_this_app))
.content(context.getString(R.string.RatingManager_if_you_enjoy_using_this_app_please_take_a_moment))
.positiveText(context.getString(R.string.RatingManager_rate_now))
.negativeText(context.getString(R.string.RatingManager_no_thanks))
.neutralText(context.getString(R.string.RatingManager_later))
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
TextSecurePreferences.setRatingEnabled(context, false);
startPlayStore(context);
super.onPositive(dialog);
}
@Override
public void onNegative(MaterialDialog dialog) {
TextSecurePreferences.setRatingEnabled(context, false);
super.onNegative(dialog);
}
@Override
public void onNeutral(MaterialDialog dialog) {
long waitUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(DAYS_UNTIL_REPROMPT_THRESHOLD);
TextSecurePreferences.setRatingLaterTimestamp(context, waitUntil);
super.onNeutral(dialog);
}
})
.show();
}
private static void startPlayStore(Context context) {
Uri uri = Uri.parse("market://details?id=" + context.getPackageName());
context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
}
private static long getDaysSinceInstalled(Context context) {
try {
long installTimestamp = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0)
.firstInstallTime;
return TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - installTimestamp);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, e);
return 0;
}
}
}

View File

@ -66,9 +66,27 @@ public class TextSecurePreferences {
private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id"; private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version"; private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
private static final String WEBSOCKET_REGISTERED_PREF = "pref_websocket_registered"; private static final String WEBSOCKET_REGISTERED_PREF = "pref_websocket_registered";
private static final String RATING_LATER_PREF = "pref_rating_later";
private static final String RATING_ENABLED_PREF = "pref_rating_enabled";
public static final String REPEAT_ALERTS_PREF = "pref_repeat_alerts"; public static final String REPEAT_ALERTS_PREF = "pref_repeat_alerts";
public static long getRatingLaterTimestamp(Context context) {
return getLongPreference(context, RATING_LATER_PREF, 0);
}
public static void setRatingLaterTimestamp(Context context, long timestamp) {
setLongPreference(context, RATING_LATER_PREF, timestamp);
}
public static boolean isRatingEnabled(Context context) {
return getBooleanPreference(context, RATING_ENABLED_PREF, true);
}
public static void setRatingEnabled(Context context, boolean enabled) {
setBooleanPreference(context, RATING_ENABLED_PREF, enabled);
}
public static boolean isWebsocketRegistered(Context context) { public static boolean isWebsocketRegistered(Context context) {
return getBooleanPreference(context, WEBSOCKET_REGISTERED_PREF, false); return getBooleanPreference(context, WEBSOCKET_REGISTERED_PREF, false);
} }