How to implement Rate It feature in Android App

前端 未结 14 1359
囚心锁ツ
囚心锁ツ 2020-12-02 04:19

I am developing an Android App. In which everything is working right. My app is ready to launch. But there I need to implement one more feature. I need to display a popup wh

相关标签:
14条回答
  • 2020-12-02 04:57

    I implemented this a while back, to some extent. It is impossible to know whether or not a user has rated an app, to prevent ratings from becoming a currency (some developers might add an option like "Rate this app and get so and so in the app for free").

    The class I wrote provides three buttons, and configures the dialog so that it is only shown after the app has been launched n times (users have a higher chance of rating the app if they've used it a bit before. Most of them are unlikely to even know what it does on the first run):

    public class AppRater {
        private final static String APP_TITLE = "App Name";// App Name
        private final static String APP_PNAME = "com.example.name";// Package Name
    
        private final static int DAYS_UNTIL_PROMPT = 3;//Min number of days
        private final static int LAUNCHES_UNTIL_PROMPT = 3;//Min number of launches
    
        public static void app_launched(Context mContext) {
            SharedPreferences prefs = mContext.getSharedPreferences("apprater", 0);
            if (prefs.getBoolean("dontshowagain", false)) { return ; }
    
            SharedPreferences.Editor editor = prefs.edit();
    
            // Increment launch counter
            long launch_count = prefs.getLong("launch_count", 0) + 1;
            editor.putLong("launch_count", launch_count);
    
            // Get date of first launch
            Long date_firstLaunch = prefs.getLong("date_firstlaunch", 0);
            if (date_firstLaunch == 0) {
                date_firstLaunch = System.currentTimeMillis();
                editor.putLong("date_firstlaunch", date_firstLaunch);
            }
    
            // Wait at least n days before opening
            if (launch_count >= LAUNCHES_UNTIL_PROMPT) {
                if (System.currentTimeMillis() >= date_firstLaunch + 
                        (DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000)) {
                    showRateDialog(mContext, editor);
                }
            }
    
            editor.commit();
        }   
    
        public static void showRateDialog(final Context mContext, final SharedPreferences.Editor editor) {
            final Dialog dialog = new Dialog(mContext);
            dialog.setTitle("Rate " + APP_TITLE);
    
            LinearLayout ll = new LinearLayout(mContext);
            ll.setOrientation(LinearLayout.VERTICAL);
    
            TextView tv = new TextView(mContext);
            tv.setText("If you enjoy using " + APP_TITLE + ", please take a moment to rate it. Thanks for your support!");
            tv.setWidth(240);
            tv.setPadding(4, 0, 4, 10);
            ll.addView(tv);
    
            Button b1 = new Button(mContext);
            b1.setText("Rate " + APP_TITLE);
            b1.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    mContext.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + APP_PNAME)));
                    dialog.dismiss();
                }
            });        
            ll.addView(b1);
    
            Button b2 = new Button(mContext);
            b2.setText("Remind me later");
            b2.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });
            ll.addView(b2);
    
            Button b3 = new Button(mContext);
            b3.setText("No, thanks");
            b3.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    if (editor != null) {
                        editor.putBoolean("dontshowagain", true);
                        editor.commit();
                    }
                    dialog.dismiss();
                }
            });
            ll.addView(b3);
    
            dialog.setContentView(ll);        
            dialog.show();        
        }
    }
    

    Integrating the class is as simple as adding:

    AppRater.app_launched(this);
    

    To your Activity. It only needs to be added to one Activity in the entire app.

    0 讨论(0)
  • 2020-12-02 05:02

    Use this library, It is simple and easy.. https://github.com/hotchemi/Android-Rate

    by adding the dependency..

    dependencies {
      compile 'com.github.hotchemi:android-rate:0.5.6'
    }
    
    0 讨论(0)
  • 2020-12-02 05:02

    Make sure the below is implemented For in-app reviews:

    implementation 'com.google.android.play:core:1.8.0'
    

    OnCreate

    public void RateApp(Context mContext) {
        try {
            ReviewManager manager = ReviewManagerFactory.create(mContext);
            manager.requestReviewFlow().addOnCompleteListener(new OnCompleteListener<ReviewInfo>() {
                @Override
                public void onComplete(@NonNull Task<ReviewInfo> task) {
                    if(task.isSuccessful()){
                        ReviewInfo reviewInfo = task.getResult();
                        manager.launchReviewFlow((Activity) mContext, reviewInfo).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(Exception e) {
                                Toast.makeText(mContext, "Rating Failed", Toast.LENGTH_SHORT).show();
                            }
                        }).addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                                Toast.makeText(mContext, "Review Completed, Thank You!", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
    
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    Toast.makeText(mContext, "In-App Request Failed", Toast.LENGTH_SHORT).show();
                }
            });
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 05:02

    Kotlin version of Raghav Sood's answer

    Rater.kt

        class Rater {
          companion object {
            private const val APP_TITLE = "App Name"
            private const val APP_NAME = "com.example.name"
    
            private const val RATER_KEY = "rater_key"
            private const val LAUNCH_COUNTER_KEY = "launch_counter_key"
            private const val DO_NOT_SHOW_AGAIN_KEY = "do_not_show_again_key"
            private const val FIRST_LAUNCH_KEY = "first_launch_key"
    
            private const val DAYS_UNTIL_PROMPT: Int = 3
            private const val LAUNCHES_UNTIL_PROMPT: Int = 3
    
            fun start(mContext: Context) {
                val prefs: SharedPreferences = mContext.getSharedPreferences(RATER_KEY, 0)
                if (prefs.getBoolean(DO_NOT_SHOW_AGAIN_KEY, false)) {
                    return
                }
    
                val editor: Editor = prefs.edit()
    
                val launchesCounter: Long = prefs.getLong(LAUNCH_COUNTER_KEY, 0) + 1;
                editor.putLong(LAUNCH_COUNTER_KEY, launchesCounter)
    
                var firstLaunch: Long = prefs.getLong(FIRST_LAUNCH_KEY, 0)
                if (firstLaunch == 0L) {
                    firstLaunch = System.currentTimeMillis()
                    editor.putLong(FIRST_LAUNCH_KEY, firstLaunch)
                }
    
                if (launchesCounter >= LAUNCHES_UNTIL_PROMPT) {
                    if (System.currentTimeMillis() >= firstLaunch +
                        (DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000)
                    ) {
                        showRateDialog(mContext, editor)
                    }
                }
    
                editor.apply()
            }
    
            fun showRateDialog(mContext: Context, editor: Editor) {
                Dialog(mContext).apply {
                    setTitle("Rate $APP_TITLE")
    
                    val ll = LinearLayout(mContext)
                    ll.orientation = LinearLayout.VERTICAL
    
                    TextView(mContext).apply {
                        text =
                            "If you enjoy using $APP_TITLE, please take a moment to rate it. Thanks for your support!"
    
                        width = 240
                        setPadding(4, 0, 4, 10)
                        ll.addView(this)
                    }
    
                    Button(mContext).apply {
                        text = "Rate $APP_TITLE"
                        setOnClickListener {
                            mContext.startActivity(
                                Intent(
                                    Intent.ACTION_VIEW,
                                    Uri.parse("market://details?id=$APP_NAME")
                                )
                            );
                            dismiss()
                        }
                        ll.addView(this)
                    }
    
                    Button(mContext).apply {
                        text = "Remind me later"
                        setOnClickListener {
                            dismiss()
                        };
                        ll.addView(this)
                    }
    
                    Button(mContext).apply {
                        text = "No, thanks"
                        setOnClickListener {
                            editor.putBoolean(DO_NOT_SHOW_AGAIN_KEY, true);
                            editor.commit()
                            dismiss()
                        };
                        ll.addView(this)
                    }
    
                    setContentView(ll)
                    show()
                }
            }
        }
    }
    

    Optimized answer

    Rater.kt

    class Rater {
        companion object {
            fun start(context: Context) {
                val prefs: SharedPreferences = context.getSharedPreferences(RATER_KEY, 0)
                if (prefs.getBoolean(DO_NOT_SHOW_AGAIN_KEY, false)) {
                    return
                }
    
                val editor: Editor = prefs.edit()
    
                val launchesCounter: Long = prefs.getLong(LAUNCH_COUNTER_KEY, 0) + 1;
                editor.putLong(LAUNCH_COUNTER_KEY, launchesCounter)
    
                var firstLaunch: Long = prefs.getLong(FIRST_LAUNCH_KEY, 0)
                if (firstLaunch == 0L) {
                    firstLaunch = System.currentTimeMillis()
                    editor.putLong(FIRST_LAUNCH_KEY, firstLaunch)
                }
    
                if (launchesCounter >= LAUNCHES_UNTIL_PROMPT) {
                    if (System.currentTimeMillis() >= firstLaunch +
                        (DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000)
                    ) {
                        showRateDialog(context, editor)
                    }
                }
    
                editor.apply()
            }
    
            fun showRateDialog(context: Context, editor: Editor) {
                Dialog(context).apply {
                    setTitle("Rate $APP_TITLE")
                    LinearLayout(context).let { layout ->
                        layout.orientation = LinearLayout.VERTICAL
                        setDescription(context, layout)
                        setPositiveAnswer(context, layout)
                        setNeutralAnswer(context, layout)
                        setNegativeAnswer(context, editor, layout)
                        setContentView(layout)
                        show()       
                    }
                }
            }
    
            private fun setDescription(context: Context, layout: LinearLayout) {
                TextView(context).apply {
                    text = context.getString(R.string.rate_description, APP_TITLE)
                    width = 240
                    setPadding(4, 0, 4, 10)
                    layout.addView(this)
                }
            }
    
            private fun Dialog.setPositiveAnswer(
                context: Context,
                layout: LinearLayout
            ) {
                Button(context).apply {
                    text = context.getString(R.string.rate_now)
                    setOnClickListener {
                        context.startActivity(
                            Intent(
                                Intent.ACTION_VIEW,
                                Uri.parse(context.getString(R.string.market_uri, APP_NAME))
                            )
                        );
                        dismiss()
                    }
                    layout.addView(this)
                }
            }
    
            private fun Dialog.setNeutralAnswer(
                context: Context,
                layout: LinearLayout
            ) {
                Button(context).apply {
                    text = context.getString(R.string.remind_later)
                    setOnClickListener {
                        dismiss()
                    };
                    layout.addView(this)
                }
            }
    
            private fun Dialog.setNegativeAnswer(
                context: Context,
                editor: Editor,
                layout: LinearLayout
            ) {
                Button(context).apply {
                    text = context.getString(R.string.no_thanks)
                    setOnClickListener {
                        editor.putBoolean(DO_NOT_SHOW_AGAIN_KEY, true);
                        editor.commit()
                        dismiss()
                    };
                    layout.addView(this)
                }
            }
        }
    }
    

    Constants.kt

    object Constants {
    
        const val APP_TITLE = "App Name"
        const val APP_NAME = "com.example.name"
    
        const val RATER_KEY = "rater_key"
        const val LAUNCH_COUNTER_KEY = "launch_counter_key"
        const val DO_NOT_SHOW_AGAIN_KEY = "do_not_show_again_key"
        const val FIRST_LAUNCH_KEY = "first_launch_key"
    
        const val DAYS_UNTIL_PROMPT: Int = 3
        const val LAUNCHES_UNTIL_PROMPT: Int = 3
    
    }
    

    strings.xml

    <resources>
        <string name="rate_description">If you enjoy using %1$s, please take a moment to rate it. Thanks for your support!</string>
        <string name="rate_now">Rate now</string>
        <string name="no_thanks">No, thanks</string>
        <string name="remind_later">Remind me later</string>
        <string name="market_uri">market://details?id=%1$s</string>
    </resources>
    
    0 讨论(0)
  • 2020-12-02 05:07

    I think what you are trying to do is probably counter-productive.

    Making it easy for people to rate apps is generally a good idea, as most people who bother do so because they like the app. It is rumoured that the number of ratings affects your market rating (although I see little evidence of this). Hassling users into rating - through nag screens - is likely to cause people to clear the nag through leaving a bad rating.

    Adding the capability to directly rate an app has caused a slight decrease in the numerical ratings for my free version, and a slight increase in my paid app. For the free app, my 4 star ratings increased more than my 5 star ratings, as people who thought my app was good but not great started to rate it as well. Change was about -0.2. For the paid, change was about +0.1. I should remove it from the free version, except I like getting lots of comments.

    I put my rating button into a settings (preference) screen, where it does not affect normal operation. It still increased my rating rate by a factor of 4 or 5. I have no doubt that if I tried nagging my users into making a rating, I would get lots of users giving me bad ratings as a protest.

    0 讨论(0)
  • 2020-12-02 05:07

    This solution is very similar to those presented above. The only difference is that you are going to be able to delay the prompt of the rating dialog per launches and days. If the remind me later button is pressed, then I will delay the pop up for 3 days and 10 launches. The same is done for those that selected to rate it, however the delays is longer (not to bother the user so soon in case that he has actually rated the app. This can be changed to not be shown again, then you will have to alter the code to your like). Hope it helps somebody!

    public class AppRater {
        private final static String APP_TITLE = "your_app_name";
        private static String PACKAGE_NAME = "your_package_name";
        private static int DAYS_UNTIL_PROMPT = 5;
        private static int LAUNCHES_UNTIL_PROMPT = 10;
        private static long EXTRA_DAYS;
        private static long EXTRA_LAUCHES;
        private static SharedPreferences prefs;
        private static SharedPreferences.Editor editor;
        private static Activity activity;
    
        public static void app_launched(Activity activity1) {
            activity = activity1;
    
            Configs.sendScreenView("Avaliando App", activity);
    
            PACKAGE_NAME = activity.getPackageName();
    
            prefs = activity.getSharedPreferences("apprater", Context.MODE_PRIVATE);
            if (prefs.getBoolean("dontshowagain", false)) 
                return;
    
            editor = prefs.edit();
    
            EXTRA_DAYS = prefs.getLong("extra_days", 0);
            EXTRA_LAUCHES = prefs.getLong("extra_launches", 0);
    
            // Increment launch counter
            long launch_count = prefs.getLong("launch_count", 0) + 1;
            editor.putLong("launch_count", launch_count);
    
            // Get date of first launch
            Long date_firstLaunch = prefs.getLong("date_firstlaunch", 0);
            if (date_firstLaunch == 0) {
                date_firstLaunch = System.currentTimeMillis();
                editor.putLong("date_firstlaunch", date_firstLaunch);
            }
    
            // Wait at least n days before opening
            if (launch_count >= (LAUNCHES_UNTIL_PROMPT + EXTRA_LAUCHES))
                if (System.currentTimeMillis() >= date_firstLaunch + (DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000) + EXTRA_DAYS)
                    showRateDialog();
    
            editor.commit();
        }   
    
        public static void showRateDialog() {
            final Dialog dialog = new Dialog(activity);
            dialog.setTitle("Deseja avaliar o aplicativo " + APP_TITLE + "?");
    
            LinearLayout ll = new LinearLayout(activity);
            ll.setOrientation(LinearLayout.VERTICAL);
            ll.setPadding(5, 5, 5, 5);
    
            TextView tv = new TextView(activity);
            tv.setTextColor(activity.getResources().getColor(R.color.default_text));
            tv.setText("Ajude-nos a melhorar o aplicativo com sua avaliação no Google Play!");
            tv.setWidth(240);
            tv.setGravity(Gravity.CENTER);
            tv.setPadding(5, 5, 5, 5);
            ll.addView(tv);
    
            Button b1 = new Button(activity);
            b1.setTextColor(activity.getResources().getColor(R.color.default_text));
            b1.setBackground(activity.getResources().getDrawable(R.drawable.rounded_blue_box));
            b1.setTextColor(Color.WHITE);
            b1.setText("Avaliar aplicativo " + APP_TITLE + "!");
            b1.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    Configs.sendHitEvents(Configs.APP_RATER, Configs.CATEGORIA_ANALYTICS, "Clique", "Avaliar", activity);
    
                    activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + PACKAGE_NAME)));
                    delayDays(60);
                    delayLaunches(30);
                    dialog.dismiss();
                }
            });        
            ll.addView(b1);
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) b1.getLayoutParams();
            params.setMargins(5, 3, 5, 3);
            b1.setLayoutParams(params);
    
            Button b2 = new Button(activity);
            b2.setTextColor(activity.getResources().getColor(R.color.default_text));
            b2.setBackground(activity.getResources().getDrawable(R.drawable.rounded_blue_box));
            b2.setTextColor(Color.WHITE);
            b2.setText("Lembre-me mais tarde!");
            b2.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    Configs.sendHitEvents(Configs.APP_RATER, Configs.CATEGORIA_ANALYTICS, "Clique", "Avaliar Mais Tarde", activity);
                    delayDays(3);
                    delayLaunches(10);
                    dialog.dismiss();
                }
            });
            ll.addView(b2);
            params = (LinearLayout.LayoutParams) b2.getLayoutParams();
            params.setMargins(5, 3, 5, 3);
            b2.setLayoutParams(params);
    
            Button b3 = new Button(activity);
            b3.setTextColor(activity.getResources().getColor(R.color.default_text));
            b3.setBackground(activity.getResources().getDrawable(R.drawable.rounded_blue_box));
            b3.setTextColor(Color.WHITE);
            b3.setText("Não, obrigado!");
            b3.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    Configs.sendHitEvents(Configs.APP_RATER, Configs.CATEGORIA_ANALYTICS, "Clique", "Não Avaliar", activity);
    
                    if (editor != null) {
                        editor.putBoolean("dontshowagain", true);
                        editor.commit();
                    }
                    dialog.dismiss();
                }
            });
            ll.addView(b3);
            params = (LinearLayout.LayoutParams) b3.getLayoutParams();
            params.setMargins(5, 3, 5, 0);
            b3.setLayoutParams(params);
    
            dialog.setContentView(ll);        
            dialog.show();        
        }
    
        private static void delayLaunches(int numberOfLaunches) {
            long extra_launches = prefs.getLong("extra_launches", 0) + numberOfLaunches;
            editor.putLong("extra_launches", extra_launches);
            editor.commit();
        }
    
        private static void delayDays(int numberOfDays) {
            Long extra_days = prefs.getLong("extra_days", 0) + (numberOfDays * 1000 * 60 * 60 * 24);
            editor.putLong("extra_days", extra_days);
            editor.commit();
        }
    }
    

    The Buttons have a specific color and background. The background is as shown in this xml file:

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:padding="10dp"
        android:shape="rectangle" >
    
        <solid android:color="#2E78B9" />
    
        <corners
            android:bottomLeftRadius="6dp"
            android:bottomRightRadius="6dp"
            android:topLeftRadius="6dp"
            android:topRightRadius="6dp" />
    
    </shape>
    

    source: Android approach for "Rate my application"

    0 讨论(0)
提交回复
热议问题