How to notify users to rate app on playstore

This post is about how to notify users to rate the app on playstore. Play store policy suggests us if we are notifying users to perform some action in our app then we must also let users to cancel the operation if user doesn't want to perform that action. We must give option to perform an action or to cancel that action which'll depend on the users choice what they want to do. Like if we are notifying users to update the app or rate the app on play store with Yes(Now) then we must also give an option for No(Later, Not Now) etc. So, if user like to perform that action then they choose Yes(Now) or if then don't want then they can cancel it by choosing No(Not Now, Later) etc.

The code given below will notify users on a defined time depends upon you. Just attach the given code in your project and write the one live of code in onBackPressed method of Main_Activity.java:

new AppRate(this).setMinDaysUntilPrompt(0) .setMinLaunchesUntilPrompt(5) .setShowIfAppHasCrashed(false).init();


 

This app function uses the SharedPreference class to set the timing to display the popup for rating. Whole code is as given below :

 

import java.lang.Thread.UncaughtExceptionHandler;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.text.format.DateUtils;
import android.util.Log;

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 long minLaunchesUntilPrompt = 0;
private long minDaysUntilPrompt = 0;

private boolean showIfHasCrashed = true;

Editor editor;

public AppRate(Activity hostActivity) {
this.hostActivity = hostActivity;
preferences = hostActivity.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, 0);
}

/**
* @param minLaunchesUntilPrompt The minimum number of times the user launches 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.<br/>
* 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 <code>false</code> the rate dialog will not be shown if the application has crashed once.<br/>
* Default value is <code>false</code>.
* @return This {@link AppRate} object to allow chaining.
*/
public AppRate setShowIfAppHasCrashed(boolean showIfCrash) {
showIfHasCrashed = showIfCrash;
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)) {
ExitApp xt = new ExitApp();
xt.exitMyApp();
return;
}

if (!showIfHasCrashed) {
initExceptionHandler();
}

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)) {
System.out.println("days..."+date_firstLaunch+"plus days "+(minDaysUntilPrompt * DateUtils.DAY_IN_MILLIS));
showDefaultDialog();
}
}
else
{
ExitApp xt = new ExitApp();
xt.exitMyApp();
}
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 = "Enjoying this ap?";
String loveit = "Love it";
String likeit = "Like it";
String hateit = "Hate it";

new AlertDialog.Builder(hostActivity)
.setTitle(title)
.setIcon(R.drawable.ic_icon)
//.setMessage(message)
.setNeutralButton(likeit, this)
.setPositiveButton(loveit, this)
.setNegativeButton(hateit, this)
.setOnCancelListener(this)
.setCancelable(true)
.create().show();
}

@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) {

switch (which) {
case DialogInterface.BUTTON_POSITIVE:
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(hostActivity);
// set title
alertDialogBuilder.setTitle("Rate us 5 stars");
alertDialogBuilder.setIcon(R.drawable.ic_icon);
// set dialog message
alertDialogBuilder
.setMessage("Would you be so kind to rate us in playstore?")
.setCancelable(true)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true);
// if this button is clicked, open playstore
try
{
hostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + hostActivity.getPackageName())));
}catch (ActivityNotFoundException e) {

hostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + hostActivity.getPackageName())));
}
editor.commit();
}
})
.setNeutralButton("Later", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// if this button is clicked, just close and show again the popup dialog on third time exit show again
editor.putBoolean(PrefsContract.PREF_LAUNCH_COUNT, true);
dialog.cancel();
}
})
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true);
editor.commit();
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});

// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();

// show it
alertDialog.show();
break;

case DialogInterface.BUTTON_NEUTRAL:
AlertDialog.Builder alertDialogBuilder3 = new AlertDialog.Builder(hostActivity);
// set title
alertDialogBuilder3.setTitle("Rate us 5 stars");
alertDialogBuilder3.setIcon(R.drawable.ic_icon);
// set dialog message
alertDialogBuilder3
.setMessage("Would you be so kind to rate us in playstore?")
.setCancelable(true)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true);
// if this button is clicked, open playstore
try
{
hostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + hostActivity.getPackageName())));
}catch (ActivityNotFoundException e) {
hostActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + hostActivity.getPackageName())));
}
editor.commit();
}
})
.setNeutralButton("Later", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
// if this button is clicked, just close and show again the popup dialog on third time exit show again
editor.putBoolean(PrefsContract.PREF_LAUNCH_COUNT, true);
dialog.cancel();
}
})
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true);
editor.commit();
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});

// create alert dialog
AlertDialog alertDialog3 = alertDialogBuilder3.create();

// show it
alertDialog3.show();
break;

case DialogInterface.BUTTON_NEGATIVE:
AlertDialog.Builder alertDialogBuilder1 = new AlertDialog.Builder(hostActivity);
// set title
alertDialogBuilder1.setTitle("Share Feedback");
alertDialogBuilder1.setIcon(R.drawable.ic_icon);
// set dialog message
alertDialogBuilder1
.setMessage("Please help us to improve.")
.setCancelable(true)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
editor.putBoolean(PrefsContract.PREF_DONT_SHOW_AGAIN, true);
editor.commit();
// if this button is clicked, open feedback page
ExitApp ext = new ExitApp();
ext.openFeedback(hostActivity);
dialog.cancel();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Cancel Dialog Box
dialog.cancel();
}
});

// create alert dialog
AlertDialog alertDialog1 = alertDialogBuilder1.create();

// show it
alertDialog1.show();
break;

default:
editor.putBoolean(PrefsContract.PREF_LAUNCH_COUNT, true);
editor.commit();
break;
}

dialog.dismiss();

if(clickListener != null){
clickListener.onClick(dialog, which);
}
}

public class PrefsContract {

public static final String SHARED_PREFS_NAME = "apprate_prefs";

public static final String PREF_APP_HAS_CRASHED = "pref_app_has_crashed";
public static final String PREF_DATE_FIRST_LAUNCH = "date_firstlaunch";
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 class ExceptionHandler implements UncaughtExceptionHandler {

private UncaughtExceptionHandler defaultExceptionHandler;
SharedPreferences preferences;

// Constructor.
public ExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler, Context context)
{
preferences = context.getSharedPreferences(PrefsContract.SHARED_PREFS_NAME, 0);
defaultExceptionHandler = uncaughtExceptionHandler;
}

public void uncaughtException(Thread thread, Throwable throwable) {

preferences.edit().putBoolean(PrefsContract.PREF_APP_HAS_CRASHED, true).commit();

// Call the original handler.
defaultExceptionHandler.uncaughtException(thread, throwable);
}
}
}

0 Comments:

Post a Comment