How To Add Firebase AppInvite To Android

August 12, 2017

Follow instruction from How To Add Firebase To Android to complete Connect your app to Firebase.

Send Firebase Invites

Add Firebase AppInvite

Click Add Firebase Invites to your app.

Firebase Add Invites

I avoid clicking Accept Changes as it will reformat my project’s build.gradle config file. I prefer to add the following entry manually.

Edit project’s build.gradle.

...

dependencies {
  ...
  compile 'com.google.firebase:firebase-invites:11.0.2'
  // if the following is used previously, it is no longer necessary
  // compile 'com.google.android.gms:play-services-appinvite:x.x.x
}

apply plugin: 'com.google.gms.google-services'

Edit root level build.gradle.

buildscript {
  ...
  dependencies {
    ...
    classpath 'com.google.gms:google-services:3.1.0'
  }
}

Add the following declaration at activity or fragment.

private static final int REQUEST_INVITE = 1;

Add the following code to the action (e.g. button click) to trigger the invite action. If you want to support iOS version of your app as well, refer to the official documentation.

/*
Trigger invite action
url = "https://www.mydomain.com/_invites/resourceId" 
 - '/_invites/' to indicate this is a invite request
 - 'resourceId' to indicate which resource to retrieve and display to user
 */
Intent intent = new AppInviteInvitation.IntentBuilder(title)
        .setMessage(message)
        .setDeepLink(Uri.parse(url))
        .setCustomImage(Uri.parse(imageUrl))
        .setCallToActionText(action)
        .build();
startActivityForResult(intent, REQUEST_INVITE);

The above intent will open contact chooser for user to select contacts to invite (email or SMS). After the intent is completed, you will received a callback.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_INVITE) {
        if (resultCode == RESULT_OK) {
            // Get the invitation IDs of all sent messages
            String[] ids = AppInviteInvitation.getInvitationIds(resultCode, data);
            for (String id : ids) {
                Log.d(TAG, "onActivityResult: sent invitation " + id);
            }

            Toast.makeText(context, ids.length + " Invites sent", Toast.LENGTH_LONG).show();
        } else {
            // Sending failed or it was canceled, show failure message to the user
            Toast.makeText(context, "Cancel", Toast.LENGTH_LONG).show();
        }
    }
}

The follow code should be put at the main activity to receive invites. When user click on an invite link (email or SMS), it shall trigger the following code (if user has yet to install the app, it will trigger the installation process through Google Play Store then trigger the receive invites code below).

// Check for App Invite invitations and launch deep-link activity if possible.
// Requires that an Activity is registered in AndroidManifest.xml to handle
// deep-link URLs.
FirebaseDynamicLinks.getInstance().getDynamicLink(activityRef.get().getIntent())
    .addOnSuccessListener(getActivity(), new OnSuccessListener<PendingDynamicLinkData>() {
        @Override
        public void onSuccess(PendingDynamicLinkData data) {
            if (data == null) {
                Log.d(TAG, "getInvitation: no data");
                return;
            }

            // Get the deep link
            Uri deepLink = data.getLink();

            // Extract invite
            FirebaseAppInvite invite = FirebaseAppInvite.getInvitation(data);
            if (invite != null) {
                String invitationId = invite.getInvitationId();
            }

            Log.d(TAG, "deepLink:" + deepLink);
            if (deepLink != null) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setPackage(activityRef.get().getPackageName());
                intent.setData(deepLink);

                startActivity(intent);
            }
        }
    })
    .addOnFailureListener(getActivity(), new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Log.w(TAG, "getDynamicLink:onFailure", e);
        }
    });

Note: Though The code above requires a connected GoogleApiClient with AppInvite.API enabled is mentioned in the official documentation, but such requirement is deprecated since v11.

Create an OpenInviteActivity to handle loading of the invite content.

@Override
public void onStart() {
    super.onStart();

    if (getIntent() != null && getIntent().getData() != null) {
        Uri data = getIntent().getData();
        processReferralIntent(data);
    }
}

private void processReferralIntent(Uri uri) {
    Log.d(TAG, "invite:processReferralIntent");

    Log.d(TAG, "invite:deepLink="+uri.toString());

    // uri.getPath() = /_invites/resourceId
    String urlName = uri.getPath();
    // not sure if first "/" is provided, handle properly just in case
    if (urlName.startsWith("/")) {
        urlName = urlName.substring(1);
    }
    if (urlName.startsWith("_invite/")){
        String resourceId = urlName.replaceFirst("_invite/", "");

        Log.d(TAG, "invite:deepLink.resourceId="+resourceId);
        // use resourceId to load the relevant information, such as retrieve info from database or API
    }
}

Edit AndroidManifest.xml. OpenInviteActivity is the actual activity which handle the invite request and display the relevant info.

<manifest ...>
    ...
    <application ...>
        ...
        <activity
            android:name=".OpenInviteActivity"
            ...>

            <!-- [START deep_link_filter] -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Relevant to the AppInviteInvitation.IntentBuilder -->
                <data
                    android:host="www.mydomain.com"
                    android:pathPrefix="/_invite/"
                    android:scheme="http" />
                <data
                    android:host="www.mydomain.com"
                    android:pathPrefix="/_invite/"
                    android:scheme="https" />
            </intent-filter>
            <!-- [END deep_link_filter] -->
        </activity>
    </application> 
</manifest>       

References

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.