Comment mettre en œuvre la fonctionnalité Rate It dans l'application Android

94

Je développe une application Android. Dans lequel tout fonctionne correctement. Mon application est prête à être lancée. Mais là, je dois implémenter une fonctionnalité supplémentaire. J'ai besoin d'afficher un popup qui contient

Rate It et Remind me later

Ici, si un utilisateur évalue l'application sur le marché, la fenêtre contextuelle ne disparaîtra pas. J'ai cherché dans Google et trouvé un lien . Avec cela, je comprends que ce n'est pas possible de savoir. J'ai donc besoin d'une suggestion pour cela.

Quelqu'un a-t-il déjà fait face à cette situation? Si oui, y a-t-il une solution ou une alternative pour cela?

Naveen
la source
Alors, demandez-vous simplement la note / rappelez-moi plus tard ou demandez-vous comment savoir si un utilisateur spécifique a évalué une application Android?
wtsang02
1
j'ai implémenté le popup. mais comment savoir si un utilisateur évalue l'application ou non
Naveen
-1 Je ne vois pas la différence entre cette question et celle du lien.
wtsang02
2
@ wtsang02, c'est peut-être vrai. Mais voyez la question. son demandé Mar 15 2011. donc presque 20 mois. Je pense que quelqu'un a une solution ou une alternative pour mon besoin. c'est yi posté ici.
Naveen
Vous pouvez utiliser la bibliothèque github.com/Vorlonsoft/AndroidRate ( implementation 'com.vorlonsoft:androidrate:1.0.3')
Alexander Savin

Réponses:

180

J'ai mis en œuvre cela il y a quelque temps, dans une certaine mesure. Il est impossible de savoir si un utilisateur a noté une application ou non, pour éviter que les notes ne deviennent une devise (certains développeurs peuvent ajouter une option telle que "Évaluer cette application et obtenir ceci et cela gratuitement").

La classe que j'ai écrite fournit trois boutons et configure la boîte de dialogue pour qu'elle ne s'affiche qu'après le lancement de l'application n(les utilisateurs ont plus de chances de noter l'application s'ils l'ont utilisée un peu auparavant. La plupart d'entre eux sont peu probables. pour même savoir ce qu'il fait au premier passage):

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

L'intégration de la classe est aussi simple que l'ajout:

AppRater.app_launched(this);

À votre activité. Il ne doit être ajouté qu'à une activité dans l'ensemble de l'application.

Raghav Sood
la source
1
Cela ne prend pas en charge plusieurs utilisateurs utilisant le même appareil.
AsafK
1
@AsafK Oui, mais plusieurs utilisateurs utilisant le même appareil peuvent être gérés en affichant uniquement la appraterboîte de dialogue après l'authentification et en modifiant shared preferencepour inclure l'adresse e-mail Google dans le fichier key.
stephen
1
Salut, j'ai juste une question. Pourquoi avez-vous tout rendu statique? Merci Raghav!
Ruchir Baronia
2
Salut, j'essaye votre code ci-dessus. J'ai mis AppRater.app_launched(this);dans mon onCreate()mainActivity. J'ai également changé le nombre minimum de lancements requis à 2. Mais, je ne vois pas la boîte de dialogue après le lancement de 2 applications. Peux-tu m'aider? Merci!
Exception
1
Mieux vaut utiliser l'énumération Context.MODE_PRIVATE-context.getSharedPreferences("apprater", Context.MODE_PRIVATE);
Vivek
18

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

Ensuite, utilisez-le dans onCreate()votre FragmentActivity principale:

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

    RateItDialogFragment.show(this, getFragmentManager());

}
mixel
la source
Bon! Je mettrais juste le editor.commit () avant d'afficher le DialogFragment juste au cas où quelque chose ne va pas lors du chargement du Dialog.
narko
@narko Merci. Actualisé.
mixel
Remarque: cela peut entraîner une fuite de mémoire si vous utilisez pour appliquer pour enregistrer la préférence partagée. Si vous le remarquez attentivement dans setPositiveButtonet setNegativeButton, il s'agit d'écrire dans les préférences partagées en utilisant commit, mais si vous utilisez apply, qui est asynchrone et conservera la référence à l'activité jusqu'à ce qu'elle se termine et juste après, il appelle à rejeter. Dismiss essaiera de détruire le fragment, mais ce ne sera pas possible car l'activité est détenue / utilisée par le processus d'application des préférences partagées (je l'ai porté car AndroidStudio invitera l'utilisateur à modifier la validation pour appliquer, ne le faites pas sauf si vous utiliser une autre logique)
Sai
@mixel Comment modifier le code pour pouvoir l'utiliser en Activity et sans fragment?
user1090751
7

Je pense que ce que vous essayez de faire est probablement contre-productif.

Permettre aux utilisateurs de noter facilement les applications est généralement une bonne idée, car la plupart des personnes qui s'en soucient le font parce qu'elles aiment l'application. Selon certaines rumeurs, le nombre de notes affecte votre note sur le marché (même si je vois peu de preuves de cela). Inciter les utilisateurs à évaluer - via des écrans de bourdonnement - est susceptible de pousser les gens à effacer le problème en laissant une mauvaise note.

L'ajout de la possibilité d'évaluer directement une application a entraîné une légère diminution des notes numériques de ma version gratuite et une légère augmentation de mon application payante. Pour l'application gratuite, mes notes de 4 étoiles ont augmenté plus que mes notes de 5 étoiles, car les gens qui pensaient que mon application était bonne mais pas géniale ont également commencé à la noter. Le changement était d'environ -0,2. Pour les payés, le changement était d'environ +0,1. Je devrais le supprimer de la version gratuite, sauf que j'aime recevoir beaucoup de commentaires.

J'ai mis mon bouton d'évaluation dans un écran de paramètres (préférences), où il n'affecte pas le fonctionnement normal. Cela a quand même augmenté mon taux de notation par un facteur de 4 ou 5. Je ne doute pas que si j'essayais de harceler mes utilisateurs pour qu'ils fassent une évaluation, je recevrais beaucoup d'utilisateurs me donnant de mauvaises notes en guise de protestation.

Peter Webb
la source
100% vrai. La même chose s'est produite avec mon application gratuite.
akash varlani
7

AndroidRate est une bibliothèque pour vous aider à promouvoir votre application Android en invitant les utilisateurs à évaluer l'application après l'avoir utilisée pendant quelques jours.

Gradle du module:

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

Les conditions par défaut pour afficher la boîte de dialogue de taux sont les suivantes:

  1. L'application est lancée plus de 10 jours après l'installation. Changer via AppRate#setInstallDays(byte).
  2. L'application est lancée plus de 10 fois. Changer via AppRate#setLaunchTimes(byte).
  3. L'application est lancée plus d'un jour après le clic sur le bouton neutre. Changer via AppRate#setRemindInterval(byte).
  4. L'application est lancée X fois et X% 1 = 0. Changement via AppRate#setRemindLaunchTimes(byte).
  5. L'application affiche une boîte de dialogue neutre (me le rappeler plus tard) par défaut. Changer via setShowLaterButton(boolean).
  6. Pour spécifier le rappel lorsque le bouton est enfoncé. La même valeur que le deuxième argument de DialogInterface.OnClickListener#onClicksera transmise dans l'argument de onClickButton.
  7. Le réglage AppRate#setDebug(boolean)garantira que la demande d'évaluation est affichée à chaque fois que l'application est lancée. Cette fonctionnalité est uniquement destinée au développement! .

Exigences d'événement personnalisé facultatives pour l'affichage de la boîte de dialogue

Vous pouvez ajouter des exigences facultatives supplémentaires pour l'affichage de la boîte de dialogue. Chaque exigence peut être ajoutée / référencée sous la forme d'une chaîne unique. Vous pouvez définir un nombre minimum pour chacun de ces événements (par exemple "action_performed" 3 fois, "button_clicked" 5 fois, etc.)

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

Effacer l'indicateur de la boîte de dialogue d'affichage

Lorsque vous souhaitez afficher à nouveau la boîte de dialogue, appelez AppRate#clearAgreeShowDialog().

AppRate.with(this).clearAgreeShowDialog();

Lorsque le bouton appuie sur

appeler AppRate#showRateDialog(Activity).

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

Définir une vue personnalisée

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

Thème spécifique

Vous pouvez utiliser un thème spécifique pour gonfler la boîte de dialogue.

AppRate.with(this).setThemeResId(int);

Boîte de dialogue personnalisée

Si vous souhaitez utiliser vos propres libellés de boîte de dialogue, remplacez les ressources XML de chaîne sur votre application.

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

Vérifiez que Google Play est disponible

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

}
Alexandre Savin
la source
3

Cette solution est très similaire à celles présentées ci-dessus. La seule différence est que vous serez en mesure de retarder l'invite de la boîte de dialogue d'évaluation par lancements et jours. Si le bouton me rappeler plus tard est enfoncé, je retarderai la fenêtre contextuelle de 3 jours et 10 lancements. La même chose est faite pour ceux qui ont choisi de l'évaluer, mais les délais sont plus longs (pour ne pas déranger l'utilisateur si tôt au cas où il aurait effectivement évalué l'application. Cela peut être modifié pour ne plus être affiché, alors vous devrez modifier le code à votre goût). J'espère que cela aide quelqu'un!

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

Les boutons ont une couleur et un arrière-plan spécifiques. L'arrière-plan est comme indiqué dans ce fichier 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>

source: approche Android pour "Evaluer mon application"

Gustavo Baiocchi Costa
la source
Qu'est-ce que "Configs" on ne le trouve pas quand j'essaye.
Md Imran Choudhury
1
@ Md.ImranChoudhury Désolé pour la réponse tardive. Les configs sont une de mes classes privées que j'utilise pour Google Analytics. Vous pouvez simplement supprimer cette déclaration sans problème!
Gustavo Baiocchi Costa
vous devez soit créer un lien vers la réponse originale, soit lui donner du crédit. stackoverflow.com/a/6920848/563735
Rohit Mandiwal
1

Comme vous le voyez dans l'autre article que vous avez lié, l'application ne peut pas savoir si l'utilisateur a laissé un avis ou non. Et pour une bonne raison.

Pensez-y, si une application pouvait dire si l'utilisateur a laissé un avis ou non, le développeur pourrait restreindre certaines fonctionnalités qui ne seraient déverrouillées que si l'utilisateur laisse une note de 5/5. Cela conduirait les autres utilisateurs de Google Play à ne pas faire confiance aux avis et minerait le système de notation.

Les solutions alternatives que j'ai vues sont que l'application rappelle à l'utilisateur de soumettre une évaluation chaque fois que l'application est ouverte un nombre spécifique de fois ou à un intervalle défini. Par exemple, à chaque dixième fois que l'application est ouverte, demandez à l'utilisateur de laisser une note et de fournir un bouton «déjà fait» et «me rappeler plus tard». Continuez à afficher ce message si l'utilisateur a choisi de le lui rappeler plus tard. Certains autres développeurs d'applications affichent ce message avec un intervalle croissant (par exemple, 5, 10, 15nème fois que l'application est ouverte), car si un utilisateur n'a pas laissé d'avis sur, par exemple, la 100ème fois que l'application a été ouverte, c'est probablement il / elle n'en laissera pas un.

Cette solution n'est pas parfaite, mais je pense que c'est la meilleure que vous ayez pour le moment. Cela vous amène à faire confiance à l'utilisateur, mais réalisez que l'alternative signifierait une expérience potentiellement pire pour tout le monde sur le marché des applications.

Vidhur Vohra
la source
1

Solution Java & Kotlin (API d'examen dans l'application par Google en 2020):

entrez la description de l'image ici

Tout d'abord, dans votre build.gradle(app)fichier, ajoutez les dépendances suivantes (configuration complète ici )

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

Ajoutez cette méthode à votre 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.
        }
    });
}

Appelez-le comme n'importe quelle autre méthode:

askRatings();

Le code Kotlin peut être trouvé ici

iLoveDocs
la source
0

Version Kotlin de la réponse de Raghav Sood

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

Réponse optimisée

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>
Victor R. Oliveira
la source
0

Lancement du nouveau système d'examen intégré aux applications d'Android, qui permet aux développeurs de demander des avis sur le Play Store sans quitter l'application.

Pour vérifier les directives de conception et quand afficher une carte de révision, reportez-vous au document officiel

https://developer.android.com/guide/playcore/in-app-review

Implémenter:

  • Ajoutez la bibliothèque play-core en tant que dépendance dans votre fichier build.gradle.
implementation 'com.google.android.play:core:1.8.0'
  • Créez une instance ReviewManager et demandez un objet ReviewInfo . L'objet ReviewInfo doit être pré-mis en cache et peut ensuite déclencher «launchReviewFlow» pour présenter la carte de révision à l'utilisateur.

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

Remarque: il est suggéré d'afficher le flux d'examen une fois que l'utilisateur a suffisamment expérimenté votre application ou votre jeu.

Quand demander un examen dans l'application:

  • Déclenchez le flux d'examen dans l'application après qu'un utilisateur a suffisamment expérimenté votre application ou votre jeu pour fournir des commentaires utiles.
  • N'invitez pas trop l'utilisateur à un examen. Cette approche permet de minimiser la frustration des utilisateurs et de limiter l'utilisation de l'API (voir la section sur les quotas).
  • Votre application ne doit poser aucune question à l'utilisateur avant ou pendant la présentation du bouton ou de la carte de notation, y compris des questions sur son opinion (telles que "Aimez-vous l'application?") Ou des questions prédictives (telles que "Évaluer cette application 5 étoiles ”).

Quelques points avant de tester ceci:

  • Lors du test de nouvelles fonctionnalités, nous créons principalement un nouveau projet qui aurait un nouvel ApplicationId, assurez-vous de donner un ApplicationId qui est déjà publié et disponible dans le Play Store.

  • Si vous avez déjà donné des commentaires sur votre application, launchReviewFlow de l'API d'examen intégré à l' application ne présentera aucune carte d'évaluation . Cela déclenche simplement un événement de réussite.

  • En raison des limitations de quota, l'appel d'une méthode launchReviewFlow peut ne pas toujours afficher une boîte de dialogue. Il ne doit être lié à aucun événement de clic.

Arunendra
la source