diff --git a/AppRater/build.gradle b/AppRater/build.gradle
index 4f7b172..ccb2333 100644
--- a/AppRater/build.gradle
+++ b/AppRater/build.gradle
@@ -6,7 +6,7 @@ android {
defaultConfig {
minSdkVersion 8
- targetSdkVersion 18
+ targetSdkVersion 29
versionName project.VERSION_NAME
versionCode Integer.parseInt(project.VERSION_CODE)
}
diff --git a/AppRater/src/main/AndroidManifest.xml b/AppRater/src/main/AndroidManifest.xml
index d968d15..d9e2f86 100644
--- a/AppRater/src/main/AndroidManifest.xml
+++ b/AppRater/src/main/AndroidManifest.xml
@@ -1,7 +1,5 @@
-
+
\ No newline at end of file
diff --git a/AppRater/src/main/java/org/codechimp/apprater/AppRater.java b/AppRater/src/main/java/org/codechimp/apprater/AppRater.java
index 806bd4a..c432a56 100644
--- a/AppRater/src/main/java/org/codechimp/apprater/AppRater.java
+++ b/AppRater/src/main/java/org/codechimp/apprater/AppRater.java
@@ -11,9 +11,14 @@
import android.content.SharedPreferences;
import android.os.Build;
import android.util.Log;
-import android.widget.Toast;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
public class AppRater {
+ private final static String TAG = AppRater.class.getSimpleName();
// Preference Constants
private final static String PREF_NAME = "apprater";
private final static String PREF_LAUNCH_COUNT = "launch_count";
@@ -33,8 +38,12 @@ public class AppRater {
private static boolean isVersionNameCheckEnabled;
private static boolean isVersionCodeCheckEnabled;
private static boolean isCancelable = true;
+ private static Callable beforeRateAction;
+ private static Callable beforePostponeAction;
+ private static Callable beforeCancelAction;
private static Market market = new GoogleMarket();
+ private static ExecutorService executor = Executors.newSingleThreadExecutor();
/**
* Decides if the version name check is active or not
@@ -196,7 +205,7 @@ public static void rateNow(final Context context) {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, market.getMarketURI(context)));
} catch (ActivityNotFoundException activityNotFoundException1) {
- Log.e(AppRater.class.getSimpleName(), "Market Intent not found");
+ Log.e(TAG, "Market Intent not found");
}
}
@@ -257,10 +266,12 @@ private static void showRateAlertDialog(final Context context, final SharedPrefe
builder.setPositiveButton(context.getString(R.string.rate),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- rateNow(context);
- if (editor != null) {
- editor.putBoolean(PREF_DONT_SHOW_AGAIN, true);
- commitOrApply(editor);
+ if (beforeRateAction == null || execute(beforeRateAction)) {
+ rateNow(context);
+ if (editor != null) {
+ editor.putBoolean(PREF_DONT_SHOW_AGAIN, true);
+ commitOrApply(editor);
+ }
}
dialog.dismiss();
}
@@ -269,13 +280,15 @@ public void onClick(DialogInterface dialog, int id) {
builder.setNeutralButton(context.getString(R.string.later),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- if (editor != null) {
- Long date_firstLaunch = System.currentTimeMillis();
- editor.putLong(PREF_FIRST_LAUNCHED, date_firstLaunch);
- editor.putLong(PREF_LAUNCH_COUNT, 0);
- editor.putBoolean(PREF_REMIND_LATER, true);
- editor.putBoolean(PREF_DONT_SHOW_AGAIN, false);
- commitOrApply(editor);
+ if (beforePostponeAction == null || execute(beforePostponeAction)) {
+ if (editor != null) {
+ Long date_firstLaunch = System.currentTimeMillis();
+ editor.putLong(PREF_FIRST_LAUNCHED, date_firstLaunch);
+ editor.putLong(PREF_LAUNCH_COUNT, 0);
+ editor.putBoolean(PREF_REMIND_LATER, true);
+ editor.putBoolean(PREF_DONT_SHOW_AGAIN, false);
+ commitOrApply(editor);
+ }
}
dialog.dismiss();
}
@@ -284,13 +297,15 @@ public void onClick(DialogInterface dialog, int id) {
builder.setNegativeButton(context.getString(R.string.no_thanks),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- if (editor != null) {
- editor.putBoolean(PREF_DONT_SHOW_AGAIN, true);
- editor.putBoolean(PREF_REMIND_LATER, false);
- long date_firstLaunch = System.currentTimeMillis();
- editor.putLong(PREF_FIRST_LAUNCHED, date_firstLaunch);
- editor.putLong(PREF_LAUNCH_COUNT, 0);
- commitOrApply(editor);
+ if (beforeCancelAction == null || execute(beforeCancelAction)) {
+ if (editor != null) {
+ editor.putBoolean(PREF_DONT_SHOW_AGAIN, true);
+ editor.putBoolean(PREF_REMIND_LATER, false);
+ long date_firstLaunch = System.currentTimeMillis();
+ editor.putLong(PREF_FIRST_LAUNCHED, date_firstLaunch);
+ editor.putLong(PREF_LAUNCH_COUNT, 0);
+ commitOrApply(editor);
+ }
}
dialog.dismiss();
}
@@ -299,6 +314,17 @@ public void onClick(DialogInterface dialog, int id) {
builder.show();
}
+ private static boolean execute(Callable action) {
+ try {
+ return executor.submit(action).get();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "error in custom action", e);
+ } catch (ExecutionException e) {
+ Log.e(TAG, "error in custom action", e);
+ }
+ return false;
+ }
+
@SuppressLint("NewApi")
private static void commitOrApply(SharedPreferences.Editor editor) {
if (Build.VERSION.SDK_INT > 8) {
@@ -318,4 +344,31 @@ public static void resetData(Context context) {
editor.putLong(PREF_FIRST_LAUNCHED, date_firstLaunch);
commitOrApply(editor);
}
+
+ /**
+ * Register a callback to be invoked when 'Rate Now' button is clicked.
+ * Callback will be executed in background thread, so be sure to not touch UI directly.
+ * @param action custom action; returns true if market should be opened, false otherwise
+ */
+ public static void onRateClick(Callable action) {
+ beforeRateAction = action;
+ }
+
+ /**
+ * Register a callback to be invoked when 'Later' button is clicked.
+ * Callback will be executed in background thread, so be sure to not touch UI directly.
+ * @param action custom action; returns true if user decision should be saved, false otherwise
+ */
+ public static void onLaterClick(Callable action) {
+ beforePostponeAction = action;
+ }
+
+ /**
+ * Register a callback to be invoked when 'No, thanks' button is clicked.
+ * Callback will be executed in background thread, so be sure to not touch UI directly.
+ * @param action custom action; returns true if user decision should be saved, false otherwise
+ */
+ public static void onNoClick(Callable action) {
+ beforeCancelAction = action;
+ }
}
diff --git a/AppRaterDemo/build.gradle b/AppRaterDemo/build.gradle
index 5282ab1..b66b4d0 100644
--- a/AppRaterDemo/build.gradle
+++ b/AppRaterDemo/build.gradle
@@ -6,7 +6,7 @@ android {
defaultConfig {
minSdkVersion 8
- targetSdkVersion 18
+ targetSdkVersion 29
versionName project.VERSION_NAME
versionCode Integer.parseInt(project.VERSION_CODE)
}
diff --git a/AppRaterDemo/project.properties b/AppRaterDemo/project.properties
index ae90fca..02d7230 100644
--- a/AppRaterDemo/project.properties
+++ b/AppRaterDemo/project.properties
@@ -12,4 +12,4 @@
# Project target.
target=android-18
-android.library.reference.1=../AppRater
+android.library.reference.1=../AppRaterLib
diff --git a/AppRaterDemo/src/main/java/org/codechimp/appraterdemo/MainActivity.java b/AppRaterDemo/src/main/java/org/codechimp/appraterdemo/MainActivity.java
index 800484e..fee2500 100644
--- a/AppRaterDemo/src/main/java/org/codechimp/appraterdemo/MainActivity.java
+++ b/AppRaterDemo/src/main/java/org/codechimp/appraterdemo/MainActivity.java
@@ -5,6 +5,8 @@
import org.codechimp.apprater.GoogleMarket;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -12,6 +14,9 @@
import android.view.View.OnClickListener;
import android.widget.Button;
import android.app.Activity;
+import android.widget.Toast;
+
+import java.util.concurrent.Callable;
public class MainActivity extends Activity {
@@ -33,7 +38,20 @@ public void onClick(View v) {
}
});
-
+ // You can intercept button clicks to add custom logic
+ // Return true if you'd like to process button click as usual or false if processing should be interrupted
+ AppRater.onRateClick(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(MainActivity.this, "Opening store...", Toast.LENGTH_SHORT).show();
+ }
+ });
+ return true;
+ }
+ });
// Optionally you can set the Market you want to use prior to calling app_launched
// If setMarket not called it will default to Google Play
// Current implementations are Google Play and Amazon App Store, you can add your own by implementing Market
diff --git a/README.md b/README.md
index 9ad280c..fe22f60 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,7 @@ You can implement your own market, implementing the Market interface and parse y
If you want to have a "Rate Now" menu option to go straight to your play store listing call `AppRater.rateNow(this);` within your menu code.
+You can intercept button clicks to add custom logic. Use `onRateClick`, `onLaterClick` and `onNoClick` to perform additional actions like analytics reporting.
Try out the demo within this repository.
## Gradle
diff --git a/build.gradle b/build.gradle
index 48a1506..a63b586 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,16 +1,21 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
+ jcenter()
mavenCentral()
+ maven {
+ url 'https://maven.google.com/'
+ name 'Google'
+ }
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.0.1'
+ classpath 'com.android.tools.build:gradle:4.0.0'
}
}
ext {
- compileSdkVersion = 19
- buildToolsVersion = "19.1.0"
+ compileSdkVersion = 29
+ buildToolsVersion = "30.0.2"
}
def isReleaseBuild() {
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 0087cd3..fd7e590 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c5ac12a..cb0dc18 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sun Dec 07 11:28:32 GMT 2014
+#Mon Oct 05 15:24:08 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755