package dev.dworks.libs.actionbarplus.misc; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.TextView; import dev.dworks.libs.actionbarplus.R; /** * Created by nicolas on 06/03/14. */ public class AppRate { private static final String PREFS_NAME = "app_rate_prefs"; private final String KEY_COUNT = "count"; private final String KEY_CLICKED = "clicked"; private Activity activity; private String text; private int initialLaunchCount = 5; private RetryPolicy policy = RetryPolicy.EXPONENTIAL; private OnShowListener onShowListener; private SharedPreferences settings; private SharedPreferences.Editor editor; private int delay = 0; private AppRate(Activity activity) { this.activity = activity; } public static AppRate with(Activity activity) { AppRate instance = new AppRate(activity); instance.text = "Like App? Rate It!";//activity.getString(R.string.dra_rate_app); instance.settings = activity.getSharedPreferences(PREFS_NAME, 0); instance.editor = instance.settings.edit(); return instance; } /** * Text to be displayed in the view * * @param text text to be displayed * @return the {@link AppRate} instance */ public AppRate text(String text) { this.text = text; return this; } /** * Text to be displayed in the view * * @param textRes text ressource to be displayed * @return the {@link AppRate} instance */ public AppRate text(int textRes) { this.text = activity.getString(textRes); return this; } /** * Initial times {@link AppRate} has to be called before the view is shown * * @param initialLaunchCount times count * @return the {@link AppRate} instance */ public AppRate initialLaunchCount(int initialLaunchCount) { this.initialLaunchCount = initialLaunchCount; return this; } /** * Policy to use to show the {@link AppRate} again * * @param policy the {@link RetryPolicy} to be used * @return the {@link AppRate} instance */ public AppRate retryPolicy(RetryPolicy policy) { this.policy = policy; return this; } /** * Listener used to get {@link AppRate} lifecycle * * @param onShowListener the listener * @return the {@link AppRate} instance */ public AppRate listener(OnShowListener onShowListener) { this.onShowListener = onShowListener; return this; } /** * Delay the {@link AppRate showing time} * @param delay the delay in ms * @return the {@link AppRate} instance */ public AppRate delay(int delay) { this.delay = delay; return this; } /** * Check and show if showing the view is needed */ public void checkAndShow() { incrementViews(); boolean clicked = settings.getBoolean(KEY_CLICKED, false); if (clicked) return; int count = settings.getInt(KEY_COUNT, 0); if (count == initialLaunchCount) { showAppRate(); } else if (policy == RetryPolicy.INCREMENTAL && count % initialLaunchCount == 0) { showAppRate(); }else if (policy == RetryPolicy.EXPONENTIAL && count % initialLaunchCount == 0 && isPowerOfTwo(count / initialLaunchCount)) { showAppRate(); } } /** * Reset the count to start over */ public void reset() { editor.putInt(KEY_COUNT, 0); editor.commit(); } /** * Will force the {@link AppRate} to show */ public void forceShow() { showAppRate(); } private void incrementViews() { editor.putInt(KEY_COUNT, settings.getInt(KEY_COUNT, 0) + 1); editor.commit(); } private void showAppRate() { final ViewGroup mainView = (ViewGroup) activity.getLayoutInflater().inflate(R.layout.app_rate, null); ImageView close = (ImageView) mainView.findViewById(R.id.close); TextView textView = (TextView) mainView.findViewById(R.id.text); textView.setText(text); close.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { hideAllViews(mainView); if (onShowListener != null)onShowListener.onRateAppDismissed(); } }); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + activity.getPackageName()))); if (onShowListener != null)onShowListener.onRateAppClicked(); hideAllViews(mainView); editor.putBoolean(KEY_CLICKED, true); editor.commit(); } }); if (delay > 0) { activity.getWindow().getDecorView().postDelayed(new Runnable() { @Override public void run() { displayViews(mainView); } }, delay); } else { displayViews(mainView); } } private void hideAllViews(final ViewGroup mainView) { Animation hideAnimation = AnimationUtils.loadAnimation(activity, android.R.anim.fade_out); hideAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mainView.removeAllViews(); } @Override public void onAnimationRepeat(Animation animation) { } }); mainView.startAnimation(hideAnimation); } private void displayViews(ViewGroup mainView) { LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); activity.addContentView(mainView, params); Animation fadeInAnimation = AnimationUtils.loadAnimation(activity, android.R.anim.fade_in); mainView.startAnimation(fadeInAnimation); if (onShowListener != null) onShowListener.onRateAppShowing(); } public interface OnShowListener { void onRateAppShowing(); void onRateAppDismissed(); void onRateAppClicked(); } public enum RetryPolicy { /** * Will retry each time initial count has been triggered * Ex: if initial is set to 3, it will be shown on the 3rd, 6th, 9th, ... times */ INCREMENTAL, /** * Will retry exponentially to be less intrusive * Ex: if initial is set to 3, it will be shown on the 3rd, 6th, 12th, ... times */ EXPONENTIAL, /** * Will never retry */ NONE; } /** * Convert a size in dp to a size in pixels * @param context the {@link android.content.Context} to be used * @param dpi size in dp * @return the size in pixels */ public static int convertDPItoPixels(Context context, int dpi) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpi * scale + 0.5f); } public static boolean isPowerOfTwo(int x) { return (x & (x - 1)) == 0; } }