Як реалізувати функцію Rate It в додатку Android


94

Я розробляю додаток для Android. В якому все працює правильно. Мій додаток готовий до запуску. Але там мені потрібно реалізувати ще одну функцію. Мені потрібно показати спливаюче вікно, яке містить

Rate It і Remind me later

Тут, якщо будь-який користувач оцінить програму на ринку, спливаюче вікно не зникне. Я шукав у Google і знайшов одне посилання . З цього я розумію, що це неможливо знати. Тож мені потрібна пропозиція щодо цього.

Хто-небудь раніше стикався з цією ситуацією? Якщо так, чи існує якесь рішення чи альтернатива для цього?


Отже, ви просите просто оцінити / нагадати мені пізніше, або запитуєте, як дізнатись, чи визначив певний користувач оцінку програми для Android?
wtsang02

1
я реалізував спливаюче вікно. але як дізнатися, оцінює користувач додаток чи ні
Naveen

-1 Я не бачу різниці між цим запитанням і тим, що знаходиться у посиланні.
wtsang02

2
@ wtsang02, можливо, це правда. Але дивіться питання. - запитав він далі Mar 15 2011. отже, майже 20 місяців. Я думаю, що хтось має рішення чи альтернативу для моєї вимоги. це yi розміщено тут.
Naveen

Ви можете використовувати бібліотеку github.com/Vorlonsoft/AndroidRate ( implementation 'com.vorlonsoft:androidrate:1.0.3')
Олександр Савін

Відповіді:


180

Я реалізував це деякий час назад, певною мірою. Неможливо дізнатись, оцінив користувач програму чи ні, щоб запобігти тому, щоб рейтинги ставали валютою (деякі розробники можуть додати опцію, як "Оцінити цю програму та безкоштовно отримувати так і так у додатку").

Клас, який я написав, передбачає три кнопки та налаштовує діалогове вікно таким чином, що воно відображається лише після запуску програми n(користувачі мають більше шансів оцінити програму, якщо вони вже трохи її використовували. Більшість із них навряд чи навіть знати, що він робить з першого запуску):

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();        
    }
}

Інтеграція класу проста, як додавання:

AppRater.app_launched(this);

До вашої діяльності. Його потрібно додати лише до однієї активності у всій програмі.


1
Це не підтримує декількох користувачів, що використовують один і той же пристрій.
AsafK

1
@AsafK Так, але з кількома користувачами, що використовують один і той самий пристрій, можна впоратись, показавши appraterдіалогове вікно лише після автентифікації та змінивши, shared preferenceщоб включити адресу електронної пошти Google в key.
Стівен,

1
Привіт, у мене є лише одне запитання. Чому ви зробили все статичним? Дякую Raghav!
Ruchir Baronia

2
Привіт, я пробую ваш код вище. Я вклав AppRater.app_launched(this);усередину своєї onCreate()MainActivity. Я також змінив мінімальну кількість необхідних запусків на 2. Але після 2 запуску програми я не бачу діалогового вікна. Чи можете ви мені допомогти? Дякую!
Виняток

1
Краще використовувати перерахування Context.MODE_PRIVATE-context.getSharedPreferences("apprater", Context.MODE_PRIVATE);
Вівек

18

Мій за допомогою 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()головному FragmentActivity:

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

    RateItDialogFragment.show(this, getFragmentManager());

}

Хороший! Я б просто поставив editor.commit () перед тим, як показувати DialogFragment, на випадок, якщо щось завантажиться.
нарко

@narko Дякую. Оновлено.
mixel

Примітка. Це може призвести до витоку пам’яті, якщо ви застосовуєте заявку для збереження спільних налаштувань. Якщо ви уважно помічаєте в setPositiveButtonі setNegativeButton, це пише для спільних налаштувань за допомогою коміту, але якщо ви використовуєте застосунок, який є асинхронним, і буде зберігати посилання на діяльність, поки вона не завершиться, і відразу після цього вона викликає звільнення. Dismiss намагатиметься знищити фрагмент, але не може, оскільки діяльність утримується / використовується процесом застосування спільних налаштувань. (Я носив це, оскільки AndroidStudio запропонує користувачеві змінити коміт на застосування, не робіть цього, якщо ви використовуйте якусь іншу логіку)
Сай

@mixel Як змінити код, щоб мати можливість використовувати його в Activity та без фрагментів?
user1090751

7

Я думаю, те, що ви намагаєтесь зробити, є, мабуть, контрпродуктивним.

Як правило, полегшити оцінку додатків - це гарна ідея, оскільки більшість людей, які турбуються, роблять це тому, що їм подобається. Подейкують, що кількість рейтингів впливає на ваш ринковий рейтинг (хоча я бачу мало доказів цього). Клопотання користувачів щодо оцінки - через нігтьові екрани - швидше за все, призведе до того, що люди очистять ніг, залишивши погану оцінку.

Додавання можливості прямого оцінювання програми спричинило незначне зменшення числових рейтингів для моєї безкоштовної версії та незначне збільшення мого платного додатка. Щодо безкоштовного додатка, мої 4-зіркові рейтинги зросли більше, ніж мої 5-зіркові, оскільки люди, які вважали моє додаток хорошим, але не найкращим, також почали оцінювати його. Зміна становила близько -0,2. Щодо платного, зміна становила приблизно +0,1. Мені слід видалити його з безкоштовної версії, за винятком того, що мені подобається отримувати багато коментарів.

Я помістив свою кнопку оцінки на екран налаштувань (налаштувань), де це не впливає на нормальну роботу. Це все одно збільшило мою рейтингову оцінку в 4 або 5 разів. Я не сумніваюся, що якби я спробував намотати своїх користувачів, щоб зробити рейтинг, я отримав би багато користувачів, які давали мені погані оцінки як протест.


100% правда. Те саме сталося і з моїм безкоштовним додатком.
akash varlani

7

AndroidRate - це бібліотека, яка допоможе вам просувати свою програму для Android, пропонуючи користувачам оцінювати програму після її використання протягом декількох днів.

Модуль Gradle:

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);
  }
}

Умови за замовчуванням для відображення діалогового вікна швидкості:

  1. Додаток запускається більш ніж на 10 днів пізніше встановлення. Змінити через AppRate#setInstallDays(byte).
  2. Додаток запускається більше 10 разів. Змінити через AppRate#setLaunchTimes(byte).
  3. Додаток запускається більше ніж через 1 день після натискання нейтральної кнопки. Змінити через AppRate#setRemindInterval(byte).
  4. Додаток запускається X разів і X% 1 = 0. Змінити через AppRate#setRemindLaunchTimes(byte).
  5. Програма за замовчуванням відображає нейтральне діалогове вікно (Нагадати мені пізніше). Змінити через setShowLaterButton(boolean).
  6. Щоб вказати зворотний дзвінок при натисканні кнопки. Те саме значення, що й другий аргумент, DialogInterface.OnClickListener#onClickбуде передано в аргументі onClickButton.
  7. Налаштування AppRate#setDebug(boolean)гарантує, що запит про рейтинг відображається кожного разу, коли додаток запускається. Ця функція призначена лише для розробки! .

Необов’язкові вимоги до спеціальних подій для відображення діалогового вікна

Ви можете додати додаткові необов’язкові вимоги для відображення діалогового вікна. Кожна вимога може бути додана / вказана як унікальний рядок. Ви можете встановити мінімальну кількість для кожної такої події (наприклад, "action_performed" 3 рази, "button_clicked" 5 разів тощо)

AppRate.with(this).setMinimumEventCount(String, short);
AppRate.with(this).incrementEventCount(String);
AppRate.with(this).setEventCountValue(String, short);

Очистити прапорець діалогового вікна показу

Якщо ви хочете знову показати діалогове вікно, телефонуйте AppRate#clearAgreeShowDialog().

AppRate.with(this).clearAgreeShowDialog();

Коли кнопка натискається

дзвінок AppRate#showRateDialog(Activity).

AppRate.with(this).showRateDialog(this);

Встановити власний вигляд

дзвінок AppRate#setView(View).

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);

Спеціальне діалогове вікно

Якщо ви хочете використовувати власні мітки діалогового вікна, перевизначте рядкові ресурси XML у своїй програмі.

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

Перевірте, чи доступний Google Play

if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING) {

}


3

Це рішення дуже схоже на наведені вище. Єдина відмінність полягає в тому, що ви зможете затримати підказку діалогового вікна оцінки за запуски та дні. Якщо натиснути кнопку нагадати мені пізніше, тоді я затримаю спливаюче вікно на 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>

джерело: Підхід Android для "Оцініть мою програму"


Що таке "Конфігурації", він не знайдений при спробі.
Md Imran Choudhury

1
@ Md.ImranChoudhury Вибачте за пізню відповідь. Конфігурації - це мій приватний клас, який я використовую для аналітики Google. Ви можете просто видалити це твердження без проблем!
Густаво Байоккі Коста,

ви повинні або посилатися на оригінальну відповідь, або віддати йому належне. stackoverflow.com/a/6920848/563735
Рохіт Mandiwal


1

Як ви бачите з іншого допису, який ви зв’язали, програма не може дізнатися, залишив користувач відгук чи ні. І недарма.

Подумайте: якщо програма зможе визначити, залишив користувач відгук чи ні, розробник може обмежити певні функції, які розблокуються лише в тому випадку, якщо користувач залишає рейтинг 5/5. Це призвело б до того, що інші користувачі Google Play не довірятимуть відгукам і підірвали б систему рейтингу.

Альтернативні рішення, які я бачив, полягають у тому, що додаток нагадує користувачеві подати оцінку щоразу, коли програму відкривають певну кількість разів або встановлений інтервал. Наприклад, кожного 10-го разу, коли додаток відкривається, попросіть користувача залишити рейтинг і надати кнопки "вже зроблено" та "нагадати мені пізніше". Продовжуйте показувати це повідомлення, якщо користувач вирішив нагадати йому про це пізніше. Деякі інші розробники додатків показують це повідомлення зі збільшеним інтервалом (наприклад, 5, 10, 15-й раз, коли додаток відкривається), тому що якщо користувач не залишив відгук, наприклад, у 100-й раз відкриття програми, це ймовірно, він / вона не піде з нього.

Це рішення не ідеальне, але я думаю, що це найкраще, що у вас є на даний момент. Це змусить вас довіряти користувачеві, але ви розумієте, що альтернатива означатиме потенційно гірший досвід для всіх на ринку додатків.


1

Рішення Java & Kotlin (API для перегляду додатків від Google у 2020 році):

введіть тут опис зображення

Спочатку у свій build.gradle(app)файл додайте такі залежності (повне налаштування тут )

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'
}

Додайте цей метод до свого Activity:

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();

Код Kotlin можна знайти тут


0

Котлінська версія відповіді Рагава Суда

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()
            }
        }
    }
}

Оптимізована відповідь

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)
            }
        }
    }
}

Константи.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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.