# Android v4 - Getting Started

> [!NOTE]
> **Note:** This guide describes the old implementation of Google Tag Manager in Android applications. New users should use [Tag Manager + Firebase](https://developers.google.com/tag-manager/android/v5) to implement Google Tag Manager in their Android applications.

## Introduction

Google Tag Manager enables developers to change configuration values in their mobile application
using the Google Tag Manager interface without having to rebuild and resubmit application binaries
to app marketplaces.

This is useful for managing any configuration values or flags in your application that you may need
to change in the future, including:

- Various UI settings and display strings
- Sizes, locations, or types of ads served in your application
- Various Game settings

Configuration values may also be evaluated at runtime using rules, enabling dynamic
configurations such as:

- Using screen size to determine ad banner size
- Using language and location to configure UI elements

Google TagManager also enables the dynamic implementation of tracking tags and pixels in
applications. Developers can push important events into a data layer and decide later which
tracking tags or pixels should be fired.

## Before you Begin

Complete the following steps before you begin this getting started guide:

- Install the [Android SDK](https://developer.android.com/sdk/index.html)
- Download the [Google Play Services SDK](https://developer.android.com/google/play-services/setup.html)
- Create a [Google Tag Manager account](https://www.google.com/tagmanager/)
- [Configure a Google Tag Manager container](https://support.google.com/tagmanager/answer/3127354)

Once you've completed these steps, the remainder of this guide will walk you through how to
configure and use Google Tag Manager within your Android application.

## Getting Started

After following this Getting Started guide, you'll understand how to:

- [Add Google Tag Manager to your project](https://developers.google.com/tag-platform/tag-manager/android/v4#add)
- [Initialize Tag Manager in your application](https://developers.google.com/tag-platform/tag-manager/android/v4#init)
- [Get configuration values from a Tag Manager container](https://developers.google.com/tag-platform/tag-manager/android/v4#get)
- [Push values and events into the `dataLayer`](https://developers.google.com/tag-platform/tag-manager/android/v4#push)
- [Preview, debug, and publish your container](https://developers.google.com/tag-platform/tag-manager/android/v4#preview-publish)

This guide uses code snippets from the `Cute Animals`
sample application included with the
[Google Play Services SDK](https://developer.android.com/google/play-services/index.html).
The complete source for this project is available in: `<android-sdk-directory>/extras/google/google_play_services/tagmanager/cuteanimals`.

## 1. Adding Google Tag Manager to your Project

To add Google Tag Manager to your project:

1. [Set Up the Google Play Services SDK](https://developer.android.com/google/play-services/setup.html#Install).
2. If you use an IDE other than [Android Studio](https://developer.android.com/sdk/index.html), add the following permissions to the `AndroidManifest.xml` file:

   ```
   <!-- For TagManager SDK -->
   <uses-permission android:name="android.permission.INTERNET" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
   ```
3. To enable [`InstallReferrerReceiver`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/InstallReferrerReceiver) to call the Google Analytics receiver to set the campaign data, add the following to the `AndroidManifest.xml` file:

   ```
   <!-- Used for install referrer tracking-->
   <service android:name="com.google.android.gms.tagmanager.InstallReferrerService" />
   <receiver
     android:name="com.google.android.gms.tagmanager.InstallReferrerReceiver"
     android:exported="true">
     <intent-filter>
       <action android:name="com.android.vending.INSTALL_REFERRER" />
     </intent-filter>
   </receiver>
   ```

## 2. Adding a Default Container File to your Project

> [!NOTE]
> **Note** : If you have not yet [configured your container in the Google Tag Manager web interface](https://support.google.com/tagmanager/answer/3127354), return to this step once you've done so.

Google Tag Manager uses a default container on the first run of your application. The default
container will cease to be used as soon as the app is able to retrieve a fresh container over the
network.

To download and add a default container binary to your application:

1. Sign in to the Google Tag Manager web interface.
2. Select the **Version** of the container you'd like to download.
3. Click the **Download** button to retrieve the container binary.
4. Add the downloaded container binary file to your project as a raw resource.
   1. If the `raw` subfolder under `<project-root>/res/` does not exist, create it.
   2. Rename the container binary file if necessary. It consists of only lowercase letters, digits, and underscores.
   3. Copy the container binary file to the folder `<project-root>/res/raw`.

Although using the binary file is recommended, if your container does not contain rules or tags,
you may choose to use a simple JSON file instead.

## 3. Initializing Google Tag Manager

To initialize Google Tag Manager in your application:

1. Get the [`TagManager`](https://developer.android.com/reference/com/google/android/gms/tagmanager/TagManager.html) singleton:

   ```
   TagManager tagManager = TagManager.getInstance(this);
   ```
2. Use the `TagManager` singleton to make a request to load a container, specifying a Google Tag Manager container ID as well as your [default container](https://developers.google.com/tag-platform/tag-manager/android/v4#default-container) file. The container ID should be uppercase and exactly match the container ID in the Google Tag Manager web interface. The call to `loadContainerPreferNonDefault()` is non-blocking and returns a [`PendingResult`](https://developer.android.com/reference/com/google/android/gms/common/api/PendingResult.html):

   ```
   PendingResult<ContainerHolder> pending =
           tagManager.loadContainerPreferNonDefault(CONTAINER_ID,
           R.raw.defaultcontainer_binary);
   ```
3. Use a [`ResultCallback`](https://developer.android.com/reference/com/google/android/gms/common/api/ResultCallback.html) to return the [`ContainerHolder`](https://developer.android.com/reference/com/google/android/gms/tagmanager/ContainerHolder.html) once it has finished loading or timed out:

   ```
   // The onResult method will be called as soon as one of the following happens:
   //     1. a saved container is loaded
   //     2. if there is no saved container, a network container is loaded
   //     3. the 2-second timeout occurs
   pending.setResultCallback(new ResultCallback<ContainerHolder>() {
       @Override
       public void onResult(ContainerHolder containerHolder) {
           ContainerHolderSingleton.setContainerHolder(containerHolder);
           Container container = containerHolder.getContainer();
           if (!containerHolder.getStatus().isSuccess()) {
               Log.e("CuteAnimals", "failure loading container");
               displayErrorToUser(R.string.load_error);
               return;
           }
           ContainerLoadedCallback.registerCallbacksForContainer(container);
           containerHolder.setContainerAvailableListener(new ContainerLoadedCallback());
           startMainActivity();
       }
   }, TIMEOUT_FOR_CONTAINER_OPEN_MILLISECONDS, TimeUnit.MILLISECONDS);
   ```

   > [!NOTE]
   > **Note** : By default, a container becomes eligible to be refreshed over the network every 12 hours. [Learn how to manually refresh a container](https://developers.google.com/tag-platform/tag-manager/android/v4#refresh).

   #### Creating a ContainerHolder Singleton

   You should only maintain one instance of `ContainerHolder` per run of your
   application. That is why the above example uses a `ContainerHolderSingleton` utility class
   to manage access to the `ContainerHolder` instance. Here is what that
   `ContainerHolderSingleton` class looks like:

   ```
   package com.google.android.tagmanager.examples.cuteanimals;

   import com.google.android.gms.tagmanager.ContainerHolder;

   /**
    * Singleton to hold the GTM Container (since it should be only created once
    * per run of the app).
    */
   public class ContainerHolderSingleton {
       private static ContainerHolder containerHolder;

       /**
        * Utility class; don't instantiate.
        */
       private ContainerHolderSingleton() {
       }

       public static ContainerHolder getContainerHolder() {
           return containerHolder;
       }

       public static void setContainerHolder(ContainerHolder c) {
           containerHolder = c;
       }
   }
   ```

#### See a Code Snippet from the Sample Application

The following snippet
shows the full pattern implemented in the `onCreate()` method of a sample `Activity`:

```
package com.google.android.tagmanager.examples.cuteanimals;

import java.util.concurrent.TimeUnit;
import java.util.Map;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.tagmanager.Container;
import com.google.android.gms.tagmanager.Container.FunctionCallMacroCallback;
import com.google.android.gms.tagmanager.Container.FunctionCallTagCallback;
import com.google.android.gms.tagmanager.ContainerHolder;
import com.google.android.gms.tagmanager.TagManager;

/**
 * Displays simple splash screen while GTM container is loading. Once the container is loaded,
 * launches the {@link MainActivity}.
 */
public class SplashScreenActivity extends Activity {
    private static final long TIMEOUT_FOR_CONTAINER_OPEN_MILLISECONDS = 2000;
    private static final String CONTAINER_ID = "GTM-XXXX";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splashscreen);

        TagManager tagManager = TagManager.getInstance(this);

        // Modify the log level of the logger to print out not only
        // warning and error messages, but also verbose, debug, info messages.
        tagManager.setVerboseLoggingEnabled(true);

        PendingResult<ContainerHolder> pending =
                tagManager.loadContainerPreferNonDefault(CONTAINER_ID,
                R.raw.defaultcontainer_binary);

        // The onResult method will be called as soon as one of the following happens:
        //     1. a saved container is loaded
        //     2. if there is no saved container, a network container is loaded
        //     3. the 2-second timeout occurs
        pending.setResultCallback(new ResultCallback<ContainerHolder>() {
            @Override
            public void onResult(ContainerHolder containerHolder) {
                ContainerHolderSingleton.setContainerHolder(containerHolder);
                Container container = containerHolder.getContainer();
                if (!containerHolder.getStatus().isSuccess()) {
                    Log.e("CuteAnimals", "failure loading container");
                    displayErrorToUser(R.string.load_error);
                    return;
                }
                ContainerLoadedCallback.registerCallbacksForContainer(container);
                containerHolder.setContainerAvailableListener(new ContainerLoadedCallback());
                startMainActivity();
            }
        }, TIMEOUT_FOR_CONTAINER_OPEN_MILLISECONDS, TimeUnit.MILLISECONDS);
  // Rest of the Activity definition.
}
```

## 4. Getting Configuration Values from the Container

Once the container is loaded, you can retrieve configuration values using any of the
`Container.get\<type\>()` methods. Configuration values are defined using
Google Tag Manager's value collection variables. For example, the following method
retrieves the latest color we've decided to use in for a UI element and returns it as
an integer:

```
/**
 * Returns an integer representing a color.
 */
private int getColor(String key) {
    return colorFromColorName(containerHolder.getContainer().getString(key));
}
```

This code does two things to retrieve the color name from the container:

1. Gets the `Container` from the `ContainerHolder` using [`ContainerHolder.getContainer()`](https://developer.android.com/reference/com/google/android/gms/tagmanager/ContainerHolder.html#getContainer()).
2. Gets the color value using [`Container.getString(key)`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/Container.html#getString(java.lang.String)), where you have defined the key and value in the Google Tag Manager web interface.

## 5. Pushing Events and Values to the dataLayer

Google Tag Manager also provides a `dataLayer`, into which you can push information
about your application that can be read in other parts of your application or used to fire tags
you've configured in the Google Tag Manager web interface.

### Pushing Values to the dataLayer

The `dataLayer` provides a layer of persistence that you can use
to store key-value pairs you might want to use in other parts of your application, or
as inputs to Google Tag Manager tags.

To push a value to the `dataLayer`, follow this pattern:

1. Get the [`DataLayer`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/DataLayer.html) singleton:

   ```
   DataLayer dataLayer = TagManager.getInstance(context).getDataLayer();
   ```
2. Push the event using [`DataLayer.push()`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/DataLayer.html#push(java.lang.String, java.lang.Object)):

   ```
   // Put the image_name into the data layer for future use.
   TagManager.getInstance(this).getDataLayer().push(IMAGE_NAME_KEY, imageName);
   ```

To get a value from the `dataLayer`, use
[`DataLayer.get(key)`](https://developer.android.com/reference/com/google/android/gms/tagmanager/DataLayer.html#get(java.lang.String)).

### Pushing Events to the dataLayer

Pushing events to the `dataLayer` allows you to separate your application code from
tags you might want to fire in response to those events.

For example, instead of hard-coding Google Analytics screenview tracking calls into your application,
you could push screen events onto the `dataLayer` and define your tracking tags via the
Google Tag Manager web interface. This gives you the flexibility to modify that tag, or add
additional tags that respond to screen events, without updating your application code.

To push an event to the `dataLayer`, follow this pattern:

1. Get the [`DataLayer`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/DataLayer.html) singleton:

   ```
   DataLayer dataLayer = TagManager.getInstance(context).getDataLayer();
   ```
2. Push the event using [`DataLayer.pushEvent()`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/DataLayer.html#pushEvent(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>)):

   ```
   dataLayer.pushEvent("openScreen", DataLayer.mapOf("screenName", screenName));
   ```


   [`DataLayer.mapOf()`](https://developers.google.com/android/reference/com/google/android/gms/tagmanager/DataLayer.html#mapOf(java.lang.Object...)) is a utility method you can use to easily generate a map of
   key-value pairs that will update the `dataLayer` at the same time the event is pushed.

#### See a Code Snippet from the Sample Application

The following utility class demonstrates how to push events, like information about screens
opening and closing in your app, on the `dataLayer`:

```
package com.google.android.tagmanager.examples.cuteanimals;

import android.content.Context;

import com.google.android.gms.tagmanager.DataLayer;
import com.google.android.gms.tagmanager.TagManager;

/**
 * Utility class.
 */
public class Utils {
    private Utils() {
        // private constructor.
    }

    /**
     * Push an "openScreen" event with the given screen name. Tags that match that event will fire.
     */
    public static void pushOpenScreenEvent(Context context, String screenName) {
        DataLayer dataLayer = TagManager.getInstance(context).getDataLayer();
        dataLayer.pushEvent("openScreen", DataLayer.mapOf("screenName", screenName));
    }

    /**
     * Push a "closeScreen" event with the given screen name. Tags that match that event will fire.
     */
    public static void pushCloseScreenEvent(Context context, String screenName) {
        DataLayer dataLayer = TagManager.getInstance(context).getDataLayer();
        dataLayer.pushEvent("closeScreen", DataLayer.mapOf("screenName", screenName));
    }
}
```

## 6. Previewing, Debugging, and Publishing

Before publishing a version of your container, you'll want to preview it to make sure it works
as intended. Google Tag Manager gives you the ability to preview versions of your container
by generating links and QR codes in the web interface and using them to open your application.
You can also enable a verbose logging mode to debug any unexpected behavior.

### Previewing

To preview a version of your container, follow these steps:

1. Adding this preview `Activity` to your `AndroidManifest` file:

   ```
   <!--  Add preview activity. -->
   <activity
       android:name="com.google.android.gms.tagmanager.PreviewActivity"
       android:label="@string/app_name"
       android:noHistory="true">  <!-- optional, removes the previewActivity from the activity stack. -->
       <intent-filter>
         <data android:scheme="tagmanager.c.com.google.android.tagmanager.examples.cuteanimals" />
         <action android:name="android.intent.action.VIEW" />
         <category android:name="android.intent.category.DEFAULT" />
         <category android:name="android.intent.category.BROWSABLE"/>
       </intent-filter>
   </activity>
   ```

   Be sure to modify this line to include your application's package name:

   ```
   <data android:scheme="tagmanager.c.com.google.android.tagmanager.examples.cuteanimals" />
   ```
2. Generate a preview link in the Google Tag Manager web interface
   1. Sign in to Google Tag Manager
   2. Select the container **Version** to preview
   3. Click the **Preview** button
   4. Enter your application's package name and click **Generate begin preview link**
3. Use the generated link or QR Code to launch your application
4. You can exit preview mode by following a link generated by the **Generate end preview link** option in the web interface.

### Debugging

If you need to troubleshoot your container implementation, enable verbose logging by calling
[`TagManager.setVerboseLoggingEnabled(true)`](https://developer.android.com/reference/com/google/android/gms/tagmanager/TagManager.html#setVerboseLoggingEnabled(boolean)):

```
// Modify the log level of the logger to print out not only
// warning and error messages, but also verbose, debug, info messages.
tagManager.setVerboseLoggingEnabled(true);
```

### Publishing

After you've previewed your container and verified it's working as intended, you can
[publish your container](https://support.google.com/tagmanager/answer/3127354). Your
container configuration values, tags, and events will be live for users the next time their
containers are refreshed. [Learn more about refreshing containers](https://developers.google.com/tag-platform/tag-manager/android/v4#refresh).

## Advanced Configuration

The following sections describe advanced configuration options you want to use to further customize your
Google Tag Manager implementation.

### Refreshing the Container

By default, your container becomes eligible to be refreshed every 12 hours. To manually refresh
the container, use [`ContainerHolder.refresh()`](https://developer.android.com/reference/com/google/android/gms/tagmanager/ContainerHolder.html#refresh()):

```
ContainerHolderSingleton.getContainerHolder().refresh();
```

This is an asynchronous call that will not return immediately. To reduce network traffic, `refresh()` may
only be called once every 15 minutes, otherwise it will be a no-op.

> [!NOTE]
> **Note** : This snippet uses the [`ContainerHolderSingleton` utility class](https://developers.google.com/tag-platform/tag-manager/android/v4#container-singleton) described in the initialization example above.

#### See a Code Snippet from the Sample Application

```
public void refreshButtonClicked(@SuppressWarnings("unused") View view) {
    Log.i(TAG, "refreshButtonClicked");
    ContainerHolderSingleton.getContainerHolder().refresh();

    // Push the "refresh" event to trigger firing an analytics tag.
    TagManager.getInstance(this).getDataLayer().push("event", "refresh");
    // Push the "custom tag" event to trigger firing a custom function call tag.
    TagManager.getInstance(this).getDataLayer().push("event", "custom_tag");
    updateCategories();
}
```