Skip to content

troii/integrated-rating-request

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status JCenter

Integrated Rating Request

Forked from mediavrog/integrated-rating-request

A better way to ask for ratings.

As popularized by Circa.

  • get better ratings by showing the rate reminder in your layout instead of popup
  • full control over design, irr manages only the flow and visibility of the rate reminder
  • customize the conditions when to show the rate reminder
  • .. or supply your own RuleEngine altogether for full control (backed by ruli)
  • adjustable callbacks for rating and feedback
  • list adapter decorator can manage visibility of irr in a list automatically so you don't have to

Getting started

Gradle Dependency (jcenter)

Easily reference the library in your Android projects using this dependency in your module's build.gradle file.

dependencies {
    implementation 'com.troii:integrated-rating-request:2.0.1'
}

Usage

  • Track app starts in your custom application Application#onStart or similar place using DefaultRuleEngine.trackAppStart(Context ctx);. This is required for the default rule engine to work properly. The default rule engine is backed by SharedPreferences and writes data to APP_PACKAGE_NAME.irr_default_rule_engine.
  • Include the layout net.mediavrog.irr.IrrLayout in your layout. Add the namespace xmlns:irr="http://schemas.android.com/apk/res-auto" to the root element.
  • Add three child layouts for the user flow identified by
    • @id/irr_nudge_layout Ask user if he likes the app.
    • @id/irr_rate_layout If so nudge user to rate app.
    • @id/irr_feedback_layout Else ask for feedback.
  • Each must have two buttons for user interaction identified by
    • @id/irr_nudge_accept_btn User enjoys the app. Proceed to rating.
    • @id/irr_nudge_decline_btn User doesn't enjoy the app. Proceed to feedback.
    • @id/irr_rate_accept_btn User wants to leave a rating.
    • @id/irr_rate_decline_btn User declines leaving a rating.
    • @id/irr_feedback_accept_btn User wants to leave feeback.
    • @id/irr_feedback_decline_btn User declines to leave feedback.
  • Set user action urls
    • irr:ratingUrl sets the url to ACTION_VIEW once a user wants to rate the app. (Default: https://play.google.com/store/apps/details?id=APP_PACKAGE_NAME)
    • irr:feedbackUrl sets the url to ACTION_VIEW once a user wants to give feedback. (Default: null)
  • [optional] Tune the rule engine parameters:
    • irr:defaultRuleAppStartCount Minimum amount of app starts before nudging for first time. (Default: 10)
    • irr:defaultRuleDistinctDays Minimum amount of distinct days the user has opened the app before nudging for first time. (Default: 3)
    • irr:defaultRuleDismissPostponeDays Postpone nudging the user again by some days when he gave feedback or left the flow without action. (Default: 7)
    • irr:defaultRuleDismissMaxCount Maximum number of times a user can dismiss before nudging him is deactivated forever. (Default: 3)

This should cover a basic setup. See the demo code for more details.

Example Basic intgrated rating request usage (styles are taken from the demo app)

<net.mediavrog.irr.IrrLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:irr="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    irr:defaultRuleAppStartCount="10"
    irr:defaultRuleDismissMaxCount="3"
    irr:defaultRuleDismissPostponeDays="7"
    irr:defaultRuleDistinctDays="3"
    irr:feedbackUrl="@string/link_feedback"
    irr:ratingUrl="@string/link_store">

    <LinearLayout
        android:id="@id/irr_nudge_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@id/irr_nudge_text"
            style="@style/Irr.Default.Text"
            android:text="Enjoying this app?"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@id/irr_nudge_decline_btn"
                style="@style/Irr.Default.Button"
                android:text="Not really"/>

            <Button
                android:id="@id/irr_nudge_accept_btn"
                style="@style/Irr.Default.Button.Accept"
                android:text="Yes!"/>
        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:id="@id/irr_rate_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@id/irr_rate_text"
            style="@style/Irr.Default.Text"
            android:text="How about a rating in the app store then?"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@id/irr_rate_decline_btn"
                style="@style/Irr.Default.Button"
                android:text="No, thanks"/>

            <Button
                android:id="@id/irr_rate_accept_btn"
                style="@style/Irr.Default.Button.Accept"
                android:text="Ok, sure."/>
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:id="@id/irr_feedback_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@id/irr_feedback_text"
            style="@style/Irr.Default.Text"
            android:text="Would you mind giving us some feedback?"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@id/irr_feedback_decline_btn"
                style="@style/Irr.Default.Button"
                android:text="No, thanks"/>

            <Button
                android:id="@id/irr_feedback_accept_btn"
                style="@style/Irr.Default.Button.Accept"
                android:text="Ok, sure."/>
        </LinearLayout>
    </LinearLayout>

</net.mediavrog.irr.IrrLayout>

Advanced usage

Auto-management in list views

Goal: Show IRRLayout in list views

IRR can handle the injection of the IRRLayout in any list adapter derived from BaseAdapter. Just pass your adapter decorated with IrrAdapterDecorator to your list view.

Example Inject IRRLayout at 10th position

ListView lv = (ListView) findViewById(android.R.id.list);
ArrayAdapter myAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);

// show the irr view at the 10th position (index starts at 0)
// optional: pass a custom rule engine as 5th parameter
decoratedAdapter = new IrrAdapterDecorator(this, myAdapter, 9, R.layout.standard_irr_layout);
lv.setAdapter(decoratedAdapter);

If you modify data for rule engine yourself, notify the adapter to refresh using decoratedAdapter.notifyRuleEngineStateChanged();

Custom action handler

Goal: Customize the behaviour for giving feedback or rating the app

Implement IrrLayout.OnUserActionListener and supply it to the IRRLayout irr.setOnUserActionListener(myOnUserActionListener).

If you only want to overwrite either action handling, extend DefaultOnUserActionListener instead.

Custom rule engine

Goal: Roll your own customized logic for showing the IRRLayout

  • First, set the IRRLayout attribute irr:useCustomRuleEngine to true. Note that all irr:defaultRule* attributes will not have any effect any more.
  • Create your own set of rules and feed them to a RuleEngine. Check the documentation of ruli for more details.
  • Finally, supply your rule engine to the IRRLayout.

Example Nudge user on weekends

// create weekend rule
RuleSet evenDayRule = new RuleSet.Builder()
        .addRule(new Rule() {
            @Override
            public boolean evaluate() {
                int dayOfWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
                return dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY;
            }

            @Override
            public String toString(boolean evaluate) {
                return "Is today Saturday or Sunday?" + (evaluate ? " => " + this.evaluate() : "");
            }
        }).build();

// .. put into a custom rule engine
ArrayList<Rule> rules = new ArrayList<>();
rules.add(evenDayRule);
engine = new RuleEngine(rules);

// evaluate the rule engine any time
engine.evaluate();

// supply to the IRRLayout
irr = (IrrLayout) findViewById(R.id.irr_layout);
irr.setRuleEngine(engine); // layout attr irr:useCustomRuleEngine must be set to true!

License

This project is licensed under the MIT License

About

A polite way to ask for ratings.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages