androidgoogle-playgoogle-play-servicesinstall-referrer

How to test install referrer with Google's installreferrer library?


There are lots of examples how to test "default" way of detecting install referrer, but there is not example how to test com.android.installreferrer:installreferrer library.

Examples like

adb shell am broadcast -a com.android.vending.INSTALL_REFERRER 
                       -n your.package.name/path.to.receiver --es referrer
                       --es referrer "EXTRA_STRING_VALUE"

do not work because we don't know receiver path. So how to test it?


Solution

  • With the InstallReferrerClient, there doesn't seem to be any BroadcastReceiver registered in the AndroidManifest.xml. The library just binds to the system's install referrer service ...

    private static final String SERVICE_PACKAGE_NAME = "com.android.vending";
    private static final String SERVICE_NAME = "com.google.android.finsky.externalreferrer.GetInstallReferrerService";
    private static final String SERVICE_ACTION_NAME = "com.google.android.finsky.BIND_GET_INSTALL_REFERRER_SERVICE";
    

    The client receives referrer utm_source=google-play&utm_medium=organic upon manual install. There is no BroadcastReceiver exposed (but the InstallReferrerService should have one).

    The keys of the raw Intent Bundle are: install_referrer, referrer_click_timestamp_seconds and install_begin_timestamp_seconds if you want to try emulating it - but the onInstallReferrerSetupFinished() callback will deliver the result indirectly.

    The documentation also states:

    The install referrer information will be available for 90 days and won't change unless the application is reinstalled. To avoid unnecessary API calls in your app, you should invoke the API only once during the first execution after install. Your app can listen to the system broadcast Intent.ACTION_PACKAGE_FIRST_LAUNCH to identify the app's first execution.


    So this should be an intent-filter for action Intent.ACTION_PACKAGE_FIRST_LAUNCH, which subsequently connects the InstallReferrerClient to the InstallReferrerService. One cannot trigger Intent.ACTION_PACKAGE_FIRST_LAUNCH with adb, because it filters for a "protected broadcast action string", therefore it might only be triggered when installing from Play Store.

    The implementation, according to the documentation, might look alike:

    AndroidManifest.xml:

    <receiver
        android:name=".receiver.PackageStatusReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_FIRST_LAUNCH"/>
        </intent-filter>
    </receiver>
    

    PackageStatusReceiver.java:

    public class PackageStatusReceiver extends BroadcastReceiver implements InstallReferrerStateListener {
    
        protected static final String LOG_TAG = PackageStatusReceiver.class.getSimpleName();
    
        private InstallReferrerClient referrerClient;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction() != null) {
                if(intent.getAction().equals(Intent.ACTION_PACKAGE_FIRST_LAUNCH)) {
                    this.referrerClient = InstallReferrerClient.newBuilder(context).build();
                    this.referrerClient.startConnection(this);
                }
            }
        }
    
        @Override
        public void onInstallReferrerSetupFinished(int responseCode) {
            switch (responseCode) {
                case InstallReferrerClient.InstallReferrerResponse.OK:
                    Log.d(LOG_TAG, "InstallReferrer Response.OK");
                    try {
                        ReferrerDetails response = referrerClient.getInstallReferrer();
                        String referrer = response.getInstallReferrer();
                        long clickTimestamp = response.getReferrerClickTimestampSeconds();
                        long installTimestamp = response.getInstallBeginTimestampSeconds();
                        Log.d(LOG_TAG, "InstallReferrer " + referrer);
                        referrerClient.endConnection();
                    } catch (RemoteException e) {
                        Log.e(LOG_TAG, "" + e.getMessage());
                    }
                    break;
                case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
                    Log.w(LOG_TAG, "InstallReferrer Response.FEATURE_NOT_SUPPORTED");
                    break;
                case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
                    Log.w(LOG_TAG, "InstallReferrer Response.SERVICE_UNAVAILABLE");
                    break;
                case InstallReferrerClient.InstallReferrerResponse.SERVICE_DISCONNECTED:
                    Log.w(LOG_TAG, "InstallReferrer Response.SERVICE_DISCONNECTED");
                    break;
                case InstallReferrerClient.InstallReferrerResponse.DEVELOPER_ERROR:
                    Log.w(LOG_TAG, "InstallReferrer Response.DEVELOPER_ERROR");
                    break;
            }
        }
    
        @Override
        public void onInstallReferrerServiceDisconnected() {
            Log.w(LOG_TAG, "InstallReferrer onInstallReferrerServiceDisconnected()");
        }
    }
    

    To test this, you'd need referrer links to the Play Store and then install the package through them... else only the default referrer will be logged (besides the intent cannot even be triggered, when properly implementing the client).