Okay I know I said the Getting Started series has been completely covered and concluded in the Performance Monitoring post.
“And that about sums it up for the ‘Getting Started With’ series. I’m preparing a whole variety of changes here at EricDecanini.com that you should be excited about.”
Of course, it’s me we’re talking about here. I’m DESTINED to forget something. And a pretty important one at that too!
Here in the Firebase ecosystem, we love our marketing and it should come as no question to any of us that word of mouth is the most powerful type of marketing of all. It is however, the hardest one to get going.
In comes Firebase Invites. To put it in a nutshell, you use them to share content in your app which you can send through email, Facebook messenger, or however you set it up.
So how does it work?
When you launch the Invites UI, the user can pick among his contacts to send a referral link (by SMS or Email). This link is a dynamic link, so it will open your app with the referral code if it’s installed, or take the user to Play Store if it isn’t. As you might know with dynamic links, the referral code will be retained after the installation process. You can then use this referral code to say, give your new users the discount they deserve, or the recipe they might want. (Cheeky examples from Firebase themselves).
Getting Started
implementation 'com.google.firebase:firebase-invites:16.0.5' implementation 'com.google.firebase:firebase-dynamic-links:16.1.3'
As with everything, we start with importing our Invites and Dynamic Links dependencies. You will also need to setup Firebase beforehand.
Sending Invites
It’s dead simple. It’s an intent… and that’s pretty much it. An intent with a callback… wait what? A callback?… More on that later.
private fun onInviteClicked() { val intent = AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title)) .setMessage(getString(R.string.invitation_message)) .setDeepLink(Uri.parse(getString(R.string.invitation_deep_link_kotlin))) .setCustomImage(Uri.parse(getString(R.string.invitation_custom_image))) .setCallToActionText(getString(R.string.invitation_cta)) .build() startActivityForResult(intent, REQUEST_INVITE) }
This intent will launch the pre-defined Firebase Invites UI which handles all the heavy lifting. All you need to do is set a few parameters to keep it personalised like the image and the CAT text.
Method | Channels | Description |
---|---|---|
setMessage |
Email & SMS | Sets the default message sent with invitations. This message can be edited by the sender in the invitation dialog. Cannot exceed 100 characters. |
setDeepLink |
Email & SMS | Sets the link into your app that is sent with invitations. Specify this to share specific content with the recipient or to otherwise present a custom experience when a user opens your app from an invitation. |
setCustomImage |
Sets the URL of a custom image to include in email invitations. The image must be square and around 600×600 pixels. The image can be no larger than 4000×4000 pixels. | |
setCallToActionText |
Sets the call-to-action text of the button rendered in email invitations. Cannot exceed 32 characters. | |
setEmailHtmlContent |
Recommended: Sets the content of an email invitation. Set this to send rich HTML email invitations. Your HTML should include the placeholder string %%APPINVITE_LINK_PLACEHOLDER%% , which is replaced with the URL the recipient opens to accept the invitation. When you specify custom email messages, the setDescription , setCustomImage , and setCallToActionText methods have no effect. |
|
setEmailSubject |
Required if setEmailHtmlContent is used. Sets the subject line of email invitations. |
In fact, here’s the list of parameters you can use to customise your app invite screen.
Callback?
Now why might there be a callback, you might ask?
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) Log.d(TAG, "onActivityResult: requestCode=$requestCode, resultCode=$resultCode") if (requestCode == REQUEST_INVITE) { if (resultCode == Activity.RESULT_OK) { // Get the invitation IDs of all sent messages val ids = AppInviteInvitation.getInvitationIds(resultCode, data!!) for (id in ids) { Log.d(TAG, "onActivityResult: sent invitation $id") } } else { // Sending failed or it was canceled, show failure message to the user // ... } } }
In all honesty, your invites process would work just fine without handling the callback, however there are a couple things to note:
Your app might want to save the Invitation IDs of the recipients sent to. On top of that, you would want to gracefully handle any errors in case things go wrong or the process was cancelled by the user.
Receiving Invites
override fun onCreate(savedInstanceState: Bundle?) { // ... // 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(intent) .addOnSuccessListener(this, OnSuccessListener { data -> if (data == null) { Log.d(TAG, "getInvitation: no data") return@OnSuccessListener } // Get the deep link val deepLink = data.link // Extract invite val invite = FirebaseAppInvite.getInvitation(data) val invitationId = invite.invitationId // Handle the deep link // ... }) .addOnFailureListener(this) { e -> Log.w(TAG, "getDynamicLink:onFailure", e) } }
You would receive an invite as if it were a dynamic link, but an extra special one. Because Firebase bestowed upon us the wonderful method of FirebaseAppInvite.getInvitation from which we can get the invitation ID. Now we can use this ID to confirm that both the sender and the receiver of the invite can receive some nice bonuses from your app.
Conclusion
To be honest, I really didn’t add much to this. I do go on about how Firebase documentations are a bit of a pain, but with Invites, it’s actually squeaky clean. Even their examples are exemplary. I didn’t think any examples of my own would’ve been much better.
In any case, I think I can say for real that this is the last of the Getting Started With series…. I think.