Come implementare la funzione Rate It nell'app Android


94

Sto sviluppando un'app per Android. In cui tutto funziona bene. La mia app è pronta per il lancio. Ma lì ho bisogno di implementare un'altra funzionalità. Devo visualizzare un popup che contiene

Rate It e Remind me later

Qui se un utente valuta l'app nel mercato, il popup non scomparirà. Ho cercato su Google e ho trovato un collegamento . Con questo capisco che non è possibile saperlo. Quindi ho bisogno di un suggerimento per questo.

Qualcuno ha affrontato questa situazione prima? In caso affermativo, esiste una soluzione o un'alternativa per questo?


Quindi stai chiedendo solo la valutazione / ricordamelo più tardi o stai chiedendo come sapere se un utente specifico ha valutato un'app Android?
wtsang02

1
ho implementato il popup. ma come sapere se un utente valuta o meno l'app
Naveen

-1 Non vedo la differenza tra questa domanda e quella nel link.
wtsang02

2
@ wtsang02, potrebbe essere vero. Ma guarda la domanda. è chiesto Mar 15 2011. quindi sono passati quasi 20 mesi. Penso che qualcuno abbia una soluzione o un'alternativa per la mia esigenza. questo è pubblicato qui.
Naveen

Puoi utilizzare la libreria github.com/Vorlonsoft/AndroidRate ( implementation 'com.vorlonsoft:androidrate:1.0.3')
Alexander Savin

Risposte:


180

L'ho implementato qualche tempo fa, in una certa misura. È impossibile sapere se un utente ha valutato o meno un'app, per evitare che le valutazioni diventino una valuta (alcuni sviluppatori potrebbero aggiungere un'opzione come "Valuta questa app e ottieni così e così nell'app gratuitamente").

La classe che ho scritto fornisce tre pulsanti e configura la finestra di dialogo in modo che venga visualizzata solo dopo che l'app è stata avviata nvolte (gli utenti hanno maggiori possibilità di classificare l'app se l'hanno usata un po 'prima. La maggior parte di essi è improbabile per sapere anche cosa fa alla prima esecuzione):

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

Integrare la classe è semplice come aggiungere:

AppRater.app_launched(this);

Alla tua attività. Deve essere aggiunto solo a un'attività nell'intera app.


1
Questo non supporta più utenti che utilizzano lo stesso dispositivo.
AsafK

1
@AsafK Sì, ma più utenti che utilizzano lo stesso dispositivo possono essere gestiti mostrando la appraterfinestra di dialogo solo dopo l'autenticazione e modificando shared preferenceper includere l'indirizzo email di Google nel file key.
stephen

1
Ciao, ho solo una domanda. Perché hai reso tutto statico? Grazie Raghav!
Ruchir Baronia

2
Ciao, sto provando il tuo codice sopra. Ho inserito AppRater.app_launched(this);nel mio onCreate()di MainActivity. Ho anche cambiato il numero minimo di lanci richiesti a 2. Ma non vedo la finestra di dialogo dopo 2 lanci di app. Puoi darmi una mano? Grazie!
Eccezione

1
Meglio usare l'enumerazione Context.MODE_PRIVATE-context.getSharedPreferences("apprater", Context.MODE_PRIVATE);
Vivek

18

Il mio che usa 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();
    }
}

Quindi usalo nella onCreate()tua FragmentActivity principale:

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

    RateItDialogFragment.show(this, getFragmentManager());

}

Buono! Vorrei solo mettere editor.commit () prima di mostrare il DialogFragment nel caso in cui qualcosa vada storto durante il caricamento del Dialog.
narko

@narko Thanks. Aggiornato.
mixel

Nota: può portare a una perdita di memoria se si utilizza per applicare per salvare la preferenza condivisa. Se noti attentamente in setPositiveButtone setNegativeButton, sta scrivendo nelle preferenze condivise usando commit ma se usi apply che è asincrono e manterrà il riferimento all'attività fino a quando non sarà completo e subito dopo chiamerà dismiss. Dismiss proverà a distruggere il frammento, ma non può perché l'attività è trattenuta / utilizzata dal processo di applicazione delle preferenze condivise (l'ho indossato perché AndroidStudio chiederà all'utente di modificare il commit per applicare, non farlo a meno che tu usa qualche altra logica)
Sai

@mixel Come modificare il codice per poterlo utilizzare in Activity e senza frammenti?
user1090751

7

Penso che quello che stai cercando di fare sia probabilmente controproducente.

Rendere facile per le persone valutare le app è generalmente una buona idea, poiché la maggior parte delle persone che si preoccupano lo fanno perché apprezzano l'app. Si dice che il numero di valutazioni influenzi la tua valutazione di mercato (anche se ne vedo poche prove). Assalire gli utenti nella valutazione - attraverso gli schermi dei nag - rischia di indurre le persone a cancellare il ronzio lasciando una valutazione negativa.

L'aggiunta della possibilità di valutare direttamente un'app ha causato una leggera diminuzione delle valutazioni numeriche per la mia versione gratuita e un leggero aumento della mia app a pagamento. Per l'app gratuita, le mie valutazioni a 4 stelle sono aumentate più delle mie valutazioni a 5 stelle, poiché anche le persone che pensavano che la mia app fosse buona ma non eccezionale hanno iniziato a valutarla. La variazione è stata di circa -0,2. Per il pagato, il cambiamento era di circa +0,1. Dovrei rimuoverlo dalla versione gratuita, tranne per il fatto che mi piace ricevere molti commenti.

Ho inserito il mio pulsante di valutazione in una schermata delle impostazioni (preferenze), dove non influisce sul normale funzionamento. Ha comunque aumentato il mio tasso di valutazione di un fattore di 4 o 5. Non ho dubbi che se provassi ad assillare i miei utenti a fare una valutazione, otterrei molti utenti che mi danno valutazioni negative come protesta.


100% vero. La stessa cosa è successa anche con la mia app gratuita.
akash varlani

7

AndroidRate è una libreria che ti aiuta a promuovere la tua app Android chiedendo agli utenti di valutare l'app dopo averla utilizzata per alcuni giorni.

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

Le condizioni predefinite per mostrare la finestra di dialogo del tasso sono le seguenti:

  1. L'app viene avviata più di 10 giorni dopo l'installazione. Cambia via AppRate#setInstallDays(byte).
  2. L'app viene lanciata più di 10 volte. Cambia via AppRate#setLaunchTimes(byte).
  3. L'app viene avviata più di 1 giorni dopo aver fatto clic sul pulsante neutro. Cambia via AppRate#setRemindInterval(byte).
  4. L'app viene avviata X volte e X% 1 = 0. Modifica tramite AppRate#setRemindLaunchTimes(byte).
  5. L'app mostra una finestra di dialogo neutra (ricordamelo più tardi) per impostazione predefinita. Cambia via setShowLaterButton(boolean).
  6. Per specificare la richiamata quando si preme il pulsante. Lo stesso valore del secondo argomento di DialogInterface.OnClickListener#onClickverrà passato nell'argomento di onClickButton.
  7. L'impostazione AppRate#setDebug(boolean)garantirà che la richiesta di valutazione venga visualizzata ogni volta che l'app viene avviata. Questa funzione è solo per lo sviluppo! .

Requisiti evento personalizzati opzionali per la visualizzazione della finestra di dialogo

È possibile aggiungere ulteriori requisiti opzionali per la visualizzazione della finestra di dialogo. Ogni requisito può essere aggiunto / referenziato come una stringa univoca. Puoi impostare un conteggio minimo per ciascuno di questi eventi (ad esempio "action_performed" 3 volte, "button_clicked" 5 volte, ecc.)

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

Cancella il flag della finestra di dialogo dello spettacolo

Quando vuoi mostrare di nuovo la finestra di dialogo, chiama AppRate#clearAgreeShowDialog().

AppRate.with(this).clearAgreeShowDialog();

Quando il pulsante preme

chiamare AppRate#showRateDialog(Activity).

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

Imposta visualizzazione personalizzata

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

Tema specifico

Puoi usare un tema specifico per gonfiare la finestra di dialogo.

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

Finestra di dialogo personalizzata

Se desideri utilizzare le tue etichette di dialogo, sovrascrivi le risorse xml della stringa nell'applicazione.

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

Verifica che Google Play sia disponibile

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

}


3

Questa soluzione è molto simile a quelle presentate sopra. L'unica differenza è che sarai in grado di ritardare il prompt della finestra di dialogo di valutazione per lanci e giorni. Se viene premuto il pulsante Ricordami più tardi, ritarderò il popup di 3 giorni e 10 lanci. Lo stesso vale per coloro che hanno scelto di valutarla, tuttavia i ritardi sono più lunghi (per non disturbare l'utente così presto nel caso in cui abbia effettivamente valutato l'app. Questo può essere modificato per non essere mostrato più, quindi dovrai farlo modifica il codice a tuo piacimento). Spero che aiuti qualcuno!

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

I pulsanti hanno un colore e uno sfondo specifici. Lo sfondo è come mostrato in questo file 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>

fonte: approccio Android per "Valuta la mia applicazione"


Ciò che è "Configs" non viene trovato quando provo.
Md Imran Choudhury

1
@ Md.ImranChoudhury Ci scusiamo per la risposta tardiva. La configurazione è una mia classe privata che utilizzo per Google Analytics. Puoi semplicemente rimuovere quella dichiarazione senza problemi!
Gustavo Baiocchi Costa

dovresti collegarti alla risposta originale o dargli credito. stackoverflow.com/a/6920848/563735
Rohit Mandiwal


1

Come puoi vedere dall'altro post che hai collegato, l'app non può sapere se l'utente ha lasciato una recensione o meno. E per una buona ragione.

Pensaci, se un'app potesse dire se l'utente ha lasciato una recensione o meno, lo sviluppatore potrebbe limitare alcune funzionalità che sarebbero sbloccate solo se l'utente lascia una valutazione di 5/5. Ciò porterebbe gli altri utenti di Google Play a non fidarsi delle recensioni e minerebbe il sistema di valutazione.

La soluzione alternativa che ho visto è che l'app ricorda all'utente di inviare una valutazione ogni volta che l'app viene aperta un numero specifico di volte o un intervallo impostato. Ad esempio, ogni 10 volte che l'app viene aperta, chiedi all'utente di lasciare una valutazione e fornire un pulsante "già fatto" e "ricordamelo più tardi". Continua a mostrare questo messaggio se l'utente ha scelto di ricordarglielo in seguito. Alcuni altri sviluppatori di app mostrano questo messaggio con un intervallo crescente (come, 5, 10, 15esima volta che l'app viene aperta), perché se un utente non ha lasciato una recensione, ad esempio, la centesima volta che l'app è stata aperta, è probabilmente probabilmente non ne lascerà uno.

Questa soluzione non è perfetta, ma penso che sia la migliore che hai per ora. Ti porta a fidarti dell'utente, ma renditi conto che l'alternativa significherebbe un'esperienza potenzialmente peggiore per tutti nel mercato delle app.


1

Soluzione Java e Kotlin (API di revisione in-app di Google nel 2020):

inserisci qui la descrizione dell'immagine

Innanzitutto, nel tuo build.gradle(app)file, aggiungi le seguenti dipendenze (configurazione completa qui )

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

Aggiungi questo metodo a 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.
        }
    });
}

Chiamalo come qualsiasi altro metodo:

askRatings();

Il codice Kotlin può essere trovato qui


0

Versione Kotlin della risposta di 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()
            }
        }
    }
}

Risposta ottimizzata

Rater.kt

class Rater {
    companion object {
        fun start(context: Context) {
            val prefs: SharedPreferences = context.getSharedPreferences(RATER_KEY, 0)
            if (prefs.getBoolean(DO_NOT_SHOW_AGAIN_KEY, false)) {
                return
            }

            val editor: Editor = prefs.edit()

            val launchesCounter: Long = prefs.getLong(LAUNCH_COUNTER_KEY, 0) + 1;
            editor.putLong(LAUNCH_COUNTER_KEY, launchesCounter)

            var firstLaunch: Long = prefs.getLong(FIRST_LAUNCH_KEY, 0)
            if (firstLaunch == 0L) {
                firstLaunch = System.currentTimeMillis()
                editor.putLong(FIRST_LAUNCH_KEY, firstLaunch)
            }

            if (launchesCounter >= LAUNCHES_UNTIL_PROMPT) {
                if (System.currentTimeMillis() >= firstLaunch +
                    (DAYS_UNTIL_PROMPT * 24 * 60 * 60 * 1000)
                ) {
                    showRateDialog(context, editor)
                }
            }

            editor.apply()
        }

        fun showRateDialog(context: Context, editor: Editor) {
            Dialog(context).apply {
                setTitle("Rate $APP_TITLE")
                LinearLayout(context).let { layout ->
                    layout.orientation = LinearLayout.VERTICAL
                    setDescription(context, layout)
                    setPositiveAnswer(context, layout)
                    setNeutralAnswer(context, layout)
                    setNegativeAnswer(context, editor, layout)
                    setContentView(layout)
                    show()       
                }
            }
        }

        private fun setDescription(context: Context, layout: LinearLayout) {
            TextView(context).apply {
                text = context.getString(R.string.rate_description, APP_TITLE)
                width = 240
                setPadding(4, 0, 4, 10)
                layout.addView(this)
            }
        }

        private fun Dialog.setPositiveAnswer(
            context: Context,
            layout: LinearLayout
        ) {
            Button(context).apply {
                text = context.getString(R.string.rate_now)
                setOnClickListener {
                    context.startActivity(
                        Intent(
                            Intent.ACTION_VIEW,
                            Uri.parse(context.getString(R.string.market_uri, APP_NAME))
                        )
                    );
                    dismiss()
                }
                layout.addView(this)
            }
        }

        private fun Dialog.setNeutralAnswer(
            context: Context,
            layout: LinearLayout
        ) {
            Button(context).apply {
                text = context.getString(R.string.remind_later)
                setOnClickListener {
                    dismiss()
                };
                layout.addView(this)
            }
        }

        private fun Dialog.setNegativeAnswer(
            context: Context,
            editor: Editor,
            layout: LinearLayout
        ) {
            Button(context).apply {
                text = context.getString(R.string.no_thanks)
                setOnClickListener {
                    editor.putBoolean(DO_NOT_SHOW_AGAIN_KEY, true);
                    editor.commit()
                    dismiss()
                };
                layout.addView(this)
            }
        }
    }
}

Constants.kt

object Constants {

    const val APP_TITLE = "App Name"
    const val APP_NAME = "com.example.name"

    const val RATER_KEY = "rater_key"
    const val LAUNCH_COUNTER_KEY = "launch_counter_key"
    const val DO_NOT_SHOW_AGAIN_KEY = "do_not_show_again_key"
    const val FIRST_LAUNCH_KEY = "first_launch_key"

    const val DAYS_UNTIL_PROMPT: Int = 3
    const val LAUNCHES_UNTIL_PROMPT: Int = 3

}

strings.xml

<resources>
    <string name="rate_description">If you enjoy using %1$s, please take a moment to rate it. Thanks for your support!</string>
    <string name="rate_now">Rate now</string>
    <string name="no_thanks">No, thanks</string>
    <string name="remind_later">Remind me later</string>
    <string name="market_uri">market://details?id=%1$s</string>
</resources>

0

Lanciato il nuovo sistema di revisione in-app di Android che consente agli sviluppatori di chiedere le recensioni del Play Store senza lasciare l'app.

Per verificare le linee guida di progettazione e quando visualizzare una scheda di revisione, fare riferimento al documento ufficiale

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

Implementare:

  • Aggiungi la libreria play-core come dipendenza nel tuo file build.gradle.
implementation 'com.google.android.play:core:1.8.0'
  • Crea un'istanza ReviewManager e richiedi l' oggetto ReviewInfo . L'oggetto ReviewInfo da memorizzare nella cache e quindi può attivare "launchReviewFlow" per presentare la scheda Review all'utente.

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

Nota: si consiglia di mostrare il flusso di revisione dopo che l'utente ha avuto abbastanza esperienza della tua app o del tuo gioco.

Quando richiedere una revisione in-app:

  • Attiva il flusso di revisione in-app dopo che un utente ha avuto abbastanza esperienza della tua app o del tuo gioco per fornire un feedback utile.
  • Non chiedere eccessivamente all'utente una revisione. Questo approccio aiuta a ridurre al minimo la frustrazione degli utenti e limitare l'utilizzo dell'API (vedere la sezione sulle quote).
  • La tua app non deve porre all'utente alcuna domanda prima o durante la presentazione del pulsante o della scheda di valutazione, comprese domande sulla sua opinione (come "Ti piace l'app?") O domande predittive (come "Valuteresti questa app con 5 stelle ").

Pochi punti prima di provare questo:

  • Durante il test di nuove funzionalità, per lo più creiamo un nuovo progetto che avrebbe un nuovo ApplicationId, assicurati di fornire un ApplicationId che è già rilasciato e disponibile nel Play Store.

  • Se hai fornito feedback in passato per la tua app, launchReviewFlow dell'API di revisione in-app non presenterà alcuna scheda di revisione . Innesca semplicemente un evento di successo.

  • A causa dei limiti di quota, la chiamata a un metodo launchReviewFlow potrebbe non visualizzare sempre una finestra di dialogo. Non dovrebbe essere collegato a nessun evento di clic.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.