Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/190.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Android应用程序中实现Rate It功能_Android_Google Play - Fatal编程技术网

如何在Android应用程序中实现Rate It功能

如何在Android应用程序中实现Rate It功能,android,google-play,Android,Google Play,我正在开发一个Android应用程序。一切正常。我的应用程序已准备好启动。但是我需要实现另外一个特性。我需要显示一个包含 评分和稍后提醒我 在这里,如果有任何用户在市场上评价该应用程序,则弹出窗口不会消失。 我在谷歌上搜索了一下,找到了一个。有了这个,我知道这是不可能知道的。所以我需要一个建议 以前有人遇到过这种情况吗?如果是这样的话,有什么解决方案或替代方案吗?正如您在链接的另一篇文章中看到的,应用程序无法知道用户是否留下了评论。有充分的理由 想想看,如果一个应用程序可以告诉用户是否留下了评论

我正在开发一个Android应用程序。一切正常。我的应用程序已准备好启动。但是我需要实现另外一个特性。我需要显示一个包含

评分
稍后提醒我

在这里,如果有任何用户在市场上评价该应用程序,则弹出窗口不会消失。 我在谷歌上搜索了一下,找到了一个。有了这个,我知道这是不可能知道的。所以我需要一个建议


以前有人遇到过这种情况吗?如果是这样的话,有什么解决方案或替代方案吗?

正如您在链接的另一篇文章中看到的,应用程序无法知道用户是否留下了评论。有充分的理由

想想看,如果一个应用程序可以告诉用户是否留下了评论,开发者可以限制某些只有在用户留下5/5评分时才能解锁的功能。这将导致谷歌Play的其他用户不信任这些评论,并破坏评级体系

我看到的替代解决方案是,每当应用程序打开特定次数或设置间隔时,应用程序提醒用户提交评级。例如,在每10次打开应用程序时,要求用户留下评分,并提供“已完成”和“稍后提醒我”按钮。如果用户选择以后提醒他/她,则继续显示此消息。其他一些应用程序开发人员显示此消息的时间间隔越来越长(例如,第5次、第10次、第15次打开应用程序),因为如果用户没有在(例如)第100次打开应用程序时留下评论,则可能不会留下评论


这个解决方案并不完美,但我认为它是目前最好的。这确实会让你信任用户,但要意识到,对于应用程序市场中的每个人来说,替代方案都可能意味着一种更糟糕的体验。

在某种程度上,我不久前就实现了这一点。不可能知道用户是否对某个应用进行了评级,以防止评级成为一种货币(一些开发者可能会添加一个选项,如“对该应用进行评级,并在应用中免费获得某某”)

我编写的类提供了三个按钮,并对对话框进行了配置,使其仅在应用程序启动
n
次后才显示(如果用户以前使用过应用程序,则对其进行评级的几率更高。他们中的大多数人甚至不太可能知道它在第一次运行时会做什么):

集成类非常简单,只需添加:

AppRater.app_launched(this);

为你的活动做准备。它只需要添加到整个应用程序中的一个活动中。

我认为您试图做的可能会适得其反

让人们更容易对应用程序进行评分通常是一个好主意,因为大多数人之所以这么做是因为他们喜欢这个应用程序。谣传评级的数量会影响你的市场评级(尽管我看不到什么证据)。通过唠叨屏幕让用户进行评级可能会导致人们通过留下一个糟糕的评级来清除唠叨

增加了对应用程序直接评分的功能,导致我的免费版的数字评分略有下降,付费应用程序的数字评分略有增加。对于免费应用程序,我的4星评级比我的5星评级提高了很多,因为那些认为我的应用程序很好但不是很好的人也开始对它进行评级。变化约为-0.2。对于付费用户,变化约为+0.1。我应该把它从免费版本中删除,除非我喜欢得到很多评论


我将我的评级按钮放入设置(首选项)屏幕,在那里它不会影响正常操作。它仍然将我的评级提高了4到5倍。我毫不怀疑,如果我试图唠叨我的用户给我评分,我会得到很多用户给我不好的评分作为抗议

使用DialogFragment的我的一个:

public class RateItDialogFragment extends DialogFragment {
    private static final int LAUNCHES_UNTIL_PROMPT = 10;
    private static final int DAYS_UNTIL_PROMPT = 3;
    private static final int MILLIS_UNTIL_PROMPT = DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000;
    private static final String PREF_NAME = "APP_RATER";
    private static final String LAST_PROMPT = "LAST_PROMPT";
    private static final String LAUNCHES = "LAUNCHES";
    private static final String DISABLED = "DISABLED";

    public static void show(Context context, FragmentManager fragmentManager) {
        boolean shouldShow = false;
        SharedPreferences sharedPreferences = getSharedPreferences(context);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        long currentTime = System.currentTimeMillis();
        long lastPromptTime = sharedPreferences.getLong(LAST_PROMPT, 0);
        if (lastPromptTime == 0) {
            lastPromptTime = currentTime;
            editor.putLong(LAST_PROMPT, lastPromptTime);
        }

        if (!sharedPreferences.getBoolean(DISABLED, false)) {
            int launches = sharedPreferences.getInt(LAUNCHES, 0) + 1;
            if (launches > LAUNCHES_UNTIL_PROMPT) {
                if (currentTime > lastPromptTime + MILLIS_UNTIL_PROMPT) {
                    shouldShow = true;
                }
            }
            editor.putInt(LAUNCHES, launches);
        }

        if (shouldShow) {
            editor.putInt(LAUNCHES, 0).putLong(LAST_PROMPT, System.currentTimeMillis()).commit();
            new RateItDialogFragment().show(fragmentManager, null);
        } else {
            editor.commit();
        }
    }

    private static SharedPreferences getSharedPreferences(Context context) {
        return context.getSharedPreferences(PREF_NAME, 0);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setTitle(R.string.rate_title)
                .setMessage(R.string.rate_message)
                .setPositiveButton(R.string.rate_positive, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getActivity().getPackageName())));
                        getSharedPreferences(getActivity()).edit().putBoolean(DISABLED, true).commit();
                        dismiss();
                    }
                })
                .setNeutralButton(R.string.rate_remind_later, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dismiss();
                    }
                })
                .setNegativeButton(R.string.rate_never, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        getSharedPreferences(getActivity()).edit().putBoolean(DISABLED, true).commit();
                        dismiss();
                    }
                }).create();
    }
}
然后在主要碎片活动的
onCreate()
中使用它:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    RateItDialogFragment.show(this, getFragmentManager());

}

我正在使用这个简单的解决方案。 您可以使用gradle添加此库:


该解决方案与上述解决方案非常相似。唯一的区别是,您将能够在每次启动和每几天延迟评级对话框的提示。如果按下“以后提醒我”按钮,则我会将弹出窗口延迟3天和10次启动。对于那些选择对其进行评级的用户,也会进行同样的操作,但是延迟时间更长(如果用户实际对应用进行了评级,则不要这么快就打扰用户。可以将其更改为不再显示,然后您必须根据自己的喜好更改代码)。希望它能帮助别人

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();
    }
}
按钮具有特定的颜色和背景。背景如此xml文件所示:

<?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>


来源:

使用这个库,它简单易学。。

通过添加依赖项

dependencies {
  compile 'com.github.hotchemi:android-rate:0.5.6'
}
是一个库,通过提示用户在使用安卓应用几天后对其进行评分,帮助您推广安卓应用

模块梯度:

dependencies {
  implementation 'com.vorlonsoft:androidrate:1.0.8'
}
MainActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  AppRate.with(this)
      .setStoreType(StoreType.GOOGLEPLAY) //default is GOOGLEPLAY (Google Play), other options are
                                          //           AMAZON (Amazon Appstore) and
                                          //           SAMSUNG (Samsung Galaxy Apps)
      .setInstallDays((byte) 0) // default 10, 0 means install day
      .setLaunchTimes((byte) 3) // default 10
      .setRemindInterval((byte) 2) // default 1
      .setRemindLaunchTimes((byte) 2) // default 1 (each launch)
      .setShowLaterButton(true) // default true
      .setDebug(false) // default false
      //Java 8+: .setOnClickButtonListener(which -> Log.d(MainActivity.class.getName(), Byte.toString(which)))
      .setOnClickButtonListener(new OnClickButtonListener() { // callback listener.
          @Override
          public void onClickButton(byte which) {
              Log.d(MainActivity.class.getName(), Byte.toString(which));
          }
      })
      .monitor();

  if (AppRate.with(this).getStoreType() == StoreType.GOOGLEPLAY) {
      //Check that Google Play is available
      if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING) {
          // Show a dialog if meets conditions
          AppRate.showRateDialogIfMeetsConditions(this);
      }
  } else {
      // Show a dialog if meets conditions
      AppRate.showRateDialogIfMeetsConditions(this);
  }
}
显示“费率”对话框的默认条件如下:

  • 应用程序比安装晚10天以上启动。通过
    AppRate#setInstallDays(字节)
    更改
  • 该应用程序已启动10多次。通过
    通知#设置启动时间(字节)
    进行更改
  • 应用程序在点击中性按钮后超过1天启动。通过
    通知#设置提醒间隔(字节)
    进行更改
  • 应用程序已启动X次,X%1=0。通过
    通知#设置提醒启动时间(字节)
    更改
  • 默认情况下,应用程序显示中立对话框(稍后提醒我)。通过
    setShowLaterButton(布尔值)
    进行更改
  • 指定按下按钮时的回调。将在
    onClickButton
    的参数中传递与
    DialogInterface.OnClickListener#onClick
    的第二个参数相同的值
  • 设置
    AppRate#setDebug(布尔值)
    将确保每次启动应用程序时都会显示评级请求这项壮举
    dependencies {
      implementation 'com.vorlonsoft:androidrate:1.0.8'
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
    
      AppRate.with(this)
          .setStoreType(StoreType.GOOGLEPLAY) //default is GOOGLEPLAY (Google Play), other options are
                                              //           AMAZON (Amazon Appstore) and
                                              //           SAMSUNG (Samsung Galaxy Apps)
          .setInstallDays((byte) 0) // default 10, 0 means install day
          .setLaunchTimes((byte) 3) // default 10
          .setRemindInterval((byte) 2) // default 1
          .setRemindLaunchTimes((byte) 2) // default 1 (each launch)
          .setShowLaterButton(true) // default true
          .setDebug(false) // default false
          //Java 8+: .setOnClickButtonListener(which -> Log.d(MainActivity.class.getName(), Byte.toString(which)))
          .setOnClickButtonListener(new OnClickButtonListener() { // callback listener.
              @Override
              public void onClickButton(byte which) {
                  Log.d(MainActivity.class.getName(), Byte.toString(which));
              }
          })
          .monitor();
    
      if (AppRate.with(this).getStoreType() == StoreType.GOOGLEPLAY) {
          //Check that Google Play is available
          if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING) {
              // Show a dialog if meets conditions
              AppRate.showRateDialogIfMeetsConditions(this);
          }
      } else {
          // Show a dialog if meets conditions
          AppRate.showRateDialogIfMeetsConditions(this);
      }
    }
    
    AppRate.with(this).setMinimumEventCount(String, short);
    AppRate.with(this).incrementEventCount(String);
    AppRate.with(this).setEventCountValue(String, short);
    
    AppRate.with(this).clearAgreeShowDialog();
    
    AppRate.with(this).showRateDialog(this);
    
    LayoutInflater inflater = (LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.custom_dialog, (ViewGroup)findViewById(R.id.layout_root));
    AppRate.with(this).setView(view).monitor();
    
    AppRate.with(this).setThemeResId(int);
    
    <resources>
        <string name="rate_dialog_title">Rate this app</string>
        <string name="rate_dialog_message">If you enjoy playing this app, would you mind taking a moment to rate it? It won\'t take more than a minute. Thanks for your support!</string>
        <string name="rate_dialog_ok">Rate It Now</string>
        <string name="rate_dialog_cancel">Remind Me Later</string>
        <string name="rate_dialog_no">No, Thanks</string>
    </resources>
    
    if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING) {
    
    }
    
        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()
                }
            }
        }
    }
    
    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)
                }
            }
        }
    }
    
    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
    
    }
    
    <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>
    
    dependencies {
        // This dependency is downloaded from the Google’s Maven repository.
        // So, make sure you also include that repository in your project's build.gradle file.
        implementation 'com.google.android.play:core:1.8.0'
    }
    
    void askRatings() {
        ReviewManager manager = ReviewManagerFactory.create(this);
        Task<ReviewInfo> request = manager.requestReviewFlow();
        request.addOnCompleteListener(task -> {
            if (task.isSuccessful()) {
                // We can get the ReviewInfo object
                ReviewInfo reviewInfo = task.getResult();
                Task<Void> flow = manager.launchReviewFlow(this, reviewInfo);
                flow.addOnCompleteListener(task2 -> {
                    // The flow has finished. The API does not indicate whether the user
                    // reviewed or not, or even whether the review dialog was shown. Thus, no
                    // matter the result, we continue our app flow.
                });
            } else {
                // There was some problem, continue regardless of the result.
            }
        });
    }
    
    askRatings();
    
    implementation 'com.google.android.play:core:1.8.0'
    
     private var reviewInfo: ReviewInfo? = null
    
     val manager = ReviewManagerFactory.create(context)
    
     val request = manager.requestReviewFlow()
    
     requestFlow.addOnCompleteListener { request ->
         if (request.isSuccessful) {
             //Received ReviewInfo object
             reviewInfo = request.result
         } else {
             //Problem in receiving object
             reviewInfo = null
         }
    
     reviewInfo?.let {
         val flow = reviewManager.launchReviewFlow(this@MainActivity, it)
         flow.addOnCompleteListener {
             //Irrespective of the result, the app flow should continue
         }
     }
    
    implementation 'com.google.android.play:core:1.8.0'
    
    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();
        }
    }
    
      FiveStarMe.with(this)
          .setInstallDays(0) // default 10, 0 means install day.
          .setLaunchTimes(3) // default 10
          .setDebug(false) // default false
          .monitor();
    
    FiveStarMe.showRateDialogIfMeetsConditions(this); //Where *this* is the current activity.
    
    allprojects {
      repositories {
        ...
        maven { url 'https://jitpack.io' }
      }
    }
    
    dependencies {
      implementation 'com.github.numerative:Five-Star-Me:2.0.0'
    }
    
    
    import android.content.Context
    import androidx.core.content.edit
    import java.util.concurrent.TimeUnit
    
    object Rater {
        private const val DAYS_UNTIL_PROMPT = 3L//Min number of days
        private const val LAUNCHES_UNTIL_PROMPT = 3//Min number of launches
        private const val RATER_KEY = "rater_key"
        private const val LAUNCH_COUNTER_KEY = "launch_counter_key"
        private const val FIRST_LAUNCH_KEY = "first_launch_key"
    
        fun Context.appRateCheck(dialog: () -> Unit) {
            val prefs = getSharedPreferences(RATER_KEY, 0)
            val launchesCounter = prefs.getLong(LAUNCH_COUNTER_KEY, 0) + 1
            prefs.edit { putLong(LAUNCH_COUNTER_KEY, launchesCounter) }
    
            var firstLaunch = prefs.getLong(FIRST_LAUNCH_KEY, 0)
            if (firstLaunch == 0L) {
                firstLaunch = System.currentTimeMillis()
                prefs.edit { putLong(FIRST_LAUNCH_KEY, firstLaunch) }
            }
    
            if (launchesCounter >= LAUNCHES_UNTIL_PROMPT) {
                if (System.currentTimeMillis() >= firstLaunch + TimeUnit.DAYS.toMillis(DAYS_UNTIL_PROMPT)) {
                    dialog()
                }
            }
        }
    }
    
    private val manager: ReviewManager by lazy { ReviewManagerFactory.create(context) }
    
    private fun initInAppReview() {
        context?.appRateCheck {
            manager.requestReviewFlow().addOnSuccessListener {
                manager.launchReviewFlow(requireActivity(), it)
            }
        }
    }