From aad5b21f0f22a06e2051e65b9c5ea4a2fafcd110 Mon Sep 17 00:00:00 2001 From: bdonahue Date: Thu, 9 Jan 2014 14:51:03 -0500 Subject: [PATCH 1/9] Adding gradle support so the project can be used with Android Studio --- .gitignore | 17 +++ AppRate/.classpath | 17 +-- AppRate/build.gradle | 34 +++++ AppRateSample/.classpath | 17 +-- AppRateSample/AndroidManifest.xml | 2 +- AppRateSample/build.gradle | 35 +++++ build.gradle | 13 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 50508 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++++++++++++++++++++++ gradlew.bat | 90 +++++++++++++ settings.gradle | 2 + 12 files changed, 380 insertions(+), 17 deletions(-) create mode 100644 .gitignore create mode 100644 AppRate/build.gradle create mode 100644 AppRateSample/build.gradle create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f1efd4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +bin +gen +*.apk +.hg/ +local.properties +*.DS_Store +*.BridgeSort +out/ +tmp/ +build/ +.gradle/ +.idea/ +*.iml +.project +.classpath +*.pem +mirror/ diff --git a/AppRate/.classpath b/AppRate/.classpath index a662f00..d57ec02 100644 --- a/AppRate/.classpath +++ b/AppRate/.classpath @@ -1,8 +1,9 @@ - - - - - - - - + + + + + + + + + diff --git a/AppRate/build.gradle b/AppRate/build.gradle new file mode 100644 index 0000000..3832df7 --- /dev/null +++ b/AppRate/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'android-library' + +dependencies { + compile fileTree(dir: 'libs', include: '*.jar') +} + +android { + compileSdkVersion 17 + buildToolsVersion "18.1.0" + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + resources.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['assets'] + } + + // Move the tests to tests/java, tests/res, etc... + instrumentTest.setRoot('tests') + + // Move the build types to build-types/ + // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... + // This moves them out of them default location under src//... which would + // conflict with src/ being used by the main source set. + // Adding new build types or product flavors should be accompanied + // by a similar customization. + debug.setRoot('build-types/debug') + release.setRoot('build-types/release') + } +} diff --git a/AppRateSample/.classpath b/AppRateSample/.classpath index a662f00..d57ec02 100644 --- a/AppRateSample/.classpath +++ b/AppRateSample/.classpath @@ -1,8 +1,9 @@ - - - - - - - - + + + + + + + + + diff --git a/AppRateSample/AndroidManifest.xml b/AppRateSample/AndroidManifest.xml index be8a123..9210e61 100644 --- a/AppRateSample/AndroidManifest.xml +++ b/AppRateSample/AndroidManifest.xml @@ -5,7 +5,7 @@ + android:targetSdkVersion="17" /> diff --git a/AppRateSample/build.gradle b/AppRateSample/build.gradle new file mode 100644 index 0000000..202406d --- /dev/null +++ b/AppRateSample/build.gradle @@ -0,0 +1,35 @@ +apply plugin: 'android' + +dependencies { + compile fileTree(dir: 'libs', include: '*.jar') + compile project(':AppRate') +} + +android { + compileSdkVersion 16 + buildToolsVersion "18.1.0" + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + resources.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['assets'] + } + + // Move the tests to tests/java, tests/res, etc... + instrumentTest.setRoot('tests') + + // Move the build types to build-types/ + // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... + // This moves them out of them default location under src//... which would + // conflict with src/ being used by the main source set. + // Adding new build types or product flavors should be accompanied + // by a similar customization. + debug.setRoot('build-types/debug') + release.setRoot('build-types/release') + } +} diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..dcaed5d --- /dev/null +++ b/build.gradle @@ -0,0 +1,13 @@ +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:0.7.+' + } +} + +task wrapper(type: Wrapper) { + gradleVersion = '1.9' +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..d5c591c9c532da774b062aa6d7ab16405ff8700a GIT binary patch literal 50508 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%0DD3;W?!&t=FUIvF}Y7;NYDq6$vu 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..59ff32c --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +include ':AppRate' +include ':AppRateSample' From c3cd64a3427affc92ec50e7cbcc133b0df78032e Mon Sep 17 00:00:00 2001 From: bdonahue Date: Thu, 9 Jan 2014 16:03:40 -0500 Subject: [PATCH 2/9] General cleanup of the code and getting it to follow Google's Android developement standards --- AppRate/res/values/strings.xml | 7 + AppRate/src/com/tjeannin/apprate/AppRate.java | 503 +++++++++--------- .../tjeannin/apprate/ExceptionHandler.java | 29 +- 3 files changed, 273 insertions(+), 266 deletions(-) diff --git a/AppRate/res/values/strings.xml b/AppRate/res/values/strings.xml index 8add2c1..1bced83 100644 --- a/AppRate/res/values/strings.xml +++ b/AppRate/res/values/strings.xml @@ -1,5 +1,12 @@ AppRate + Rate %1$s + "If you enjoy using %1$s, please take a moment to rate it. Thanks for your support!" + Rate it! + Remind me later + No thanks + No Play Store installed on device + (unknown) \ No newline at end of file diff --git a/AppRate/src/com/tjeannin/apprate/AppRate.java b/AppRate/src/com/tjeannin/apprate/AppRate.java index 1ee8b3a..e423da8 100644 --- a/AppRate/src/com/tjeannin/apprate/AppRate.java +++ b/AppRate/src/com/tjeannin/apprate/AppRate.java @@ -1,7 +1,5 @@ package com.tjeannin.apprate; -import java.lang.Thread.UncaughtExceptionHandler; - import android.app.Activity; import android.app.AlertDialog; import android.content.ActivityNotFoundException; @@ -20,255 +18,258 @@ import android.util.Log; import android.widget.Toast; +import java.lang.Thread.UncaughtExceptionHandler; + public class AppRate implements android.content.DialogInterface.OnClickListener, OnCancelListener { - private static final String TAG = "AppRater"; - - private Activity hostActivity; - private OnClickListener clickListener; - private SharedPreferences preferences; - private AlertDialog.Builder dialogBuilder = null; - - private long minLaunchesUntilPrompt = 0; - private long minDaysUntilPrompt = 0; - - private boolean showIfHasCrashed = true; - - - public AppRate(Activity hostActivity) { - this.hostActivity = hostActivity; - preferences = hostActivity.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, 0); - } - - /** - * @param minLaunchesUntilPrompt The minimum number of times the user lunches the application before showing the rate dialog.
- * Default value is 0 times. - * @return This {@link AppRate} object to allow chaining. - */ - public AppRate setMinLaunchesUntilPrompt(long minLaunchesUntilPrompt) { - this.minLaunchesUntilPrompt = minLaunchesUntilPrompt; - return this; - } - - /** - * @param minDaysUntilPrompt The minimum number of days before showing the rate dialog.
- * Default value is 0 days. - * @return This {@link AppRate} object to allow chaining. - */ - public AppRate setMinDaysUntilPrompt(long minDaysUntilPrompt) { - this.minDaysUntilPrompt = minDaysUntilPrompt; - return this; - } - - /** - * @param showIfCrash If false the rate dialog will not be shown if the application has crashed once.
- * Default value is false. - * @return This {@link AppRate} object to allow chaining. - */ - public AppRate setShowIfAppHasCrashed(boolean showIfCrash) { - showIfHasCrashed = showIfCrash; - return this; - } - - /** - * Use this method if you want to customize the style and content of the rate dialog.
- * When using the {@link AlertDialog.Builder} you should use: - *
    - *
  • {@link AlertDialog.Builder#setPositiveButton} for the rate button.
  • - *
  • {@link AlertDialog.Builder#setNeutralButton} for the rate later button.
  • - *
  • {@link AlertDialog.Builder#setNegativeButton} for the never rate button.
  • - *
- * @param customBuilder The custom dialog you want to use as the rate dialog. - * @return This {@link AppRate} object to allow chaining. - */ - public AppRate setCustomDialog(AlertDialog.Builder customBuilder) { - dialogBuilder = customBuilder; - return this; - } - - /** - * Reset all the data collected about number of launches and days until first launch. - * @param context A context. - */ - public static void reset(Context context) { - context.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, 0).edit().clear().commit(); - Log.d(TAG, "Cleared AppRate shared preferences."); - } - - /** - * Display the rate dialog if needed. - */ - public void init() { - - Log.d(TAG, "Init AppRate"); - - if (preferences.getBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, false) || ( - preferences.getBoolean(PrefsContract.PREF_APP_HAS_CRASHED, false) && !showIfHasCrashed)) { - return; - } - - if (!showIfHasCrashed) { - initExceptionHandler(); - } - - Editor editor = preferences.edit(); - - // Get and increment launch counter. - long launch_count = preferences.getLong(PrefsContract.PREF_LAUNCH_COUNT, 0) + 1; - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, launch_count); - - // Get date of first launch. - Long date_firstLaunch = preferences.getLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, 0); - if (date_firstLaunch == 0) { - date_firstLaunch = System.currentTimeMillis(); - editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, date_firstLaunch); - } - - // Show the rate dialog if needed. - if (launch_count >= minLaunchesUntilPrompt) { - if (System.currentTimeMillis() >= date_firstLaunch + (minDaysUntilPrompt * DateUtils.DAY_IN_MILLIS)) { - - if (dialogBuilder != null) { - showDialog(dialogBuilder); - } else { - showDefaultDialog(); - } - } - } - - editor.commit(); - } - - /** - * Initialize the {@link ExceptionHandler}. - */ - private void initExceptionHandler() { - - Log.d(TAG, "Init AppRate ExceptionHandler"); - - UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler(); - - // Don't register again if already registered. - if (!(currentHandler instanceof ExceptionHandler)) { - - // Register default exceptions handler. - Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(currentHandler, hostActivity)); - } - } - - /** - * Shows the default rate dialog. - * @return - */ - private void showDefaultDialog() { - - Log.d(TAG, "Create default dialog."); - - String title = "Rate " + getApplicationName(hostActivity.getApplicationContext()); - String message = "If you enjoy using " + getApplicationName(hostActivity.getApplicationContext()) + ", please take a moment to rate it. Thanks for your support!"; - String rate = "Rate it !"; - String remindLater = "Remind me later"; - String dismiss = "No thanks"; - - new AlertDialog.Builder(hostActivity) - .setTitle(title) - .setMessage(message) - .setPositiveButton(rate, this) - .setNegativeButton(dismiss, this) - .setNeutralButton(remindLater, this) - .setOnCancelListener(this) - .create().show(); - } - - /** - * Show the custom rate dialog. - * @return - */ - private void showDialog(AlertDialog.Builder builder) { - - Log.d(TAG, "Create custom dialog."); - - AlertDialog dialog = builder.create(); - dialog.show(); - - String rate = (String) dialog.getButton(AlertDialog.BUTTON_POSITIVE).getText(); - String remindLater = (String) dialog.getButton(AlertDialog.BUTTON_NEUTRAL).getText(); - String dismiss = (String) dialog.getButton(AlertDialog.BUTTON_NEGATIVE).getText(); - - dialog.setButton(AlertDialog.BUTTON_POSITIVE, rate, this); - dialog.setButton(AlertDialog.BUTTON_NEUTRAL, remindLater, this); - dialog.setButton(AlertDialog.BUTTON_NEGATIVE, dismiss, this); - - dialog.setOnCancelListener(this); - } - - @Override - public void onCancel(DialogInterface dialog) { - - Editor editor = preferences.edit(); - editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); - editor.commit(); - } - - /** - * @param onClickListener A listener to be called back on. - * @return This {@link AppRate} object to allow chaining. - */ - public AppRate setOnClickListener(OnClickListener onClickListener){ - clickListener = onClickListener; - return this; - } - - @Override - public void onClick(DialogInterface dialog, int which) { - - Editor editor = preferences.edit(); - - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - try - { - hostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + hostActivity.getPackageName()))); - }catch (ActivityNotFoundException e) { - Toast.makeText(hostActivity, "No Play Store installed on device", Toast.LENGTH_SHORT).show(); - } - editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); - break; - - case DialogInterface.BUTTON_NEGATIVE: - editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); - break; - - case DialogInterface.BUTTON_NEUTRAL: - editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); - break; - - default: - break; - } - - editor.commit(); - dialog.dismiss(); - - if(clickListener != null){ - clickListener.onClick(dialog, which); - } - } - - /** - * @param context A context of the current application. - * @return The application name of the current application. - */ - private static final String getApplicationName(Context context) { - final PackageManager packageManager = context.getPackageManager(); - ApplicationInfo applicationInfo; - try { - applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); - } catch (final NameNotFoundException e) { - applicationInfo = null; - } - return (String) (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "(unknown)"); - } + private static final String TAG = "AppRater"; + + private Activity mHostActivity; + + private OnClickListener mClickListener; + + private SharedPreferences mPreferences; + + private AlertDialog.Builder mDialogBuilder = null; + + private long mMinLaunchesUntilPrompt = 0; + + private long mMinDaysUntilPrompt = 0; + + private boolean mShowIfHasCrashed = true; + + public AppRate(Activity hostActivity) { + mHostActivity = hostActivity; + mPreferences = hostActivity.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, Context.MODE_PRIVATE); + } + + /** + * @param minLaunchesUntilPrompt The minimum number of times the user lunches the application before showing the rate dialog.
+ * Default value is 0 times. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setMinLaunchesUntilPrompt(long minLaunchesUntilPrompt) { + mMinLaunchesUntilPrompt = minLaunchesUntilPrompt; + return this; + } + + /** + * @param minDaysUntilPrompt The minimum number of days before showing the rate dialog.
+ * Default value is 0 days. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setMinDaysUntilPrompt(long minDaysUntilPrompt) { + mMinDaysUntilPrompt = minDaysUntilPrompt; + return this; + } + + /** + * @param showIfCrash If false the rate dialog will not be shown if the application has crashed once.
+ * Default value is false. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setShowIfAppHasCrashed(boolean showIfCrash) { + mShowIfHasCrashed = showIfCrash; + return this; + } + + /** + * Use this method if you want to customize the style and content of the rate dialog.
+ * When using the {@link AlertDialog.Builder} you should use: + *
    + *
  • {@link AlertDialog.Builder#setPositiveButton} for the rate button.
  • + *
  • {@link AlertDialog.Builder#setNeutralButton} for the rate later button.
  • + *
  • {@link AlertDialog.Builder#setNegativeButton} for the never rate button.
  • + *
+ * + * @param customBuilder The custom dialog you want to use as the rate dialog. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setCustomDialog(AlertDialog.Builder customBuilder) { + mDialogBuilder = customBuilder; + return this; + } + + /** + * Reset all the data collected about number of launches and days until first launch. + * + * @param context A context. + */ + public static void reset(Context context) { + context.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, Context.MODE_PRIVATE).edit().clear().commit(); + Log.d(TAG, "Cleared AppRate shared preferences."); + } + + /** + * Display the rate dialog if needed. + */ + public void init() { + Log.d(TAG, "Init AppRate"); + + if (mPreferences.getBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, false) || ( + mPreferences.getBoolean(PrefsContract.PREF_APP_HAS_CRASHED, false) && !mShowIfHasCrashed)) { + return; + } + + if (!mShowIfHasCrashed) { + initExceptionHandler(); + } + + Editor editor = mPreferences.edit(); + + // Get and increment launch counter. + long launch_count = mPreferences.getLong(PrefsContract.PREF_LAUNCH_COUNT, Context.MODE_PRIVATE) + 1; + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, launch_count); + + // Get date of first launch. + Long date_firstLaunch = mPreferences.getLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, Context.MODE_PRIVATE); + if (date_firstLaunch == 0) { + date_firstLaunch = System.currentTimeMillis(); + editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, date_firstLaunch); + } + + // Show the rate dialog if needed. + if (launch_count >= mMinLaunchesUntilPrompt) { + if (System.currentTimeMillis() >= date_firstLaunch + (mMinDaysUntilPrompt * DateUtils.DAY_IN_MILLIS)) { + + if (mDialogBuilder != null) { + showDialog(mDialogBuilder); + } else { + showDefaultDialog(); + } + } + } + + editor.commit(); + } + + /** + * Initialize the {@link ExceptionHandler}. + */ + private void initExceptionHandler() { + Log.d(TAG, "Init AppRate ExceptionHandler"); + + UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler(); + + // Don't register again if already registered. + if (!(currentHandler instanceof ExceptionHandler)) { + // Register default exceptions handler. + Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(currentHandler, mHostActivity)); + } + } + + /** + * Shows the default rate dialog. + * + * @return + */ + private void showDefaultDialog() { + Log.d(TAG, "Create default dialog."); + + String title = mHostActivity.getString(R.string.dialog_title, getApplicationName(mHostActivity.getApplicationContext())); + String message = mHostActivity.getString(R.string.dialog_message, getApplicationName(mHostActivity.getApplicationContext())); + String rate = mHostActivity.getString(R.string.dialog_positive_button); + String remindLater = mHostActivity.getString(R.string.dialog_neutral_button); + String dismiss = mHostActivity.getString(R.string.dialog_negative_button); + + new AlertDialog.Builder(mHostActivity) + .setTitle(title) + .setMessage(message) + .setPositiveButton(rate, this) + .setNegativeButton(dismiss, this) + .setNeutralButton(remindLater, this) + .setOnCancelListener(this) + .create().show(); + } + + /** + * Show the custom rate dialog. + * + * @return + */ + private void showDialog(AlertDialog.Builder builder) { + Log.d(TAG, "Create custom dialog."); + + AlertDialog dialog = builder.create(); + dialog.show(); + + String rate = (String) dialog.getButton(AlertDialog.BUTTON_POSITIVE).getText(); + String remindLater = (String) dialog.getButton(AlertDialog.BUTTON_NEUTRAL).getText(); + String dismiss = (String) dialog.getButton(AlertDialog.BUTTON_NEGATIVE).getText(); + + dialog.setButton(AlertDialog.BUTTON_POSITIVE, rate, this); + dialog.setButton(AlertDialog.BUTTON_NEUTRAL, remindLater, this); + dialog.setButton(AlertDialog.BUTTON_NEGATIVE, dismiss, this); + + dialog.setOnCancelListener(this); + } + + @Override + public void onCancel(DialogInterface dialog) { + Editor editor = mPreferences.edit(); + editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, Context.MODE_PRIVATE); + editor.commit(); + } + + /** + * @param onClickListener A listener to be called back on. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setOnClickListener(OnClickListener onClickListener) { + mClickListener = onClickListener; + return this; + } + + @Override + public void onClick(DialogInterface dialog, int which) { + Editor editor = mPreferences.edit(); + + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + try { + mHostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + mHostActivity.getPackageName()))); + } catch (ActivityNotFoundException e) { + Toast.makeText(mHostActivity, mHostActivity.getString(R.string.toast_play_store_missing_error), Toast.LENGTH_SHORT).show(); + } + editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); + break; + + case DialogInterface.BUTTON_NEGATIVE: + editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); + break; + + case DialogInterface.BUTTON_NEUTRAL: + editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, Context.MODE_PRIVATE); + break; + + default: + break; + } + + editor.commit(); + dialog.dismiss(); + + if (mClickListener != null) { + mClickListener.onClick(dialog, which); + } + } + + /** + * @param context A context of the current application. + * @return The application name of the current application. + */ + private static final String getApplicationName(Context context) { + final PackageManager packageManager = context.getPackageManager(); + ApplicationInfo applicationInfo; + + try { + applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), Context.MODE_PRIVATE); + } catch (final NameNotFoundException e) { + applicationInfo = null; + } + + return (String) (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : context.getString(R.string.application_name_unknown)); + } } \ No newline at end of file diff --git a/AppRate/src/com/tjeannin/apprate/ExceptionHandler.java b/AppRate/src/com/tjeannin/apprate/ExceptionHandler.java index 6e97ff8..c27c536 100644 --- a/AppRate/src/com/tjeannin/apprate/ExceptionHandler.java +++ b/AppRate/src/com/tjeannin/apprate/ExceptionHandler.java @@ -1,27 +1,26 @@ package com.tjeannin.apprate; -import java.lang.Thread.UncaughtExceptionHandler; - import android.content.Context; import android.content.SharedPreferences; +import java.lang.Thread.UncaughtExceptionHandler; + public class ExceptionHandler implements UncaughtExceptionHandler { - private UncaughtExceptionHandler defaultExceptionHandler; - SharedPreferences preferences; + private UncaughtExceptionHandler mDefaultExceptionHandler; - // Constructor. - public ExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler, Context context) - { - preferences = context.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, 0); - defaultExceptionHandler = uncaughtExceptionHandler; - } + private SharedPreferences mPreferences; - public void uncaughtException(Thread thread, Throwable throwable) { + // Constructor. + public ExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler, Context context) { + mPreferences = context.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, Context.MODE_PRIVATE); + mDefaultExceptionHandler = uncaughtExceptionHandler; + } - preferences.edit().putBoolean(PrefsContract.PREF_APP_HAS_CRASHED, true).commit(); + public void uncaughtException(Thread thread, Throwable throwable) { + mPreferences.edit().putBoolean(PrefsContract.PREF_APP_HAS_CRASHED, true).commit(); - // Call the original handler. - defaultExceptionHandler.uncaughtException(thread, throwable); - } + // Call the original handler. + mDefaultExceptionHandler.uncaughtException(thread, throwable); + } } \ No newline at end of file From 0e5545a59ac397851355b75fe751ea0f9befd3f5 Mon Sep 17 00:00:00 2001 From: bdonahue Date: Thu, 9 Jan 2014 17:00:29 -0500 Subject: [PATCH 3/9] Fixing wrong documentation on setShowIfAppHasCrashed --- AppRate/src/com/tjeannin/apprate/AppRate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppRate/src/com/tjeannin/apprate/AppRate.java b/AppRate/src/com/tjeannin/apprate/AppRate.java index e423da8..8cda9ec 100644 --- a/AppRate/src/com/tjeannin/apprate/AppRate.java +++ b/AppRate/src/com/tjeannin/apprate/AppRate.java @@ -65,7 +65,7 @@ public AppRate setMinDaysUntilPrompt(long minDaysUntilPrompt) { /** * @param showIfCrash If false the rate dialog will not be shown if the application has crashed once.
- * Default value is false. + * Default value is true. * @return This {@link AppRate} object to allow chaining. */ public AppRate setShowIfAppHasCrashed(boolean showIfCrash) { From 0343f924bc948068fb58bc72f831557569e9588d Mon Sep 17 00:00:00 2001 From: bdonahue Date: Thu, 9 Jan 2014 17:12:46 -0500 Subject: [PATCH 4/9] Was a little over agressive with search replace of ,0 for Context.MODE_PRIVATE 0's in these cases are more correct. --- AppRate/src/com/tjeannin/apprate/AppRate.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AppRate/src/com/tjeannin/apprate/AppRate.java b/AppRate/src/com/tjeannin/apprate/AppRate.java index 8cda9ec..ad4e958 100644 --- a/AppRate/src/com/tjeannin/apprate/AppRate.java +++ b/AppRate/src/com/tjeannin/apprate/AppRate.java @@ -118,11 +118,11 @@ public void init() { Editor editor = mPreferences.edit(); // Get and increment launch counter. - long launch_count = mPreferences.getLong(PrefsContract.PREF_LAUNCH_COUNT, Context.MODE_PRIVATE) + 1; + long launch_count = mPreferences.getLong(PrefsContract.PREF_LAUNCH_COUNT, 0) + 1; editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, launch_count); // Get date of first launch. - Long date_firstLaunch = mPreferences.getLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, Context.MODE_PRIVATE); + Long date_firstLaunch = mPreferences.getLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, 0); if (date_firstLaunch == 0) { date_firstLaunch = System.currentTimeMillis(); editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, date_firstLaunch); @@ -208,7 +208,7 @@ private void showDialog(AlertDialog.Builder builder) { public void onCancel(DialogInterface dialog) { Editor editor = mPreferences.edit(); editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, Context.MODE_PRIVATE); + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); editor.commit(); } @@ -241,7 +241,7 @@ public void onClick(DialogInterface dialog, int which) { case DialogInterface.BUTTON_NEUTRAL: editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, Context.MODE_PRIVATE); + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); break; default: @@ -265,7 +265,7 @@ private static final String getApplicationName(Context context) { ApplicationInfo applicationInfo; try { - applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), Context.MODE_PRIVATE); + applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); } catch (final NameNotFoundException e) { applicationInfo = null; } From 41ed5c679031f5a217f381a799093e5cc24b7163 Mon Sep 17 00:00:00 2001 From: bdonahue Date: Thu, 9 Jan 2014 17:54:36 -0500 Subject: [PATCH 5/9] Adding support for having the rating dialog re-initialize itself after the app has been upgraded. This is disabled by default. --- AppRate/src/com/tjeannin/apprate/AppRate.java | 62 ++++++++++++++++++- .../com/tjeannin/apprate/PrefsContract.java | 1 + 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/AppRate/src/com/tjeannin/apprate/AppRate.java b/AppRate/src/com/tjeannin/apprate/AppRate.java index ad4e958..2f4f0e7 100644 --- a/AppRate/src/com/tjeannin/apprate/AppRate.java +++ b/AppRate/src/com/tjeannin/apprate/AppRate.java @@ -11,6 +11,7 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; @@ -38,6 +39,8 @@ public class AppRate implements android.content.DialogInterface.OnClickListener, private boolean mShowIfHasCrashed = true; + private boolean mResetOnAppUpgrade = false; + public AppRate(Activity hostActivity) { mHostActivity = hostActivity; mPreferences = hostActivity.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, Context.MODE_PRIVATE); @@ -73,6 +76,17 @@ public AppRate setShowIfAppHasCrashed(boolean showIfCrash) { return this; } + /** + * @param resetOnAppUpgrade If true the rate dialog tracking will be reset when the application is upgraded. + * This will allow the rate the application dialog to be shown again. + * Default value is false. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setResetOnAppUpgrade(boolean resetOnAppUpgrade) { + mResetOnAppUpgrade = resetOnAppUpgrade; + return this; + } + /** * Use this method if you want to customize the style and content of the rate dialog.
* When using the {@link AlertDialog.Builder} you should use: @@ -106,6 +120,9 @@ public static void reset(Context context) { public void init() { Log.d(TAG, "Init AppRate"); + Editor editor = mPreferences.edit(); + performAppUpgradeCheck(editor); + if (mPreferences.getBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, false) || ( mPreferences.getBoolean(PrefsContract.PREF_APP_HAS_CRASHED, false) && !mShowIfHasCrashed)) { return; @@ -115,8 +132,6 @@ public void init() { initExceptionHandler(); } - Editor editor = mPreferences.edit(); - // Get and increment launch counter. long launch_count = mPreferences.getLong(PrefsContract.PREF_LAUNCH_COUNT, 0) + 1; editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, launch_count); @@ -143,6 +158,24 @@ public void init() { editor.commit(); } + /** + * Checks and saves off the current version information for the application. If the application has been upgraded, and configured to do so, then + * reset tracking information to allow the rate dialog to be shown again. + */ + private void performAppUpgradeCheck(Editor editor) { + Integer currentAppVersionCode = AppRate.getApplicationVersionCode(mHostActivity.getApplicationContext()); + Integer lastRunAppVersionCode = mPreferences.getInt(PrefsContract.PREF_APP_VERSION_CODE, -1); + + // If the version has been initialized, we are being upgraded, and the user enabled resetting on upgrading + if (lastRunAppVersionCode != -1 && currentAppVersionCode > lastRunAppVersionCode && mResetOnAppUpgrade) { + AppRate.reset(mHostActivity); + } + + // Save off the current app version code + editor.putInt(PrefsContract.PREF_APP_VERSION_CODE, currentAppVersionCode); + editor.commit(); + } + /** * Initialize the {@link ExceptionHandler}. */ @@ -272,4 +305,29 @@ private static final String getApplicationName(Context context) { return (String) (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : context.getString(R.string.application_name_unknown)); } + + /** + * Get the application version code + * + * @param context + * @return The version name or null if there was an error + */ + private static final Integer getApplicationVersionCode(Context context) { + try { + if (context != null) { + PackageManager pm = context.getPackageManager(); + if (pm != null) { + PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); + if (pi != null) { + return pi.versionCode; + } + } + } + + } catch (NameNotFoundException e) { + Log.e(TAG, "Unable to get application version code"); + } + + return 0; + } } \ No newline at end of file diff --git a/AppRate/src/com/tjeannin/apprate/PrefsContract.java b/AppRate/src/com/tjeannin/apprate/PrefsContract.java index 4f75b1c..001cef1 100644 --- a/AppRate/src/com/tjeannin/apprate/PrefsContract.java +++ b/AppRate/src/com/tjeannin/apprate/PrefsContract.java @@ -9,4 +9,5 @@ public class PrefsContract { public static final String PREF_LAUNCH_COUNT = "launch_count"; public static final String PREF_DONT_SHOW_AGAIN = "dont_show_again"; public static final String PREF_DONT_SHOW_IF_CRASHED = "pref_dont_show_if_crashed"; + public static final String PREF_APP_VERSION_CODE = "pref_app_version_code"; } From 4d09935ba8e1710df283b5765f511bdcb8ba6d70 Mon Sep 17 00:00:00 2001 From: bdonahue Date: Fri, 10 Jan 2014 11:55:00 -0500 Subject: [PATCH 6/9] Adding support for a new flow where the user with first be prompted if they like the app or not. If yes, then they are directed to the existing rating dialog. If not they are prompted to leave feedback for the app. This flow is disabled by default. --- AppRate/res/values/strings.xml | 11 + AppRate/src/com/tjeannin/apprate/AppInfo.java | 75 +++ AppRate/src/com/tjeannin/apprate/AppRate.java | 471 ++++++++++++++---- .../com/tjeannin/apprate/SendFeedback.java | 71 +++ .../screenshot_doyoulikeapp_dark.png | Bin 0 -> 21861 bytes .../screenshot_doyoulikeapp_light.png | Bin 0 -> 21326 bytes .../screenshot_sendfeedback_dark.png | Bin 0 -> 25787 bytes .../screenshot_sendfeedback_light.png | Bin 0 -> 25203 bytes README.md | 130 ++++- 9 files changed, 655 insertions(+), 103 deletions(-) create mode 100644 AppRate/src/com/tjeannin/apprate/AppInfo.java create mode 100644 AppRate/src/com/tjeannin/apprate/SendFeedback.java create mode 100644 AppRateScreenshots/screenshot_doyoulikeapp_dark.png create mode 100644 AppRateScreenshots/screenshot_doyoulikeapp_light.png create mode 100644 AppRateScreenshots/screenshot_sendfeedback_dark.png create mode 100644 AppRateScreenshots/screenshot_sendfeedback_light.png diff --git a/AppRate/res/values/strings.xml b/AppRate/res/values/strings.xml index 1bced83..82f232e 100644 --- a/AppRate/res/values/strings.xml +++ b/AppRate/res/values/strings.xml @@ -6,7 +6,18 @@ Rate it! Remind me later No thanks + Tell Us + "Do you like %1$s?" + Yes + No + Oh no! + Please let us know what we can do to make it better for you. + Send Feedback + Cancel No Play Store installed on device (unknown) + "%1$s Feedback" + Please enter your feedback above this line + Send Email… \ No newline at end of file diff --git a/AppRate/src/com/tjeannin/apprate/AppInfo.java b/AppRate/src/com/tjeannin/apprate/AppInfo.java new file mode 100644 index 0000000..357e1d3 --- /dev/null +++ b/AppRate/src/com/tjeannin/apprate/AppInfo.java @@ -0,0 +1,75 @@ +package com.tjeannin.apprate; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.util.Log; + +/** + * Created by bdonahue on 1/10/14. + */ +public class AppInfo { + private static final String TAG = AppInfo.class.getSimpleName(); + + /** + * @param context A context of the current application. + * @return The application name of the current application. + */ + public static final String getApplicationName(Context context) { + final PackageManager packageManager = context.getPackageManager(); + ApplicationInfo applicationInfo; + + try { + applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); + } catch (final PackageManager.NameNotFoundException e) { + applicationInfo = null; + } + + return (String) (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : context.getString(R.string.application_name_unknown)); + } + + /** + * Get the application version code + * + * @param context + * @return The version name or null if there was an error + */ + public static final Integer getApplicationVersionCode(Context context) { + try { + if (context != null) { + PackageManager pm = context.getPackageManager(); + if (pm != null) { + PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); + if (pi != null) { + return pi.versionCode; + } + } + } + + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Unable to get application version code"); + } + + return 0; + } + + public static String getApplicationVersionName(Context context) { + try { + if (context != null) { + PackageManager pm = context.getPackageManager(); + if (pm != null) { + PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); + if (pi != null) { + return pi.versionName; + } + } + } + + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Unable to get application version name"); + } + + return ""; + } +} diff --git a/AppRate/src/com/tjeannin/apprate/AppRate.java b/AppRate/src/com/tjeannin/apprate/AppRate.java index 2f4f0e7..03af952 100644 --- a/AppRate/src/com/tjeannin/apprate/AppRate.java +++ b/AppRate/src/com/tjeannin/apprate/AppRate.java @@ -10,18 +10,15 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.text.format.DateUtils; import android.util.Log; +import android.widget.Button; import android.widget.Toast; import java.lang.Thread.UncaughtExceptionHandler; -public class AppRate implements android.content.DialogInterface.OnClickListener, OnCancelListener { +public class AppRate { private static final String TAG = "AppRater"; @@ -29,10 +26,18 @@ public class AppRate implements android.content.DialogInterface.OnClickListener, private OnClickListener mClickListener; + private OnClickListener mSendFeedbackClickListener; + + private OnClickListener mDoYouLikeAppClickListener; + private SharedPreferences mPreferences; private AlertDialog.Builder mDialogBuilder = null; + private AlertDialog.Builder mSendFeedbackDialogBuilder = null; + + private AlertDialog.Builder mDoYouLikeAppDialogBuilder = null; + private long mMinLaunchesUntilPrompt = 0; private long mMinDaysUntilPrompt = 0; @@ -41,6 +46,14 @@ public class AppRate implements android.content.DialogInterface.OnClickListener, private boolean mResetOnAppUpgrade = false; + private boolean mShowDoYouLikeTheAppFlow = false; + + private String mSendFeedbackEmailAddress; + + private String mSendFeedbackSubject; + + private String mSendFeedbackBody; + public AppRate(Activity hostActivity) { mHostActivity = hostActivity; mPreferences = hostActivity.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, Context.MODE_PRIVATE); @@ -104,6 +117,80 @@ public AppRate setCustomDialog(AlertDialog.Builder customBuilder) { return this; } + /** + * Use this method if you want to customize the style and content of the do you like the app dialog.
+ * When using the {@link AlertDialog.Builder} you should use: + *
    + *
  • {@link AlertDialog.Builder#setPositiveButton} for the yes button.
  • + *
  • {@link AlertDialog.Builder#setNegativeButton} for the no button.
  • + *
+ * + * @param customBuilder The custom dialog you want to use as the do you like the app dialog. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setCustomSendFeedbackDialog(AlertDialog.Builder customBuilder) { + mSendFeedbackDialogBuilder = customBuilder; + return this; + } + + /** + * Use this method if you want to customize the style and content of the send feedback dialog.
+ * When using the {@link AlertDialog.Builder} you should use: + *
    + *
  • {@link AlertDialog.Builder#setPositiveButton} for the yes button.
  • + *
  • {@link AlertDialog.Builder#setNegativeButton} for the no button.
  • + *
+ * + * @param customBuilder The custom dialog you want to use as the send feedback dialog. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setCustomDoYouLikeAppDialog(AlertDialog.Builder customBuilder) { + mDoYouLikeAppDialogBuilder = customBuilder; + return this; + } + + /** + * Enable do you like the app flow instead of showing just the rating dialog. + * The flow will be as follows: + *
    + *
  • A Dialog asking if the user likes the app.
  • + *
  • If they say yes they are directed to the rating dialog.
  • + *
  • If they say no they are directed to a dialog asking them if they would like to leave feedback for the + * app.
  • + *
+ *

+ * + * @param sendFeedbackEmailAddress The email address that the user will send feedback to + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate showDoYouLikeTheAppFlow(String sendFeedbackEmailAddress) { + mShowDoYouLikeTheAppFlow = true; + mSendFeedbackEmailAddress = sendFeedbackEmailAddress; + return this; + } + + /** + * Set the subject for the send feedback dialog. + * + * @param subject + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setSendFeedbackSubject(String subject) { + mSendFeedbackSubject = subject; + return this; + } + + /** + * Set the body for the send feedback dialog. + * + * @param body + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setSendFeedbackBody(String body) { + mSendFeedbackBody = body; + return this; + } + /** * Reset all the data collected about number of launches and days until first launch. * @@ -123,15 +210,15 @@ public void init() { Editor editor = mPreferences.edit(); performAppUpgradeCheck(editor); + if (!mShowIfHasCrashed) { + initExceptionHandler(); + } + if (mPreferences.getBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, false) || ( mPreferences.getBoolean(PrefsContract.PREF_APP_HAS_CRASHED, false) && !mShowIfHasCrashed)) { return; } - if (!mShowIfHasCrashed) { - initExceptionHandler(); - } - // Get and increment launch counter. long launch_count = mPreferences.getLong(PrefsContract.PREF_LAUNCH_COUNT, 0) + 1; editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, launch_count); @@ -143,14 +230,13 @@ public void init() { editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, date_firstLaunch); } - // Show the rate dialog if needed. + // Show the first dialog if needed. if (launch_count >= mMinLaunchesUntilPrompt) { if (System.currentTimeMillis() >= date_firstLaunch + (mMinDaysUntilPrompt * DateUtils.DAY_IN_MILLIS)) { - - if (mDialogBuilder != null) { - showDialog(mDialogBuilder); + if (mShowDoYouLikeTheAppFlow) { + showDoYouLikeAppDialog(); } else { - showDefaultDialog(); + showDialog(); } } } @@ -163,7 +249,7 @@ public void init() { * reset tracking information to allow the rate dialog to be shown again. */ private void performAppUpgradeCheck(Editor editor) { - Integer currentAppVersionCode = AppRate.getApplicationVersionCode(mHostActivity.getApplicationContext()); + Integer currentAppVersionCode = AppInfo.getApplicationVersionCode(mHostActivity.getApplicationContext()); Integer lastRunAppVersionCode = mPreferences.getInt(PrefsContract.PREF_APP_VERSION_CODE, -1); // If the version has been initialized, we are being upgraded, and the user enabled resetting on upgrading @@ -191,6 +277,39 @@ private void initExceptionHandler() { } } + /** + * Shows the rate dialog using either the default or user provided builder. + */ + private void showDialog() { + if (mDialogBuilder != null) { + showCustomDialog(mDialogBuilder); + } else { + showDefaultDialog(); + } + } + + /** + * Shows the do you like the app dialog using either the default or user provided builder. + */ + private void showDoYouLikeAppDialog() { + if (mDoYouLikeAppDialogBuilder != null) { + showCustomDoYouLikeAppDialog(mDoYouLikeAppDialogBuilder); + } else { + showDefaultDoYouLikeAppDialog(); + } + } + + /** + * Shows the send feedback dialog using either the default or user provided builder. + */ + private void showSendFeedbackDialog() { + if (mSendFeedbackDialogBuilder != null) { + showCustomSendFeedbackDialog(mSendFeedbackDialogBuilder); + } else { + showDefaultSendFeedbackDialog(); + } + } + /** * Shows the default rate dialog. * @@ -199,19 +318,63 @@ private void initExceptionHandler() { private void showDefaultDialog() { Log.d(TAG, "Create default dialog."); - String title = mHostActivity.getString(R.string.dialog_title, getApplicationName(mHostActivity.getApplicationContext())); - String message = mHostActivity.getString(R.string.dialog_message, getApplicationName(mHostActivity.getApplicationContext())); - String rate = mHostActivity.getString(R.string.dialog_positive_button); - String remindLater = mHostActivity.getString(R.string.dialog_neutral_button); - String dismiss = mHostActivity.getString(R.string.dialog_negative_button); + String title = mHostActivity.getString(R.string.dialog_title, AppInfo.getApplicationName(mHostActivity.getApplicationContext())); + String message = mHostActivity.getString(R.string.dialog_message, AppInfo.getApplicationName(mHostActivity.getApplicationContext())); + String positiveButtonText = mHostActivity.getString(R.string.dialog_positive_button); + String neutralButtonText = mHostActivity.getString(R.string.dialog_neutral_button); + String negativeButtonText = mHostActivity.getString(R.string.dialog_negative_button); + + new AlertDialog.Builder(mHostActivity) + .setTitle(title) + .setMessage(message) + .setPositiveButton(positiveButtonText, mDialogOnClickListener) + .setNegativeButton(negativeButtonText, mDialogOnClickListener) + .setNeutralButton(neutralButtonText, mDialogOnClickListener) + .setOnCancelListener(mDialogOnCancelListener) + .create().show(); + } + + /** + * Shows the default do you like app dialog. + * + * @return + */ + private void showDefaultDoYouLikeAppDialog() { + Log.d(TAG, "Create default do you like app dialog."); + + String title = mHostActivity.getString(R.string.like_app_dialog_title, AppInfo.getApplicationName(mHostActivity.getApplicationContext())); + String message = mHostActivity.getString(R.string.like_app_dialog_message, AppInfo.getApplicationName(mHostActivity.getApplicationContext())); + String positiveButtonText = mHostActivity.getString(R.string.like_app_dialog_positive_button); + String negativeButtonText = mHostActivity.getString(R.string.like_app_dialog_negative_button); + + new AlertDialog.Builder(mHostActivity) + .setTitle(title) + .setMessage(message) + .setPositiveButton(positiveButtonText, mDoYouLikeAppDialogOnClickListener) + .setNegativeButton(negativeButtonText, mDoYouLikeAppDialogOnClickListener) + .setOnCancelListener(mDoYouLikeAppDialogOnCancelListener) + .create().show(); + } + + /** + * Shows the default send feedback dialog. + * + * @return + */ + private void showDefaultSendFeedbackDialog() { + Log.d(TAG, "Create default send feedback dialog."); + + String title = mHostActivity.getString(R.string.send_feedback_dialog_title, AppInfo.getApplicationName(mHostActivity.getApplicationContext())); + String message = mHostActivity.getString(R.string.send_feedback_dialog_message, AppInfo.getApplicationName(mHostActivity.getApplicationContext())); + String positiveButtonText = mHostActivity.getString(R.string.send_feedback_dialog_positive_button); + String negativeButtonText = mHostActivity.getString(R.string.send_feedback_dialog_negative_button); new AlertDialog.Builder(mHostActivity) .setTitle(title) .setMessage(message) - .setPositiveButton(rate, this) - .setNegativeButton(dismiss, this) - .setNeutralButton(remindLater, this) - .setOnCancelListener(this) + .setPositiveButton(positiveButtonText, mSendFeedbackDialogOnClickListener) + .setNegativeButton(negativeButtonText, mSendFeedbackDialogOnClickListener) + .setOnCancelListener(mSendFeedbackDialogOnCancelListener) .create().show(); } @@ -220,33 +383,71 @@ private void showDefaultDialog() { * * @return */ - private void showDialog(AlertDialog.Builder builder) { + private void showCustomDialog(AlertDialog.Builder builder) { Log.d(TAG, "Create custom dialog."); + buildDialogWithWrapperedClickHandlers(builder, mDialogOnClickListener, mDialogOnCancelListener); + } + /** + * Show the custom do you like app dialog. + * + * @return + */ + private void showCustomDoYouLikeAppDialog(AlertDialog.Builder builder) { + Log.d(TAG, "Create custom do you like app dialog."); + buildDialogWithWrapperedClickHandlers(builder, mDoYouLikeAppDialogOnClickListener, mDoYouLikeAppDialogOnCancelListener); + } + + /** + * Show the custom send feedback dialog. + * + * @return + */ + private void showCustomSendFeedbackDialog(AlertDialog.Builder builder) { + Log.d(TAG, "Create custom send feedback dialog."); + buildDialogWithWrapperedClickHandlers(builder, mSendFeedbackDialogOnClickListener, mSendFeedbackDialogOnCancelListener); + } + + /** + * Create the dialog using the provided builder. After created reassign all on click listeners to route through the provided listener. + * + * @param builder + * @param onClickListener + * @param onCancelListener + */ + private void buildDialogWithWrapperedClickHandlers(AlertDialog.Builder builder, OnClickListener onClickListener, OnCancelListener onCancelListener) { + // Make the dialog AlertDialog dialog = builder.create(); dialog.show(); - String rate = (String) dialog.getButton(AlertDialog.BUTTON_POSITIVE).getText(); - String remindLater = (String) dialog.getButton(AlertDialog.BUTTON_NEUTRAL).getText(); - String dismiss = (String) dialog.getButton(AlertDialog.BUTTON_NEGATIVE).getText(); - - dialog.setButton(AlertDialog.BUTTON_POSITIVE, rate, this); - dialog.setButton(AlertDialog.BUTTON_NEUTRAL, remindLater, this); - dialog.setButton(AlertDialog.BUTTON_NEGATIVE, dismiss, this); + // Wrapper each of the button click listeners with our own that gets called first + updateDialogButtonClickListeners(dialog, AlertDialog.BUTTON_POSITIVE, onClickListener); + updateDialogButtonClickListeners(dialog, AlertDialog.BUTTON_NEUTRAL, onClickListener); + updateDialogButtonClickListeners(dialog, AlertDialog.BUTTON_NEGATIVE, onClickListener); - dialog.setOnCancelListener(this); + // Wrapper the on cancel listener + dialog.setOnCancelListener(onCancelListener); } - @Override - public void onCancel(DialogInterface dialog) { - Editor editor = mPreferences.edit(); - editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); - editor.commit(); + /** + * Update all of the dialogs buttons to use the provided onClickListener + * + * @param dialog + * @param whichButton + * @param onClickListener + */ + private void updateDialogButtonClickListeners(AlertDialog dialog, int whichButton, OnClickListener onClickListener) { + if (dialog != null) { + Button button = dialog.getButton(whichButton); + if (button != null) { + String buttonText = (String) button.getText(); + dialog.setButton(whichButton, buttonText, onClickListener); + } + } } /** - * @param onClickListener A listener to be called back on. + * @param onClickListener A listener to be called back on click actions to the rate dialog. * @return This {@link AppRate} object to allow chaining. */ public AppRate setOnClickListener(OnClickListener onClickListener) { @@ -254,80 +455,150 @@ public AppRate setOnClickListener(OnClickListener onClickListener) { return this; } - @Override - public void onClick(DialogInterface dialog, int which) { - Editor editor = mPreferences.edit(); + /** + * @param onClickListener A listener to be called back on click actions to the do you like the app dialog. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setDoYouLikeAppOnClickListener(OnClickListener onClickListener) { + mDoYouLikeAppClickListener = onClickListener; + return this; + } - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - try { - mHostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + mHostActivity.getPackageName()))); - } catch (ActivityNotFoundException e) { - Toast.makeText(mHostActivity, mHostActivity.getString(R.string.toast_play_store_missing_error), Toast.LENGTH_SHORT).show(); - } - editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); - break; + /** + * @param onClickListener A listener to be called back on click actions to the send feedback dialog. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setSendFeedbackOnClickListener(OnClickListener onClickListener) { + mSendFeedbackClickListener = onClickListener; + return this; + } - case DialogInterface.BUTTON_NEGATIVE: - editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); - break; + private OnClickListener mDialogOnClickListener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Editor editor = mPreferences.edit(); + + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + try { + mHostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + mHostActivity.getPackageName()))); + } catch (ActivityNotFoundException e) { + Toast.makeText(mHostActivity, mHostActivity.getString(R.string.toast_play_store_missing_error), Toast.LENGTH_SHORT).show(); + } + editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); + break; - case DialogInterface.BUTTON_NEUTRAL: - editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); - editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); - break; + case DialogInterface.BUTTON_NEGATIVE: + editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); + break; - default: - break; - } + case DialogInterface.BUTTON_NEUTRAL: + editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); + break; - editor.commit(); - dialog.dismiss(); + default: + break; + } + + editor.commit(); + dialog.dismiss(); - if (mClickListener != null) { - mClickListener.onClick(dialog, which); + if (mClickListener != null) { + mClickListener.onClick(dialog, which); + } } - } + }; + + private OnClickListener mDoYouLikeAppDialogOnClickListener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Dismiss the do you like the app dialog + dialog.dismiss(); + + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + // Show the rating dialog + showDialog(); + break; + + case DialogInterface.BUTTON_NEGATIVE: + // They don't like the app; don't prompt them again + doNotShowDialogAgain(); + + // Show the send feedback dialog + showSendFeedbackDialog(); + break; + + default: + break; + } - /** - * @param context A context of the current application. - * @return The application name of the current application. - */ - private static final String getApplicationName(Context context) { - final PackageManager packageManager = context.getPackageManager(); - ApplicationInfo applicationInfo; - - try { - applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); - } catch (final NameNotFoundException e) { - applicationInfo = null; + if (mDoYouLikeAppClickListener != null) { + mDoYouLikeAppClickListener.onClick(dialog, which); + } } + }; - return (String) (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : context.getString(R.string.application_name_unknown)); - } + private OnClickListener mSendFeedbackDialogOnClickListener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Editor editor = mPreferences.edit(); - /** - * Get the application version code - * - * @param context - * @return The version name or null if there was an error - */ - private static final Integer getApplicationVersionCode(Context context) { - try { - if (context != null) { - PackageManager pm = context.getPackageManager(); - if (pm != null) { - PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); - if (pi != null) { - return pi.versionCode; - } - } + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + SendFeedback sendFeedback = new SendFeedback(mHostActivity); + sendFeedback.promptForFeedback(mSendFeedbackEmailAddress, mSendFeedbackSubject, mSendFeedbackBody); + break; + + case DialogInterface.BUTTON_NEGATIVE: + // Nothing to do + break; + + default: + break; } - } catch (NameNotFoundException e) { - Log.e(TAG, "Unable to get application version code"); + editor.commit(); + dialog.dismiss(); + + if (mSendFeedbackClickListener != null) { + mSendFeedbackClickListener.onClick(dialog, which); + } + } + }; + + private OnCancelListener mDialogOnCancelListener = new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + resetLaunchData(); } + }; - return 0; + private void resetLaunchData() { + Editor editor = mPreferences.edit(); + editor.putLong(PrefsContract.PREF_DATE_FIRST_LAUNCH, System.currentTimeMillis()); + editor.putLong(PrefsContract.PREF_LAUNCH_COUNT, 0); + editor.commit(); + } + + private void doNotShowDialogAgain() { + Editor editor = mPreferences.edit(); + editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true); + editor.commit(); } + + private OnCancelListener mDoYouLikeAppDialogOnCancelListener = new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + resetLaunchData(); + } + }; + + private OnCancelListener mSendFeedbackDialogOnCancelListener = new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + doNotShowDialogAgain(); + } + }; } \ No newline at end of file diff --git a/AppRate/src/com/tjeannin/apprate/SendFeedback.java b/AppRate/src/com/tjeannin/apprate/SendFeedback.java new file mode 100644 index 0000000..b0ae2a1 --- /dev/null +++ b/AppRate/src/com/tjeannin/apprate/SendFeedback.java @@ -0,0 +1,71 @@ +package com.tjeannin.apprate; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; + +/** + * This class will craft a feedback email to allow the user to send feedback. + */ +public class SendFeedback { + private Activity mActivity; + + public SendFeedback(Activity activity) { + mActivity = activity; + } + + /** + * Prompt the user for feedback by generating and sending an intent to open their email client. + * + * @param feedbackEmailAddress + * @param subject (Optional) If null default subject will be used + * @param body (Optional) If null the default body will be used + */ + public void promptForFeedback(String feedbackEmailAddress, String subject, String body) { + if (mActivity == null) return; + + // Generate default body text + StringBuilder defaultBodyText = new StringBuilder(); + defaultBodyText.append("\n\n\n\n"); + defaultBodyText.append("------------------------------------\n\n"); + defaultBodyText.append(mActivity.getString(R.string.feedback_email_header)); + defaultBodyText.append("\n\n"); + defaultBodyText.append("\nAndroid Device: " + getDeviceName()); + defaultBodyText.append("\nAndroid Version: " + Build.VERSION.RELEASE); + defaultBodyText.append("\nApp Version: " + AppInfo.getApplicationVersionName(mActivity)); + + String defaultSubjectText = mActivity.getString(R.string.feedback_email_subject_line, AppInfo.getApplicationName(mActivity)); + + Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", feedbackEmailAddress, null)); + i.putExtra(Intent.EXTRA_SUBJECT, subject != null ? subject : defaultSubjectText); + i.putExtra(Intent.EXTRA_TEXT, body != null ? body : defaultBodyText.toString()); + + try { + mActivity.startActivity(Intent.createChooser(i, mActivity.getString(R.string.send_email))); + } catch (android.content.ActivityNotFoundException ex) { + } + } + + public String getDeviceName() { + String manufacturer = Build.MANUFACTURER; + String model = Build.MODEL; + if (model.startsWith(manufacturer)) { + return capitalize(model); + } else { + return capitalize(manufacturer) + " " + model; + } + } + + private String capitalize(String s) { + if (s == null || s.length() == 0) { + return ""; + } + char first = s.charAt(0); + if (Character.isUpperCase(first)) { + return s; + } else { + return Character.toUpperCase(first) + s.substring(1); + } + } +} diff --git a/AppRateScreenshots/screenshot_doyoulikeapp_dark.png b/AppRateScreenshots/screenshot_doyoulikeapp_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..8f1e210ef26367eb1538609dba7de53831078e6a GIT binary patch literal 21861 zcmZs@2RxSV`#!D+g$P+$8KJDCY(larWbf=fvR8!cogGOiW%Jl0BiST-?>!!S`<>7G z^Z9)LpYQ+od-Zxs&vQTbeP7poo#%O+$8lVOUnof8-JrOEhK7bGE%i(Z{@q4HyYd|y z6Mnj|q#%TUFb!oTpP^l%{(P#G0~L#_J{j)bbpU6*sQHRv|g?a zkBR18{IITfTK_Gp_5Sf0P|)QhXx7Fi`*8!ARgg6UvgHpIF{d7125;I^;yzdY3SG znzvi@!_4k+P>bO(B3wyQ_vzy9F&cJ&m|1e*)D{y(_^d-^FE`r-Ul#F<9q&c50ok+6 zK2fj3#sHkQ-@l*sb5DAoTDP~i2Nt|_bZ`iIp80oRVE;66%%(bgqS_@kB}G<3LgMU_ zkB^U=o7?X4{1E?W{;@p0fIv!BRh8)Fi>6xzLmlIlj`o$>u7cE``fbCtqtRysA19Yg{@%!{J3L} z@xl6tk%`IYHU1g9MC&mG@?@=`#JoTI$h0+*2EQQ??+&MY>^J2cB~{hu3JN#9>+4g3 zM9#Lw!-vtMqna@>F%_%1-z(-K1ejS^R_wJ+OzuscE%F?n4An=>@v6s5aFR9KQwmb! zmzee}j!j)W$;!%t&+BJ0BZV97Q!AuCC?T0)r982nq_nl;di3a}%tN;wBi4@3b#--m zL-y;#MPIVAUcP*J%g4Gi@nNddphhVI@n?7#yTSiDQ6jfFq0e!Lo_n}IArTSs*z@n- zzs;GS>U6hcWMpnsR#pxp()OC(WirkA zvgFxLLjC$;mkv8=M*;^E%)CD5Z)HUx2^}4(k&%%gfmHFIlgW8`cLrOz3XRSOYj zn&uWbq~}9bFeD4hJKOy8ntQqXmoHy99pY3k1aQe7!nEoypRkGs0MkOXHU7jq&~($X`z z-}6K2C#5Yc?jKHiaB$RYUxi8TOnUTw%jfdczsaEPuy*UA)2fQD_p$M>@H?$I95rvP z$IglDR8>jj<>fuMe`0C7&IDME6bIyKl^5&(yy|_@pI&U(azjZ;sbcwas4E0?b(yYs zc*nx$PoLff;E*~jCYi=WNB=z8Uvpb8YBe)6<27;AYvMFBH^0lsc&&a)(ZJyDR_!4* z)5kYT_3ep|OmCtV9n5b;{a|lzLl@6fXI}Ya$k@i_-K$NU73;+v>If@xHEsKAB1b>* z(JJ-_wJKpjyBTZwdd3q=_^j3!@g|_r9qUK!S_;Eicb_Z@JIjHg64{ z%H|NcToM=Kq)YG6H3y@X|GakEA57@_><_59!D|lB zh$)syF}tE7@!{)Vg)mjBKh$qUT5)l4VZU!mbz4mG-2bjerH*|*vE`irhitzWIrD`Z zj6_16?_P5j(_Q+3$?kqIa%P(?vDZ* zFgG5Dn?fc61^nXecD$Xd1K+O)h^eTlJ+d79VZ&#j_hzybl`q)X*d`{cA#7Y{gPGj- z^&{r&n(%nG(=U(Hkrz0y5XHobl1;c;=ymF>%}y%A0)HvzD1?WW!+oo>l8`zv z5N4E?63h4h?&w&195(3mv9y%CM%Ol-FT~~5i~Rzhu2eq9 zik0k?uRngw`(jZ~Uz~24F0_A`pPw%@Y9sU%rl~(_;b3NG7dGO_HP-l{SD&U)ViKK} z7NHap7KYm`xGR_DvB{U5oE)KX>p|A<_Vz|@dDQ}4d1q(m`evM{gak=x>FZ+%>$QWE zuP-x)VMTZxtgq|}G|h0nZjA_k->P#BcN+@M?({qSo!|74dz!y23u=GCvCJGCrh`8; zwC!7NGu*pZ?6{;r?Xmvwo?=?(&O*l=UXarL$=1FVd-`Z>h+o%Q-8VXtED}ymk97+Y zSd_Cr#eIfq*XnX7@MjqLBN(0FbeTLvcXo=+ETpkDyDN%9onx%RzqN*Le#y+8`(m-3!z;%MNRpss3>}HQ1w>?RYwGs04Hvy zWIloeRmJKr&$p5UT-ed9t*s#zlfM_#CChTumiA1(?kFCvuzy{%S&QtGq}d`}L*glEBnmlF*kL8YAB=Y3?g2D_5SZeoqqd5#Hb5|DjVI z4>|QiR|*eJtWb~6H6t=iSfFxgf=N3&4k4kTNf5qQBB>sk;O2aErkMK`KKJX6tR z)V$n*2@$({qgBJTm=SIUgfC`%=co+|u$jltx#EHN7RMWrk-*$n}ZpgpiOM$tfw7u;|r`jjlryV6m;;SG{zczBurs4l?5ou^#if z@bMv?{SvEScz&|~L$fS*$a7KsmpvsQkJ;l%^PG>*phBsar`0}X>M*V8IKKRiAmS&Vv6mii;$+4 z)-i-s=btRuV-!@FA2MJ4`wfsGr+3fh8l%AFq}m%;-rSEL!|2QHN4ksF>QGp%+N&P^&=QN7m4U z3;4tck|e-5SiasIXAr%B+aZ03WxNn9*mkc4q%QnEom;+XZJ+Sw`^eubUXnL_pT50C z|9l$h8uW|~DNTOfvf%L0{0{>xJX9%;6gn6drP@Ne{_g2%-Ebzt#T)@>c%@}(XiMmC zz2nlC7+B2u8YDSs?iPZ#f8^%UL0VuZN$8M(io{dR)AK!!j`#-E-kSmOmbVzJ*n0kG z*KQTkQVt|yjalBq_QO^u@XsJ9oM-dn^o+jEhan2bG!_zVUwpRBI=HN(#TKX24?pnv zxYzRpH$0V2Py1_N#_MFvPZ`7vSrteuIZVyEVZ%@_eXV|OuLf@}`W{)On3TqGxtQmP z>YD!g%)bu0ep|~@WNr*dz#CM5Zz{U^m9cmyI-DaHO^3(O^*`)P2Tv%Vyn-$uojk&&hANMDt~3R z{ah(Lm=lCI(Xh5lh>MAJZWNloHbHW(8X?Y1xjB?+^Kr`SlX;qTxv}>#rPf1thpT)6)Pzbz$JPqxdvk#Absok6;49PhLrZ19}$PQDCji@kR%yoGtPD6_UaKVj!(NX@vQ zg3vxO^p$p$?;9J%o>&bx4E6|%Z&~qTx?W%vPq4d`KMr|cVu z*6J^DI*MObNKs^Du54IvbMv4*d=TP59KWD1ahD?0P%8v6h^_kLFp9c?Q~sVDnWB>u zo`#0T`gkRge19)(owd}G*y6{rK(;|xeP((N`&~SfK|VuCrfF@` zOliOG*w*-FuPs+i=E-Fd2j(lkc=42%GW*S;4Qq!OOTgIN&jp8D!Osd=apZ@N|0FCH z+e}m)wMS@`+bp2k)Wgk*XLQlJ9b1|-k*)8t&5;r~p2B*b1Fh!+1(IKS4O}+w{&l+L ze{oi4h_6>Yb+>e`)Pri^;man(E6?m#?)sG9e51{lxywG3lzTryEa(etOjh(i*y3PT zkdtdJW<>$D#h!FUdwcuVs}q=}sYOx0eqjP;my(jw?@1H-p<3#r@kjn zD0JM-YCCJV#sZ{UHda;)^z_q+C5ZyETLwZac9Fco_Z>+{l7CVzr z-GN*xZ!|pW{?Wm}p0$MmHN9|2Z1#i)7dlWUYj)bdtH%#m9^2L+F=bewbCa^RW}|-| zM$5ty483{A8b9PM1|}xtPb``j+S)ajC+0dnci#6e_AoK>k<0g+Sz6AO4e72S-uc>v zEj8%mJm+`zP!G?Jo=KO`RAOf@Ie$)li|m>zm&d9I8k1k(6<%JM3`z+PqE8$Byu4x5 zj{>1-A;d+@9G*(a%VuWOQOl#J_sG6_%dhm6b`-vG-7P#iZx1{G`X05UMx%)89W*_ZkatfB)~_(gH1Ri@jy)g`Dhc zB{eltJ%#1;%QGfvX=xOgwi>U9PS8EUB2P+U6`TumMMu=1IOV#ImYN%V$=QXab7gy= z!25&!+^?e7tvBcGU*58ljL5ADQlDYAGpFYIv-8dJKGX1Epb|fOxxz`1XN(`;-)GfU zHUoXHCrIa7!{>Z14}G9&Z;X{ca{Lu`6i-u?uMGV=KF@ckX^$<4@9@|#5C#)$V5^l| zkNpBfJ)7}mY{LYqnOXAl_MltvH$26v{F3iq{A+LD4x?l#XWS~pt_U64z<&P$ zo%crT%L+OCq;C=!=kn^Raq~|-f-D5Omkdg-O7?kca|l%eIB!|ohwjy{LZ66`5c+AP z#ILH!plB%!08?vjzYL2ij>Iwuw(2jv&uUA0gj0wXI}P>)wxW_gv?P#nM0hx4M%wjr z>!_=GB*ATlKOd=bdXStQ9ToLdOY06)Ku935ot><8XA3Q;ex~{9C%uL5>^@Ga_CB92 z3)1^CTPKP~U2vDj3BMo^s?86sZc;2d&(|nO_Hcjd^KN2py)uwiz#kEAkjUGfasCtY zcD=I49g08P;XqaG0Q7A+EG@E5QC8p!`1@A{z{hO5a;_IEA0uN@OpK0>u8SRI4!z1j zi({{s<8)wPpli>DKXMM58#b8cE2A#o`m0ivmvY~+v2~FJ_E}#hcc-48?e;9$`kZQc zR)?>y-rtMpE`n?%p{S|IcvvAUv_`rX@6XM{LloMgUhQm+Z-7HLeLy|&N!~Cd*qG%7 zCUej)F%^~DvGK`ww(?bFUQWG`@Opi_DkJkX!OZ~apcM=)_lTdESFb>1z=B$Ta@VLM zo(5wg-(mh#w8=%m`&-6x{ zn(y<4Mjk(YOl5grfS8z=02_mo-?_xn!s0XF*RwOvgUtz9N5@B@q#P#DoB{jyr?>Yv z!aDt>l2YR}QtgJEbZ;3}lGi))Z7M1%1h|+UYp0e%qi& zYdGDi?>Syd?}0W8_zHveI2M48A<&*88zuRYCwr3AtMX@%cbe&LR!W$ESwci!*LaAf zENk@4@NSif(wNF~hQT0{w-M4>nWAk7i*ahwzMz37oazZ1=v2Ob`?lg-LLMjzj1O>! z+MdXkA3CRZtMU!VFc%gUV6?ZeF?gZ-J|3#SkhfUH2243pT~0V=bJ)w9{Q_LLRe|vMjerw*gX1G7yqSm9OA- zobH}n2#=|4jt)IM=PP)Zr{`lDb-h*p=J@R~XXcSVG78b8{l>sW7qL+#bjbg8D6~#_ zVHsANh4+m9=DW)DI3?~UPk!xo=4%-+X94L%Rw#AgQgV23^3xL`vPHFAa}(iBr;Thl zSF4jX-J8ewktoi9yC5*O&Ezg6^QvO}o^z+Zt$9Zj>-YZ3HFsO;B1iQ_vw5?Ebh|`B zJJa$g1B(hl%&LrxwT(;9E9m7N43w1ow!K4m<0)Swa|idC3(`3;M#+|a5ynIo%DjkB z^-?bjkfQ#u+RK7*qjn&>gO;Lbe)UGS8-<}hhcDy3+HwekTD_Tm6tA+n#W7p~%Ep`)@ z4oN$S*7}TPO0h!DFhB*ZemrppeNi&R-BMa?IymRE20z-Mx7Yr`+0pF!R7|SSIh*poBVaUJ`qPAU-R03_6aV z9T^6zbO6kP+F0Bdv44MBj=C1#f8E=^&-I^cpyq~`5QCMdznR2?Y>YiAm=T*$499P~ z<+bx}7p-Fpz<08d|fEsJV`yz0$E~2a_3rSak3(x)=Zd{Dxf+ z2J6Qin8q;ca$NfBe*V4xdP1nP{rAA#i3-Dhz@*ugJuYt@6TZp%U@{bjULs#f0AKdp z=n;ZZ{ej#4&$lQi62)Hz8EY^ze%tfy{gUnA%l|zWXhQp=YgWtrOsSrPx{*0UhxpHj z-{;;M)~kF!D{y+>v2e=i(;Sx4MaGdAre+VvPDRGi1eWr1214W0gALwyg7}V6j~m`3 z{T&*Z;f<(J7hSg9%w4M(w*d|?Ih%_5%6Im>UVQ~I0{<&dFdVM`&(c9Xzo57H{$Zy# z8mC{p8;o()7v;?sH_I|2foZu3U0=gB&%y^D*nXUEShmsB1|NC^71tx4b@_4fmg;gl zN4dulXc9zV+>(W3TkUQNMiHxvQyDSjHQ1kAxO|$l%IdvJ-#b2eP>f5&#)7veoc3MC zEAE@hsfVB4FjXOi+>NmOz6-r2+4B;CdQE|^*iUyEK9S0caisQk)CZe=8#%pQ6ym>q zeq_+er-wQAyythT&*_c5(p25#d+0(gteOs^!q=z&1LsXzMg6F zm=IF8EucN=5%Jp0qQY{VY)NGDOzNdd_(UgK8R|cieAUPI>L7P&2$jFLk8$-1{`Bc( z8r{L7UT`has=9$YFVwZnS&Iep??N7NGad8T>T#O2DC>BMw!E#6{Jm^!y*Rx)UxKQ0T$@xTH`z)n@Sv`4# z`0NxtKgoVsbIm^%S}g4ksztIM{Bp5N_rcpNI76e zWY^YMlI7)h)E{6Q`Wq;xd1G9cJK+u+V+p-W?``+axt``! zPp&k_{08$M_o`-v*QsbaUc}lxlXctvs4j!|QSa{?74h2#5&P+faxUh~H=oP3BN{?7 z7_$%7d8K5~9}HfQ_Xots1eYB={(-NHnYFFEe@9TSI(phR-tYDY4_RJAzR%;Ki#r4! zy9E{Xo-CRsSMHBvGHW~b2)NSF+%&Y+dcWo`v3xxDB12WB0`K*>T&ISqzSqfG(nBu`5>XqLn*hlu!fyi+cDzbr!C zcpjc&|Ix+xbWcw4>WrjKp!zd0vzZ`;z{in8JW*aOv!PWUxt#mfmo)tHASEVxp@3c|*uluJvKKnGL??pj2u*VWDBIPo#CmQiP~tk9fw5 z57l##4nIS^u z4=gtQV0@^B^jAszGsPRQcAtG7d`uFRRg7V&g@ z>5xzDFhbOz3i3X2oc7HNW*jM?r3{&_tas`}?p+L3o&K`#mX(@y@Je5+?aXed{`g)!6XI{mIUeNPOhF*@q( zCIMtP+}DBn8X9bshEPdfiC%>cYGC zg;)j+OA{T-@vg}KcmXU=@e;VdV7)-=m7_W@=J;v4hN%`Yv?O9SHNt20C9ZM9Av!&w zf8m}gmB9Ty`U|yOua?lJjXJD1lcU1c-B%*E#*Gb^Rndq8-7d6r>k_0`0|#fqA8**P zT3~I^jUS3K=A}21H`*CW@e`L`@kWTWx(q5)7A~vxzYw>Zl4XjAA)u=Ke^teQ75(>j zbXsS*_L;@4u3F$W z@vf87Q{F_8r7wVbo~-q7J6XwjDO2RUp_%47dmWTyIdSo(x9zGj(aFi}D>>;3($a08 z(lZo*m|ZXFF@a7O)h9&LODbt;$wGToRd?yk_m5BEN`V_MCF%fephr{f8m}j2OWWH& z%yu(#`SC&qnZ@B1{5`)a5!NKE>J5I^a6s!Zg!2kQ->>aFVyqtTG|Z8!6!PT@!#{!+d-Xck#l>Mg^rfKp zzq2r+Y@PWd%duc8a!L*o?>ph4&Q3X$_yB!=TX*;3UccfJ5ErjO9zV6Fv>IE?5jkfW z()D0NSZ^IVq7-Mtzot5HiAEfbdC*|M zgW=G4ooV~8vf?dV%=eL}lz!xH?q|Nw^5&*|*N@gd%D0JnXXNh|_?(C8U7ie$J9Mz6 zI(GB1>Qu#n4t=}T9)tf4*T`xtMHuRDXFY;=PwiV}R;yrVmdw3iYq-F7>po?Hi6cpJ~d& z`haIT!+R4<9>BH~xgrf693AZ`v7m=MtUDC)-ib}$o{v@BDX%{dFYsJ=fD*BdjE(m- z>*jcoCm_iKebodv$cc+C-;Z*5I4*Vu>+N=*FfuW@eAm-UTZYLFPZ&DBb1_R=KaCO- zK{jT5@F4VM=5xH1+lImgi-3e^#wfSZ&ptYOV7)a@2KNeX)2ECKU!RNJbkDgvQ~CqB zuYe0MJ}W7Mq_g2oA^k4lhZQ5sEuwtQw`VHD`ol}l+Iw%)sUykV9c z2Q^HQ$X1%&lJxVi2l*9#z}JC!5FfSaE)G z%Ri5#?gEXI68|(u;bS{2^pTPlgG6LKBAzbu;?;;*4zockcJ^NkSe^z$HP=Llpc(C<&{4+yO^6o^{1p8Cb8EG#WiIw6`X2+7AimuHG_x`_NWh~UkdT?H6EIL4Om_VnQ= zxnj-YMh4~Ep_FrASWv9~aM3$|e+0?hgNw+ZtndXI5@%2 zGlAvW1vALbJDRh%LLLX8x&=*bnNCzWfmjzE6T`)@yF#PFv4V+*F z-un;GfW6vw75tatcE$_Y2j#{=F|4o0o;* zOBQ(Ra>=1`_ActtLjtRxqUq`DXm9^Vxc~io+7E|)8VGfxmXORM0^A44sqmHxUnL2-1?~=2n2Cn%FP3hN^N$N zp0x06bHRh**T^#;Fvu`x^>T+}(RfAyotFldmKny$yA70{YY!{#J!5HsLyc-sM~SQF7EobAk3$ zS(%8V?#NKk%F^1Jks{oAmo`DinLIh$9;T{QkK_J*Iw7HtgM))MOPO(W|M(N#Q@<N%nKg^*3|N$0^Ara{2-c z0xpvLp&>?c_KZWNU8VMNl>)d^z(&w)_z;zLh!h2Xwtsj4Qx5g3NK3poDFWpRs;LnK z!f(QQ+ymxz+r~ z)04M%o>N?HSF*pXek*WpB~ zhUv!^&<#4EBt8X13Qx8MY-)l~YLS?x5HA>4ujqPgl)1)DJ6EF?T;)Q%mMau!m@pJP zN%cNi0eM7OORED#iF$hrqdZrDJZOn;*rO7L=dlAkZ1C{Flg}8dRD1Qxe$+fC8qik# z#XbjWlqi)6uqvQ%@K&KgOgBaPoV`Y+PgsGja7mOcp&LAYD13@CG@>*omvMV6l!p{t zulFdzxd6~pyUpKPU0pqbV%CDPsDM!-&^-AW-7UyHb3?hi6c)+P4Gj&?4*Q*`(tAin zmh$%npp>|+e#`lqpKo%qw{qkujN3GQSbr&mvK-z3YxdK%YY&P(M`uQ zZif!pO<x&sgL_{zU6Od7b0-eC7Ar3`!#;#(>u6E7R>%6vLWA_*;UCxgmVRpRZmLEO7o91BY zKxouMRYk#vwS8~^2P%btd~k8LB!Y5|Mn^}BLR6xBa+nu~LOJ;>VoFMczt92{Hm_2~19i?jRguy9<;m+8R#2~INSt;q>%E7z$P2%bAZ zLt9WP!-opMTG!*j{@?))FzDvyE8g|CuDEy2<31!1g+K2DGsCTBQfje7p2P7vFOTx5 z{52%XsR;$x&+qC57)y~5 z9QN1gBh*q?v$5lM&UIkg8P7aB|EO#lF%I)M#}DEisBz^f@U)9TXVYCPH0?>NI9%^> znmjz3TvzBz$__Rl12wCpXKlz$?$xVTHL*563$iyo{rBV!o%$71p8SKSkt5G)CuqIS zzrLqy9-TU*!fv%!FSED}A%pDxmfxg^QhbZlt)4D<(TeUJj_&QB=&uSzo!}juMik%r z;`_drd7!ST9ZhUGqoJ4;Jm0znhhKlY(M3zu&|6IXx)0qR(ltVc!?AQ|>uGpj8vET+ z3M*`(RK)Yu^-4iaD7ju2zdusxNv_Fzat{^gg{zZ#;ptm`@wMi-kKNcC(D!aiR|WX; zHneN3-s%K_-B|d+Z}Ck`4H(5p{KaFg(WFw#W7dckuH(~Ti*NbjcgIu0QTAkPKriT&S2rXA`;dcI{rei~|a zsFZ`me$%}mBR@2X<_$(~yzfr&re-qldnZ#XnvaHUKu?Kl3h7^)qBd zg>RnX_yG+|P^W$+bPG6-OgvrL#fBTpmTX$01SffPW%bdzKS90g{Vqr=>tx9M}Na7P~iikN%0Xku9A?gx7JIKSROtHJz)r7DHolG5? z4p3&_zF>aFNp{wlHh*h0y|<4$94w|_VhVmnH|~A90j~czCFIl>T{C$_#6ek zd(VhPeSwmiwISC6{&n$K@7{3UMKwl{Jsc;ThJuUho?a;cNe_(5F@UpT7-c~ZGX+N} z%G6gr<(-1^`$5P-_pLQ`LIRa^X(2)Ho{*5&QHVOx6`Hfh{oL>wcJkmZ&BSH zxS>M8Cj}mmhEntXKo=a5Ffd|`LuD8T-!95yI0Nlt3n#AkZpxG$KoPsH$3u2=;XE-> zQ4J_miE@IXT!B1w$nY6b6MRvbT$*kUk#WF!wn!$q#J5T}AZWp2PridCu<;o?Evr44>otOHTEv`uN^}>vOT>a|HVg+EAWAaM(R-(EH-3bfcdeTm$m`%xrANV5U4Uh)1n1_$Egx9hs`~Unk!K<=+@uPe3Us zkOO@QWT}C|{e~tdX{sz@*nt3;6gZW+f{##vp{YQ5HUI#FM-EzSW#F%%X##6Ih3d*y zTCGR0#A`FE!}up}8FeEyuF&B8PF9yJe*5@fJ&&yPE!H-#!P4jAKMx*YzYBUq7Lufd z9)x3jvy_&SMXD!^mh!+#9TG`v;v3*JH54QXZkGG+)6Xzq%nU!n(-a5Esgd(JP3P{} z?AvPwP%H<<#jw7Ml=Meidhza`kI3vjz(!XqJgCg(uIkBOE}-t3)I__f|D8Qh(1Zya z{kQiAF}|D0PbxMf%KV$Z_$p?p+{mJ=p~lZPKS=&W)3GBw-WS}uCV}2KvrQmyGq@Vl ziOEb~>&ed-ycbXLaP8Rlo`UVm_4cP15n@gsa!<}8&q>(3wRqdLR&6x$2lt)u@-ne< zzX##Ri&}3_)a?qIxmS}te(EG0cAH}KLgl`ATVr8l0RE3no4dt>(YqGup)Q<>?}!Rc zw40HfpVqz|mZZoE7IA6|6%0<{ACzJe@#AM;sh+03UG>h*rQyHL!AhBTs|<0eNcjZ6 zW{PN8yy>&DsJ~$8eNOx~bIV!%Ycrt@#7@^6wUv%le&e0otwCP`!A3J^MGL@l4;7^Z} zWrl-kPnnbRwpKS%n^u&!@p?d$&^6o}S@V^cqGXsh>L{9;;{PxGUBS^~mZ7S9iI%0} zss4FwO5Asjm#gaTRbehWN~|%&`?G8nndr25*ueyQw*-jAlx3o$)4GrB=U&J}r=~W4 zeM$fRi&d*VnUDps@6)F?Y2yAY37>p;++<|9=6*$7<9?%)^Q|&?W6T9NsT_>MN9V%# z?-Of^m^3jmG1`yYE4!V395_EYyVzzrl2%lFeHuaa_Q}^B+$P$8b|9g>&F<(FMmD@B zhvp<~rGFUVg#}RVb=PQ_>$nX#qpJhzPTfslW6o_?)5OvJlH6TAj;#%F6%Z58XRh&A zQZ4nCt=H967woF!o(qA`%fcf2ixFv6K20I@#{w6&4qyol&UjhJprLZ!WX%9Sv*g5~ zi;XyWBh5aw`e-Y<$CRI+=jf;(gl|i&GP0Wx@EBSmmm61^lM^&r#U-vxWlsC>Q%rn( z2XOFk0cyS`0SdansbwuXGiv57;*@1TpNLb#2fGPGJ$ak zQs5ZEHs@<$RPAk#IiAbr>qKTai0JtEz_E?&A6EDPjiAGW_7^r=fHUj0z)jeO5dMPs zFZ~~s)xI^tkXxQ!gd?)E6ZdH*B0mDUo`3e3DXFW!H6VlX6%y+5*_?uiDXet^X*VAC z&1$OXT{L|tpy-UOEb@MCFl55RqeE;IR+q+|oVWvn0QN1|u9O5_ZLj`P_eaS1c>Gno z6n)L;G)6%yyL}|M&K>|W!}GL6nmBP|Vy?~`nWFYWDXHo8B=*s_b+s+_ho=nJ7(b8* z*f2z}hO#K%d#SA4bb^=OJ3ijHx6*2`%rC?8N2#BAOu4&if6cy92*sLiH_Na*kD!zm z7pM0)h`COdzbaghuQSxv(Uq0Q_WMLpI4eItZKXe= zsd&R?0UR)Z`(;>wrDeH)->5%6&uY9Tsb-w=#*H2O%8AZI;c%)JfsyUDoW$%%m(rv!DE-7Ry!lW0Rj~AB|L$&qXF+Z)8 zPv*YW#5upXCjRr|T6O5#Q^#6vs)6?|fd^QkG9B%(0S7H^o!z)=6yLsDyF!j=3?VIN zwe`D*?T(MwRo%$3oJ>h6=6JniV>n&{_WFS* zoS0-jlla-^mlP?|s=ch`Nq zGwpFGY__0_Hmk-`y3xcrTw(qwAmEx@`V+ihpFcf3UYopXIz#5xmMwD!pAPsGK}2AMT|yI*nOO$OCTHW^@}Vwrd=X8Z zEB)IQ6Q!ky*~8Ce1 z)NZw^{7jWoywvFEZa7EL;dRjuN^)c((N$IMgWjbPivQRUo2L||r86pAnQXx~gs>ii z1>kTNC~PM_8McK94fH8qVtFd2OheW~8`%0Z}IoIV_ zQUn?h1V20NJg4tt4!$0Yd<|={txft%PEIs2cA?3}dtga&R9?NJ;#Aw9^p=&wZSLvc zI=qE@ZQHhr#rI$qsJ3BYvCoT)4 zmuHT1t&!l0j)pBpCeJYeU%d^?H;1PAO8QVo;=@eXy@ByAL-@{iObj7JjI=zJD72=J zKyckSAP7YvHrU|@qysSt$tRW8X9SXEOMSt?NGUX0if|=mtq%KEdB&gVPhrC=Ae-Vp zTzy+_C4LyV*3?~M=`U{xeG%KD%ZCNe$QS_7H|DA|@zyv5I}o_AFWAh=ijE`{*cI3i z!@$TC{qcjmtRs$mm;AHLhohsTkgx7OcoaKcqutAmuo@BLrf6DlFc>4r%dzNHCdij{Vtn35m6>?W802T!V93RyP3m=yX@%Q1Oe5yJ+UNs^O zYseQ`YD^^+?x=myZ?s9-q6EdRBnB!tI23Dt^bV@5=NY&V_TXIDBL&^dW2en(vN$O| zesEK0#hV7TgBJEKHgb2}J>EPY6z!kJ`EgqGOj+5{bMNUETRzD_{}opPo=G^tR~!9~ zkp0{{S+pdfcq=Yj<*7|C4qyMt@Z9vp1CTr)g6oLe-(0joP1nbbH^Dvn-pxPr7kY>G zawhIr@yVV$-DKv^1!tap;irtIzD;U-VY2{M`54JH45~&(0r$^JV)ekH2bh zY7Q+fdQ}8^$DBW$KU&x9e+*^+>ZXj@jU!a-CNIJSwv9Ula|$ z$sf^_*p~^;$L3-y{-qo1EF3viRVMY-4}l<2qJ3(qr4>2xz+aqUI$w74w_N|l7<)oW zVBmAu@+I2Oi5E+>M5$09peZ>+RFU(qD($#!x-P$c zdc4lTgC$?%nHb;U8(E_~IQ`t=QoM3noWn&OqNiP&>grN}{!}|Z1JKH|&I2LqH^h%* z*i*g`p@jvgU!SiC*QbNJIcr~SZeyMShmB}x7=1C-AA3Swp7N2AaiSZP6$crv$7N+? zfeN$)w3=!-r8ot&BI)|f!!s}05L?XmC~tsUVW=+l^O!tsloX_pYUhp3*v=yu z=N5-}r3ZaDU75D3E#UEgC)%{49s>^FnAn&xp4)4~yjJaTZ5UUB!8@N6QtOfQ(2D{w z2ZGI0)#vws^38BHz1}MS(Qjx;JmaCqpd6Iv<2Q3AQ1@c*$$!bM0>d;W@F&AMnuBw! zR%6+mBI(Ji6uI}mv#>HZAVdyNAg@5O1JyuIS@}_awn9s>6(Qjnq_h%KMLxK|-A9jN z`!b)m?7Fv_7o-?#91)=?;=e;Y)4Vs~aL`!;pqynxnwra&GoMoTROCZgmjJ9o45~uB zlZ)7}raZAVp3CkEqkbIY-;7b|#DFEtwKKimDW?<@J6Ab1*n_wg?2mL6{KCLgV%%YR zbgmmWr=N)F+x(1D(twN~medR8-yT~&PgzZXrVL&kem%5x2)hefzedwv*}p7zVJ`}& zG^M`We`obXTAEmhP%=(RhQ3QG(``&@5Qo0-HNBLAJ$ogF)J;r68ua-n%AIWrOh1P0 zyHDAr_2=WXZi+fcbK1`iSC5prP}vI3ML*v=}RH46O`6iY6B5b|gr9ka>e ziLB1R`Tn8TtBL*A(jQe1Uv0LD3J6q#VB~o>l0n+FmS4CaL8+2tH95ZJ*Wx|)SH_Nx zv5w;J-~$BSv6!#t-S_^@fBtZZzk9g2xMb-!Tf{tLM?**`oSsmv+^_QeHnGHv&!s(% zM!bEs⁢MNDc6H4m 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 literal 0 HcmV?d00001 diff --git a/AppRateScreenshots/screenshot_doyoulikeapp_light.png b/AppRateScreenshots/screenshot_doyoulikeapp_light.png new file mode 100644 index 0000000000000000000000000000000000000000..fa38c50252258e74b57f958fc73eeddf8466acb8 GIT binary patch literal 21326 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�x|puH*(mjNmT>U8*Q1<;PzgNGvstZ#@x)Kh?y5Q`1M3!pCz zz#kqktUj#!ON3a#Zrr#55e6Gf1=ra+IqOd1B?E~Ia)D7K+VH@@%DPeG5hL`h*b*w6yWOnEqJjj2nQP<81=Wbg2|no&yiD5zn5>j4K~3K zh#?I~cCgx{c<z!0?VEF|;Q z3s%1^jBK~@G65p90=EqM7#iYxgE}1#9*K{T8X+=&T&4AT26hi{8zg$~kAB-9vji11 zWB6te>IUMokr=Sjh%t`5eRAegQc~guD^hc9;%_;_#!nm@STR7RK;wH@X{f0DQ*Bob=1q+ByS-T|gm;a;8~j6;`9o?{0~#wc+tsuTme-t}Jgx=mWbAVkICE{gzv$jHr#I+?Xi*c8Nh1QOsa)GAqw(r`5Ze88$D z?dVka?bkhn?o9-3SYk?qQw(-wth)Ki%3kvYm)2;V=M(rv+sf~EKy3u!$7YzN%K*F{ zF5f~{KT%sGL`5`5goPObG~!=8P%w^A`8MKZ2QFSXd#dz9>f-5&Jpw0dHruohE@F(| z1A`C9v~mfuIGl;37^WI+R`E!hNyD4L_|z5$V!Q%fkfcDFs?n&c-zX$yO3^1LAtQ6u z5*Xdv1ot5Cg|~fgTadt;zb5@ED#i<)(TL*=2~(Gs*{cL&<7eJ`BoPBlPsiLI$r>(p z$00;Lk*!tWJ~)S(mz`)-PD47?$xdp#k&D1O~Ozdf?B8n)`0S>2xX1=pJogaSy6 z!l`}OvInc6$^c5PjTTcR;iHMH+gT~g^U88Rl9MJob|a*$=F|COUF>5O-H#CG^~8SP zsFV=t=ii;*9VS$^q)G{p>Ap- z*ZJ%Be`lq$SoRs6+70iY5Rqcc9@=NmTN2zDiWIFXZisBxBJrm?jjE^UDexE|7{2tE z6nm480MYl>pai?@!>1J~{LfKwQYz zaf00TM@^9i>O|+|(U-O7qxS3)zJ&wDq!)WGzE_!6}R0h#B~j+?K(68zduO#{18_aRAPE#tPz_D|A$A-^Rb=A^X<{@Qo1?C zKQ1?rw*ToCVRaB6#u~SSKg$Pwa%9?~E3K&L9X9dZt*sV4FfhY z09)NcNY;aIGfcr23 z=@_trYQAP0l>WGP_PB0?71Q;+;nSqc+E%{9~=^e-tjr0Da3!& zK77Ynr}B!I@YP~vl{PNf@xPYwE|RnRDqn9~qzcybcpvGi;Zi$h84ewoiFwJ8au4Zm z#=6baJ{Uc%`g4+K|QT#6v6R8~kD@F0&!ebz@NEQnF zTFbk8x3RKn%$)0LUtMeYoS!e796^^j2eTw-Auau*K^4r>__L&eN{Iy&(E>$ue+`kl z`1hwZ-+KCcJI!II8gADjq!!=6IUeY2Tv)aS-cZfvm$p@wT^_elk!NAz>Djp!7v6kx z!-$f{CadJLIZsZC>qVk3i|TWxmPM_F`tZ%cAQKRei1+l#=aAZ$Fx5ePERj&3#t3Jn z*yqecStSE{Kj0NU14MV%g`=67lOwg#Yma|m<`*<|LJd3(80nfS?gA(VmW~t(oiv5D zwe_J_y?}26@FCFlZiR#GC>CV{5G^-16dcNzMuv9Gz$^y2AEJ7#%E;Rf2oq&!9J*py z5H}eZdSh>Lnh;`PfCETGMP;1AwXCz)PEDG+G?|@gYR{wF!TIc~QeNIFbm39ZNJjLp>W%E?PW%0rUN8tSEB9N&i-u=Izm0*`2a0IeFCNqdIzV{?z)BiEHB);JET`HSVq)+I z@XfyT+P>1HNBF6$4T=-Yum~%XKoVOWF3bW;AUNNE*H~k4q=rU+U|>Mu#fxUJiUH$U z8B`2|TfpOF=jMX#6?#WeKw|(H;q#DLDX?kO6oCC(SX*2B-u2<(VI>`%pWpy2W)9P- zby3vN0G}Lkd$TPeV6g;}MsK{r8l1P#g+Z6oT*3@fP||GVMgYBFS|b>)`XM1f8aiem ziosF)0k~;p6=Rstf-e8uSPuBW4=ey z$^*KA2CUBWfWvu386Y~+$9wLtrIwX_1b20@aTfw}VHOTy`k)KSluLRJLsqb_rB~k~ z0QkX!xwJ4=Rl*82G(SfY{%0 z2*)}+)YDLnyo|+O$w?9J01W^%5on0z4w)t*!2xUls1*D(BOA8Re*>oj*dI7xAcWOp z+Gd&pZnEj2#b>^UZGeBCxN=b8E5XECwqiOO%=a+D7XJBNLqNkvt}_fqKjXg7LcrR< z-qsXEefkuVY5sd*p?_*>%Cdpi#Cvyl7u-HDcnIuW2uK>Uc6O7_!?SkW(Ba&HLB5pU z5Mzz~#&|I2b8UfFH>a@BbfU^0xK)S%*k^z?VD^EO{3R<3$~@3nknC&qiCcpNU|m;> zIpQ+S)%qg5zdxgE1kw${8o}5&L2KyA$fOw@5Ln~qTolH?zDPmhY9y7lMO|Ts#^sIZ zZL6toH@ix(f`kDxfdz1#&*@YUdJ>q2WJ!t7gnPuoxWu1n7=JfdpOB2qbcyLP=&lq9 zj|V>h-gbWX2!Gr*Ts$4{2uxy8;a>*Eg*W5jMv3}NVcW5ZiOGwXFCh-guWG`8i$;l& zRHdRBSVU`GSVl)j!P}k$a?Us1!ZUXmF@m!&2SWz>@bF)C>*6Kpe;L;BKca`(3xhv> zsqpkbiy}i|!TQJ$jMf+Gt9j7DgG-Q9e~lBx1&;%@(MDH{8UIt4n4@E<<t}49Sf& z_zHrV6-;&k5IpZbeR5UbUapDA%|-U#ytU>ozx!iEh)Hx<%57_$3dEEWzIoMNyh1N#Z!ydtBkvoj66YThUN@8jd2 zgS!lnJ#>r?j*dCm*`L3D#d`(WViv{%LRugwfv7|SZdDc~DJNGEr1WNt1{ZZ4Xs zQ6E2w0-}SB1=A_J(GS83+i5xIT@1g!g#o_F4PH1fvA|nhl0|U?;#5?L1}k(LBP2D@ zW}uOci4g}i0dSkubbS&GUm?j25V8O8s+fujaM!Z*MEV2SijX+L&L)=?1!MqNfZ@>J zCBcC%7-kYmBwAe8Mj$mUf!G1&YzSP)(m+Ib@_jZ`|MM2LT*fcBus?2FX>cR6u1*KT zi{!EGTlyJOEOVvLC^r!dI z#`+@$aDUC#+gjD@(ge}{?X9=V5&+u}WX|I6{&qOTS`iee92UJSl$5ZrKi)KM^ZgAT zSE{!Iygr1UPm~D*m8QKn=w}LOvHa~;?jYtYKqs?CbW4|Ug?)*w<(DqE4vRp+Qa5=jK8dird+7 z@SJ^>X-+~)3dPU!2PTw7IJ+>ny5gL|Dum(n9B6}%A3yZq7(+1!%?#*UI?yUn+eyW; zUA(HNBhH@_j91<8LX9=Rw+@j3B?NemgQ~xeV5(*JXzk}OUYaB#=>|&yo{jYhc7E3Krm_AmIw z4J@fAvlie6IHG_GpzeX@0D=uR6cLyFU6J5;kP7+lW>If4mKvy@NROj z-cqhYLnCTIz83)TI(Ol-alCf6ARNChH0%tf?d>D4efxBfyV3wPKwbv=sPk8bbiZ>F zLassigXR*D9v+kG*P_T1Z7@S4i3Pv}azxJlD(&p-0CQ;sj&_7zvJH1mf`@^0+Ya?~ zwBEbcdONM3k=Jztv~EWb@Zh|E-&yDa{IRbg2A*@7WWG3PjUQW&8F^x|qw`YXYienM zZ65MNsyPLGC>=E6NCHnu=>-J~9vosN&71-lQqb5T5%nT&ZV-GBI0C}g{`)+C^_i$C zf~iVdTEM=snP95Mg>frjJwOP7R}e}a?)`*04VD)=7&bh39heZLJIz9MKnSg4!r(%< z-{q?%VD;CMsVSIu;;F5kyLRmw_`*Fc=~H?ofLxt?>B3C~BnJ$WfT)f%#TArqLAN-m zpPMs4hC31eFD+v|a3Iiy!#Fr};h--8s)j-1Mwelj?1$Wnv~XTDTcyEG4dvjLnLpqvfKF=33O@@gPJLHt#8V70G^DIS7&wzjHOVWmIU`X*^-tUvdA z&(it`t*nd;Jw-TCxHy1Vz((+00w9IKMM~Ya4dDGi(tP~%sdW3oc2nD6JbUW#dG}$= zi2d4kXI2+hd|AhJ7OsqI3>eX*HLog!S1_?jqsLg^t2g>fH{=ps8n{A4`RoQ0Jt?!o z`v(eAwv6ThII{7N$;PFMqPXm-mR7dCO-@<#@Lh=RF!N zM6vPl{(}}!Np67m!fyE&0|egiLyo3gh2S#RQQ6POe#mU6po4nM#Y|BTIN*^V)80L9)?A+bcW8mOG1l+qq-XMJY z1;`qh5Puj#&p6@&Rr8Pu2qO)XTLt6m;;ybwaHSv=V)$zLpFFvm-v1hgnF0T&=H}vn zjswGX`lZQ?p;eAc_|VUQO(pW%H$Dg;&edOU-eAKArRC+}0zo3(-K8X!gC(D@3e)pV zOS`i$ZSOm-dmgQGaB>D~Gy>_Xrly9ChbQ#t$lb}=xp*tdE%5g;j5=S)W1EwtsL!R` z!n%Zqc^SqwM%Wonx#DDitdd|PX>M#pyL<1RqN*xpR0l@wWP~LBB?#r5ocoa4fOsM- zVQ!hV({pnp4+sbVId`PQ7#9GH9ve9u2Z#UivUx>s_b#8fgaou2_;tFy&A*H|-T*lr z*rHF4hxs-lBCV{9WO8y6?G;Q{k@EE#8W>!H{Y_QCYH4XH8eca9m2Y$v-e7{!v&#p0 zhF(e-w5hMEOdydUgA(!ahybRo{T3RX>_H2>YuB2LIGQZVo6We=8X9OpsfBc1G-~zx zq88JMXL9=T0)Xc@-c&j)`k6;2pUDdEeA=y55pEwCei2#7l~Cwn^+-@hh|q4K^9B{n zNByLYo#%c`3G->fALvPWOphnphEIwFnmR3WJo{S(BR7!bm}FN+>0EA@Lw%$lUZm7k zGFCj;`q`-b(~0ME6W%B^wG%CZRpM{IK0i|+3R6d~(~X3&hLQy77h)=EYLzwza>Vp{ zb1!jrqdm(%IbEtzduo}AcS-2oD{TM6!q2%MG2Sn9r7~E~z{06Bi!Xcok2E$%)0?~d z>V=Do?5AP8zw+hia+XcW($bRBDxoN8zF!AzEL{otbA#&`*s*l4FRqy1D%-)hCPYX{ z95MfkW>;nxC>B4>*L07$bL8(76M7VHGQtlDcCOxi-Ht`X_RmMtp%Y^WUAhZ@-ERG0 zQI$zDt5u1Apq6Cmk8xUOj^GgjNFNtaZwD}U&Fi%y72q{Pp*$(JK4xv0V|(x`_wXq5@Mj= zjk-U-_K2T9985d2gK96mf6qBNIy%BZGBY!K#TW`rjb-v9rNV@H?m*#GhM>LI&hdUq z4PV+)QBnJzd^GJ4)cwDH`GeR)a^uDw`gQz}{?SqFB)O{^G5rGr7-4N6TztZMuc4JXXcTy7`+x(lF$) zVT?rgg&RLo|)tnF*nq z9k6(`+eS@EX;^WOs(ltzUO4m+n>G2VMynwK7STeI7E)jStNcG#wh*03XO; zk%XZGg3HA|Jp>n>qLNYo;I{7G-g%gz>sxk$k;7of^&%pdp_o9YM;I;+&ulYU6I5OO z6a;fJAhD3b0D(v^1z%-@-n)x9X!MHJ?EvC1xa4wOMp3x6m5=YO4ma)c5xv2f+vdin z6~NPoK^Tuy4Q76tNZ?-Z`1$z>#jZD|5Cs1yc^e#z2||r3en~1fSZU4htUC+uM6>aR+p!*J-a|!6Dk`LD-SJ z8#Mw_FDIr};_~{&MsS;f##~;)%6TP)KONnB$;Ne;mIVhe&cIA*8W=Q!bUIBtO7KcY zyJaerUMijXx6E#pcnifC(-UEnhl{)Xe4G&e^Dh)|z@lt%GTlGC%3BkeyWq~PW;o#X z3*9n`-m8l@{-yu5b6b^W9F&u0IJAxSRBy%SOU~=k7!6!pND-eFu)3Ek$HT$6^KGY- zNxEdBQx6#~g{?wH^9R?H7Wl%0Lqec9MgXM%5CV#O%jN-8adxGxfj~t@5(CWnxKsa6 ztGIl{PeX!(`%tKsz|rC1t3rfOJxA7Z=@S5L!B3SR+yJNo z1Olj46>~HN;^{(=QDJIi?CE{WHV7}^Pd`^wAjt>PfG8v`O7)GYx-bPsjL7!Og~Nyf z_;|+2)%6b1o6nV%WS9Z^ZOy@uLjvH-!oVClF+m02@5IK-iyJO}S&`&A7RJoB+l)iC zdYUZur|4Bxg*7o=9-fivE0_Gre)ze)mI^-gD_*mjKRD5^93RE|Ix(R4I3X3a3@97E z&j5^;fLgRnVaTw=?lDbdsZoq(zBtsAzCJ>rd=XSoUoY@BGBQ0U2OIcdms)B-7?3{k zLjs)L0-9a{7y`ltap71!i%m=nWDJE2X|A6&Y8BkO6fkMizO}`MErlXtkJev9Yw!Sl9dwVZv7d-0vG_QMs&zFp>rPqn?k(JKru0ijN zOhq!mD(=^{Vci-hY-l5bMy=#dF8t|0?zq+-N&C`erpHMjXLYx2Tq9>VvE!Z_!}RaL zv3Qe3!SQ}Qwjv`M<5V@X?7;|@VMR5bdT!?4-+2i+>F2~R^%f52`uOrQi!_t^Q@Bw_ zUl$z{LG_)eF68>0KQz>eBgH(o4Vee|nhNvi(;I**@oD&eRMZ2SC`MP@px3f_+}qKS zirKmEb?p)Q|KN?{%tv;)f@}y-(TG7MOPO9$%^U2RVwNXt{eByeSlcf?`SV5u@T@PG zj+xM58O*n!f7a5*x-Fgh_QwBQ=3lTyh>%{-pH8w7JeIH%GJ@@%$p}28386G6T!G<$)R*c?}G~40Ocu-`sY0 zc0hjcC)0I9M~q%j^}m1rzBTDOja0nulHdPV4`&yXWE_QYG`uPErVpVhWqi0rQfMSH zmFa4vGbMFxq?x8z%Zo>}`#;kPriLUp!_|1da&&DLR^;^}xO&4h#mGpyvr zrKNGy^u#A3xl=3_mq8Z=L>28l*|Hm{2a7hF9t>w0fSTXFbbn{L$W)10t87_ zX4=(as00iJw%81==t6!(>Nqz#%~Y{qY!^Y>Oz8C(p6tMavoNroZJ)>5abr0Pe;nG} zzR@|m8K*ULtzqzxU!}jP$I6#NrFxM{5K?63bJ*loUXTNBDSr5Mh+x1YHPbP%4N@3m z4ySVleyb>wX6*7y!}bN3;WL7`D=F9PtJPQF3sq2+Bj8&k;ZIM84vK}e#TXR@1w}HDo3Eo9)C{y`@v%d+q$r~Fa`P@ z0&{Y5-bXLuk^$(oa>&<$q&-21^IERWw4o;=w`us7BTFAnSyAwy4*gccWrF;z6SwK08iBCLVR9G(06*PRqn2SISd!unWV-Kj^=x?1@% zZwM!t_&BardDHd!%FAs*Xz`c4q(Cx@#X6(i?tWo$SU#ike&8ot3k2x!V{>-(lptP( z+m=a(_g6jN6s-KDP~25(eEDBT^LI~&hv|{Gu08m+_$f0^ar7hAB_{|%_Gd+!4l0-3 zW3&{w*=d)s&PgP~tl!XVqiz&GsIH!Y8#O&pLaMK4-c#S91v5PA;(uL2T_{kO9+Bet cJThZT*s%KQ{8Z!s2g#SDxYLQJG_jeAf1sHScmMzZ literal 0 HcmV?d00001 diff --git a/AppRateScreenshots/screenshot_sendfeedback_dark.png b/AppRateScreenshots/screenshot_sendfeedback_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..38c7844171759c16655e7ad3f57ad2f368638b5f GIT binary patch literal 25787 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 Va`oQBgU5^e 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 Date: Tue, 14 Jan 2014 12:28:17 -0500 Subject: [PATCH 7/9] Fixing typo in readme and moving screenshots to the top --- README.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e0dd7fb..75cbb87 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,18 @@ AppRate * If enabled, then the user will first be asked if they like the application prior to asking them to rate it. If they respond that they don't like the application they will be prompted to leave email feedback. Both of these dialogs can be customized. +Screenshots +----------- +![DoYouLikeApp Dark](AppRateScreenshots/screenshot_doyoulikeapp_dark.png "Do you like the app (dark)") +![DoYouLikeApp Light](AppRateScreenshots/screenshot_doyoulikeapp_light.png "Do you like the app (light)") + +![Screenshot 1](AppRateScreenshots/screenshot_1.png "Screenshot 1") +![Screenshot 2](AppRateScreenshots/screenshot_2.png "Screenshot 2") + +![Send Feedback Dark](AppRateScreenshots/screenshot_sendfeedback_dark.png "Send Feedback (dark)") +![Send Feedback Light](AppRateScreenshots/screenshot_sendfeedback_light.png "Send Feedback (light)") + + How to install and use ---------------------- @@ -63,6 +75,7 @@ new AppRate(this) .showDoYouLikeTheAppFlow("support@your_support_email_address.com") .setSendFeedbackSubject("Subject") .init(); +``` * You can **customize** the send feedback **email body**. @@ -186,17 +199,6 @@ new AppRate(this) .init(); ``` -Screenshots ------------ -![DoYouLikeApp Dark](AppRateScreenshots/screenshot_doyoulikeapp_dark.png "Do you like the app (dark)") -![DoYouLikeApp Light](AppRateScreenshots/screenshot_doyoulikeapp_light.png "Do you like the app (light)") - -![Screenshot 1](AppRateScreenshots/screenshot_1.png "Screenshot 1") -![Screenshot 2](AppRateScreenshots/screenshot_2.png "Screenshot 2") - -![Send Feedback Dark](AppRateScreenshots/screenshot_sendfeedback_dark.png "Send Feedback (dark)") -![Send Feedback Light](AppRateScreenshots/screenshot_sendfeedback_light.png "Send Feedback (light)") - License ------- From b4f2f08c2bda10ffd93035f900e7431d2b55ff94 Mon Sep 17 00:00:00 2001 From: bdonahue Date: Tue, 14 Jan 2014 15:11:42 -0500 Subject: [PATCH 8/9] Adding support for a listener to be called back when the app rater launches its first dialog to begin a flow. --- AppRate/src/com/tjeannin/apprate/AppRate.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/AppRate/src/com/tjeannin/apprate/AppRate.java b/AppRate/src/com/tjeannin/apprate/AppRate.java index 03af952..4684a45 100644 --- a/AppRate/src/com/tjeannin/apprate/AppRate.java +++ b/AppRate/src/com/tjeannin/apprate/AppRate.java @@ -54,6 +54,8 @@ public class AppRate { private String mSendFeedbackBody; + private AppRaterEventListener mAppRaterEventListener; + public AppRate(Activity hostActivity) { mHostActivity = hostActivity; mPreferences = hostActivity.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, Context.MODE_PRIVATE); @@ -238,6 +240,11 @@ public void init() { } else { showDialog(); } + + // Notify listener that we have shown a dialog starting the flow + if (mAppRaterEventListener != null) { + mAppRaterEventListener.onAppRaterDialogsShown(); + } } } @@ -473,6 +480,19 @@ public AppRate setSendFeedbackOnClickListener(OnClickListener onClickListener) { return this; } + public interface AppRaterEventListener { + public void onAppRaterDialogsShown(); + } + + /** + * @param appRaterEventListener listener to be called back when the app rater launches its first dialog to begin a flow. + * @return This {@link AppRate} object to allow chaining. + */ + public AppRate setAppRaterEventListener(AppRaterEventListener appRaterEventListener) { + mAppRaterEventListener = appRaterEventListener; + return this; + } + private OnClickListener mDialogOnClickListener = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { From 7b732265ec45a8baae2a21704998f3d919c65f3c Mon Sep 17 00:00:00 2001 From: bdonahue Date: Tue, 14 Jan 2014 16:11:20 -0500 Subject: [PATCH 9/9] Moving some strings to the strings file --- AppRate/res/values/strings.xml | 3 +++ AppRate/src/com/tjeannin/apprate/SendFeedback.java | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/AppRate/res/values/strings.xml b/AppRate/res/values/strings.xml index 82f232e..226908c 100644 --- a/AppRate/res/values/strings.xml +++ b/AppRate/res/values/strings.xml @@ -19,5 +19,8 @@ "%1$s Feedback" Please enter your feedback above this line Send Email… + Android Device: %s + Android Version: %s + App Version: %s \ No newline at end of file diff --git a/AppRate/src/com/tjeannin/apprate/SendFeedback.java b/AppRate/src/com/tjeannin/apprate/SendFeedback.java index b0ae2a1..f27b9d7 100644 --- a/AppRate/src/com/tjeannin/apprate/SendFeedback.java +++ b/AppRate/src/com/tjeannin/apprate/SendFeedback.java @@ -31,9 +31,9 @@ public void promptForFeedback(String feedbackEmailAddress, String subject, Strin defaultBodyText.append("------------------------------------\n\n"); defaultBodyText.append(mActivity.getString(R.string.feedback_email_header)); defaultBodyText.append("\n\n"); - defaultBodyText.append("\nAndroid Device: " + getDeviceName()); - defaultBodyText.append("\nAndroid Version: " + Build.VERSION.RELEASE); - defaultBodyText.append("\nApp Version: " + AppInfo.getApplicationVersionName(mActivity)); + defaultBodyText.append("\n" + mActivity.getString(R.string.email_heading_android_device, getDeviceName())); + defaultBodyText.append("\n" + mActivity.getString(R.string.email_heading_android_version, Build.VERSION.RELEASE)); + defaultBodyText.append("\n" + mActivity.getString(R.string.email_heading_app_version, AppInfo.getApplicationVersionName(mActivity))); String defaultSubjectText = mActivity.getString(R.string.feedback_email_subject_line, AppInfo.getApplicationName(mActivity));