Creating, Receiving and Testing a Firebase Dynamic Link

From Techotopia
Revision as of 15:13, 29 August 2017 by Neil (Talk | contribs)

Jump to: navigation, search

This chapter will provide a practical example of Dynamic Links in the context of an Android app. The topics that will be covered in this chapter include the creation of dynamic links using both the Firebase console and within the app together with both approaches to handling a link within the app. Finally, the chapter will explore some of the ways in which dynamic links can be tested without the app being published in the Google Play store.


Contents


About the Dynamic Links Example App

The example project created in this chapter is intentionally simple. The only features the app will include are the ability to generate and share a dynamic link and to implement custom behavior as a result of being launched by a dynamic link click.

Creating the Dynamic Links Project

Begin by starting Android Studio and selecting the Start a new Android Studio project quick start option from the welcome screen.

Within the new project dialog, enter DynamicLinks into the Application name field and your domain as the Company Domain setting before clicking on the Next button. On the form factors screen, enable the Phone and Tablet option and set the minimum SDK to API 16: Android 4.1 (Jellybean). Continue to proceed through the screens, requesting the creation of an Empty Activity named DynamicLinksActivity with a corresponding layout named activity_dynamic_links.


Designing the User Interface

The user interface for the main activity will consist of two Button objects in addition to the default “Hello World” TextView. Within Android Studio open the activity_dynamic_links.xml file in the layout editor and use the toolbar buttons to remove all constraints from the layout and to disable the Autoconnect feature.

Move the default TextView object so that it is positioned nearer to the top of the layout before dragging and dropping two Button objects from the palette onto the layout canvas so that they are centered beneath the TextView. Set the text property on the buttons to read Get Link and Share as shown in Figure 46‑1:


Dynamic links example ui.png

Figure 46‑1


Select all three widgets in the layout, then right-click on the TextView widget. From the resulting menu, select the Center Horizontally option. With all three widgets still selected, repeat this step and choose the Center Vertically menu option to constrain the widgets using a chain.

Before proceeding to the next step, assign onClick methods named getLink and shareLink to the buttons. Also, change the IDs on the TextView and Share button to statusText and shareButton respectively.

Connecting the Project to Firebase

Connect the project to Firebase by selecting the Tools -> Firebase menu option and unfolding the Dynamic Links section within the Firebase assistant panel. Click on the Add a dynamic link option and use the buttons on the Dynamic Links page to connect the app to the Firebase Examples project and to add the project dependencies.

Performing Basic Initialization

Before starting work on generating dynamic links, some basic initialization tasks need to be performed. Within Android Studio, edit the DynamicLinksActivity.java file as follows:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

public class DynamicLinksActivity extends AppCompatActivity {

    private TextView statusText;
    private Button shareButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dynamic_links);

        statusText = (TextView) findViewById(R.id.statusText);
        shareButton = (Button) findViewById(R.id.shareButton);

        shareButton.setEnabled(false);
    }
.
.
}

Adding the Link Generation Code

The app needs to generate a dynamic link when the user taps the Get Link button. Before adding the method, use the steps outlined in the previous chapter to find the app code for your Firebase project.

Within the DynamicLinksActivity.java file, add the getLink() method so that it reads as follows (where <app_code> is replaced by your app code):

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.net.Uri;
import android.util.Log;
import android.view.View;

public class DynamicLinksActivity extends AppCompatActivity {

    private Uri dynamicLink = null;
    private static final String TAG = "DynamicLinks";
.
.
.
    public void getLink(View view) {
        String appCode = "<app_code>";
        final Uri deepLink = Uri.parse("http://example.com/promo?discount");

        String packageName = getApplicationContext().getPackageName();

        // Build the link with all required parameters
        Uri.Builder builder = new Uri.Builder()
                .scheme("https")
                .authority(appCode + ".app.goo.gl")
                .path("/")
                .appendQueryParameter("link", deepLink.toString())
                .appendQueryParameter("apn", packageName);

        dynamicLink = builder.build();
        shareButton.setEnabled(true);
    }
.
.
}

The code builds a dynamic link containing a deep link URL of http://www.example.com/promo with a query value of discount. Once the link has been generated, it is assigned to a variable named dynamicLink and the Share button is enabled.

Sharing the Dynamic Link

Now that a dynamic link has been generated the code for the shareLink() method can be added to the project so that users can share links. This will be achieved using the standard Android ACTION_SEND intent. Remaining within the DynamicLinksActivity.java file, add the shareLink() method:

.
.
.
import android.content.Intent;

import java.net.URL;
import java.net.URLDecoder;

public class DynamicLinksActivity extends AppCompatActivity {
.
.
.
    public void shareLink(View view) {
        try {
            URL url = new URL(URLDecoder.decode(dynamicLink.toString(), 
							"UTF-8"));
            Log.i(TAG, "URL = " + url.toString());
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_SUBJECT, "Firebase Deep Link");
            intent.putExtra(Intent.EXTRA_TEXT, url.toString());
            startActivity(intent);
        } catch (Exception e) {
            Log.i(TAG, "Could not decode Uri: " + e.getLocalizedMessage());
        }
    }
.
.
}

Run the app (for a greater range of sharing options a physical device is recommended) and tap the Get Link button. When the Share button enables, click on it and select a way to send the link to someone else (or even to yourself for testing purposes). Within the body of the message, the dynamic link should have already been inserted and should resemble the following URL:

https://<app_code>.app.goo.gl/?link=http://example.com&apn=com.ebookfrenzy.dynamiclinks

Adding the Main Activity Intent Filter

The next task is to add the intent filter for the main activity within the app project. This filter will ensure that the main activity is launched when a dynamic link with an example.com deep link is received by the system. Edit the AndroidManifest.xml file and modify the DynamicLinksActivity entry to add this additional intent filter:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ebookfrenzy.dynamiclink_work">

    <application
.
.
.
        <activity android:name=".DynamicLinkActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="example.com"
                    android:scheme="http" />
                <data
                    android:host="example.com"
                    android:scheme="https" />
            </intent-filter>
        </activity>
.
.
</application>

Detecting a Dynamic Link Launch

With the intent filter configured, code now needs to be added to detect when the app has been launched as the result of a dynamic link. Edit the DynamicLinkActivity.java file and add some import directives. The class will also need to be declared as implementing the OnConnectionFailedListener interface of the GoogleApiClient. A variable will also be needed in which to store a reference to the GoogleApiClient instance:

.
.
.
import android.widget.Toast;
import android.support.annotation.NonNull;

import com.google.android.gms.appinvite.AppInvite;
import com.google.android.gms.appinvite.AppInviteInvitationResult;
import com.google.android.gms.appinvite.AppInviteReferral;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;

public class DynamicLinksActivity extends AppCompatActivity implements 
		GoogleApiClient.OnConnectionFailedListener {
.
.
    private GoogleApiClient googleApiClient;
.
.

The OnConnectionFailedListener interface requires that the OnConnectionFailed method be overridden within the class so add this method now:

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.w(TAG, "onConnectionFailed:" + connectionResult);
    Toast.makeText(this, "Google Play Services Error: " 
			+ connectionResult.getErrorCode(),
            Toast.LENGTH_SHORT).show();
}

Finally, modify the onCreate() method to handle a dynamic link app launch:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_dynamic_links);

    statusText = (TextView) findViewById(R.id.statusText);
    shareButton = (Button) findViewById(R.id.shareButton);
    shareButton.setEnabled(false);

    googleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, this)
            .addApi(AppInvite.API)
            .build();

    boolean launchDeepLink = false;

    AppInvite.AppInviteApi.getInvitation(googleApiClient, this, 
		launchDeepLink).setResultCallback(

                    new ResultCallback<AppInviteInvitationResult>() {
                        @Override
                        public void onResult(
			   @NonNull AppInviteInvitationResult result) {

                            if (result.getStatus().isSuccess()) {

                                Intent intent = result.getInvitationIntent();
                                String deepLink = 
				   AppInviteReferral.getDeepLink(intent);

                                handleDeeplink(deepLink);
                            } else {
                                Log.i(TAG, "Deeplink not found");
                            }
                        }
                    });
}

Note that in the event that a dynamic link is detected, the deep link URL is extracted from the intent and passed through to a method named handleDeepLink() for handling. This method now needs to be added to the class.

Parsing the Deep Link URL

Now that we have a deep link, the app needs to decide what to do with it. Typically, an app will take different actions depending on the content of the deep link URL. In this case, the app dynamic link is being used as part of a promotional email sent to existing users to encourage them to use the app. When the user clicks on the dynamic link the app will load and credit the user’s account with extra points.

The code within the handleDeepLink() method will need to check for a /credit path within the deep link URL together with a query parameter representing the number of points to be credited. If a match is found, a message will be displayed within the TextView object confirming that the points have been applied to the user’s account:

public void handleDeeplink(String deepLink) {

    Uri deepUri = Uri.parse(deepLink);

    if (deepUri.getPath().equals("/credit")) {
        statusText.setText(deepUri.getQuery() + 
			" points have been applied to your account");
    }
}

Although for the sake of simplicity such steps are not being taken in this example, code should be added in a real world situation to record that the user has claimed the offer to ensure that the user cannot use the link more than once.

Generating the Dynamic Link

The dynamic link to test the app will be generated using the Firebase console. Open the Firebase console in a browser window, select the Firebase Examples project and click on the Dynamic Links option. Within the Dynamic Links screen, click on the New Dynamic Link button and configure the link as follows:

• Deep link URL – http://www.example.com/credit?200

• Dynamic Link name – Bonus points email promotion

• iOS behavior – Open the deep link URL in a browser

• Android behavior – Open the deep link in your Android app (select the app from the menu).

• UTM parameters – None

• Social media tags – None

Once the link has been configured, click on the Create Dynamic Link button to generate the link. After the link has been generated, hover the mouse pointer over the link row, click on the menu dots when they appear and select Link details from the menu.

When using dynamic links in scenarios such as this it is important to use the short form of the URL. In this example, the user could easily reverse engineer the long form URL to increase the number of bonus points awarded.

Copy the short dynamic link to the clipboard before moving to the next step.

Testing a Dynamic Link

There are a few different ways to test that a dynamic link is working. The simplest way is to edit the run configuration of the app within Android Studio to launch the app using the dynamic link URL.

To modify the run configuration, click on the app entry in the Android Studio toolbar and select the Edit Configurations… menu option:


Dynamic links edit config.png

Figure 46‑2


When the Run/Debug Configurations dialog appears, locate the Launch Options section of the General screen and change the Launch menu from Default Activity to URL:


Dynamic links launch options.png

Figure 46‑3


Paste the dynamic link into the URL: text field before clicking on the Apply button followed by the OK button to commit the change and close the dialog.

When the app is run using the new configuration the deep link should be detected and the text view updated within the main activity to show that the points have been credited to the user’s account.

Another option is to use the adb command-line tool together with the Chrome browser running on the device or emulator on which the test app is installed. On the device or emulator, open the Chrome browser and enter the shortened dynamic link into the search bar and attempt to load the URL. After a short delay, the DynamicLinks app should launch and display the message indicating that bonus points have been earned.

Typing the URL into the browser can be time consuming and prone to error (particularly when using a long form URL). A useful trick to avoid having to type the URL is to use the adb tool. On the device or emulator, open Chrome once again and select the search bar so that the keyboard appears ready to receive input and remove any previous URL within the search field. Open a command-prompt or terminal window on the development system and run the following command where <dynamic url here> is replaced by the dynamic link URL copied from the Firebase console:

adb shell input text "<dynamic url here>"

When the command is executed, the text will appear within the Chrome search bar. Tapping the search button on the virtual keyboard will then load the URL and launch the app.

Adding a Second Activity

The final step of this tutorial is to add a second activity to the app which will be launched automatically in response to a dynamic link click. This second activity is intended to display a welcome message to users after they have installed the app for the first time.

Within the Android Studio Project tool window, right click on the package name (app -> java -> <your domain>.dynamiclinks) and select the New -> Activity -> Empty Activity menu option. In the New Android Activity dialog, name the activity WelcomeActivity, verify that the Generate Layout File and Backwards Compatibility options are enabled, and that Launcher Activity is disabled before clicking on the Finish button.

Load the activity_welcome.xml file into the layout editor, position a TextView widget in the center of the layout and use the Infer constraints button in the layout editor toolbar to constrain the widget appropriately. Using the Properties tool window, change the text on the view to “Thank you for installing our app”:


Dynamic links landing ui.png

Figure 46‑4

Configuring Automatic Activity Launching

The goal for the Welcome Activity is to have it launch automatically when a dynamic link containing the following deep link URL is clicked:

http://www.example.com/welcome

This involves the addition of an intent filter to the manifest entry for the activity. Edit the AndroidManifest.xml file, locate the WelcomeActivity entry and modify it to read as follows:

<activity android:name=".WelcomeActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="http"
            android:host="www.example.com"
            android:pathPrefix="/welcome" />
    </intent-filter>
</activity>

Next, edit the DynamicLinksActivity.java file and change the code to assign a true value to the launchDeepLink variable:

boolean launchDeepLink = true;

Compile and run the app so that the latest version is installed ready for testing.

Testing Automatic Launching

Return to the Firebase console and generate a new dynamic link containing a deep link URL of http://www.example.com/welcome configured to launch the DynamicLinks Android app.

Edit the run configuration for the app once more within Android Studio and paste the dynamic link URL into the settings dialog before clicking on the Apply and Ok buttons.

When the app is run the Welcome activity should appear instead of the main activity.

As a final test, attempt to launch the app with the original bonus credit dynamic URL and verify that the dynamic link works as before with the main activity launching and the TextView displaying the credited points.

Dynamic Link Analytics

Although basic statistics relating to dynamic link clicks are available within the Dynamic Links screen of the Firebase console, a greater level of detail is provided within Firebase Analytics. In fact, dynamic link clicks are one of the event types captured automatically by Firebase Analytics.

To view dynamic link analytics, select the Analytics screen within the Firebase console followed by the Events tab and, using the app selection menu at the top of the page, select the DynamicLinks app. In the event table, dynamic link events will be listed on the dynamic_link_app_open line:


Dynamic links analytics.png

Figure 46‑5


To view dynamic link stats in greater detail, select the event to display the graphs, charts and demographic data.

Event parameters are also available to gather additional information about dynamic link clicks. To configure event parameters display the menu for the event as shown in Figure 46‑6 and select the Edit parameter reporting menu option:


Dynamic links edit param reporting.png

Figure 46‑6


In the parameter configuration dialog, select the parameters to be added to the event. In Figure 46‑7, the accept time and link ID parameters have been selected for inclusion in the dynamic links analytics data:


Dynamic links param reporting.png

Figure 46‑7


Each added event parameter will be represented by a graph within the detail event view.

Summary

This chapter provided a practical example of creating and handling Dynamic Links. The topics covered included the creation of dynamic links using both the Firebase console and within an Android app together with both manual and auto loading approaches to handling a link within the app. The chapter also outlined ways to test dynamic links before an app is published in the Google Play store.