# Using the DataTrack API - Android

In this guide, we will show you how to use the DataTrack API to send messages between Participants connected to a Room. With the DataTrack API you will be able to build powerful collaboration features such as whiteboarding, screen annotations, shared augmented reality apps and more. Use this guide along with our example app [Android DataTrack Example](https://github.com/twilio/video-quickstart-android/tree/master/exampleDataTrack) to learn about the DataTrack API.

* [Overview](#overview)
* [Using the DataTrack API](#using-the-datatrack-api)
* [Configuring DataTrack reliability](#configuring-datatrack-reliability)

## Overview

The DataTrack API lets you create a DataTrack channel which can be used to send low latency messages to zero or more receivers subscribed to the data. DataTracks have the following properties.

* DataTracks are `unidirectional`.
  * [LocalDataTrack](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/LocalDataTrack.html) is used to send messages to a room.
  * Implement [RemoteDataTrack.Listener](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/RemoteDataTrack.Listener.html) to receive messages.
* DataTracks have built-in mechanisms to `support reliable transmission`. Check out the section on [Configuring DataTrack reliability](#configuring-datatrack-reliability).
* Recommended maximum payload size of data sent over the DataTrack is `16KiB`.
* `string` or `byte` data can be sent over the DataTrack.

In the next section we will show you how to use the DataTrack API with the Android SDK.

## Using the DataTrack API

### Create a LocalDataTrack

The [LocalDataTrack](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/LocalDataTrack.html) is a Track that represents data that can be published to a Room by the [LocalParticipant](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/LocalParticipant.html)

```bash
LocalDataTrack localDataTrack = LocalDataTrack.create(context);
```

### Connect to a Room with a LocalDataTrack

Next, we want to connect to a Room with the `LocalDataTrack` we created earlier

```bash
ConnectOptions connectOptions = new ConnectOptions.Builder(token)
    .dataTracks(Collections.singletonList(localDataTrack))
    .build();
Video.connect(context, connectOptions, roomListener);
```

### Publish the LocalDataTrack

After connecting to the Room, we now want to publish our `LocalDataTrack` to it.

```bash
LocalParticipant localParticipant = room.getLocalParticipant();
localParticipant.publish(localDataTrack);
```

### Send messages over the LocalDataTrack

The DataTrack API supports sending `string` as well as `byte` data.
You can use one of the two variants of [send](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/LocalDataTrack.html) to send a `string` or `byte` to the Room. DataTracks behave similarly to audio and video Tracks in the sense that, Participants will only receive data that was sent after:

* The [LocalDataTrack](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/LocalDataTrack.html) was successfully published to the Room, and
* The Participant subscribed to the DataTrack.

For example, if Alice starts sending a stream of consecutive natural numbers (one number per second), and Bob joins the Room and subscribes to Alice's DataTrack after 5 seconds while Charlie joins the Room and subscribes to Alice's DataTrack after 10 seconds, then Bob will receive all the numbers starting from 6, and Charlie will receive all the numbers starting from 11.

```bash
public class MyClass implements LocalParticipant.Listener {

    // NOTE: Other LocalParticipant.Listener methods not implemented for brevity

    @Override
    public void onDataTrackPublished(@NonNull LocalParticipant localParticipant, @NonNull LocalDataTrackPublication localDataTrackPublication) {

        // The data track has been published and is ready for use
        string message = "hello DataTrack!"
        localDataTrackPublication.getLocalDataTrack().send(message);

        ByteBuffer messageBuffer = ByteBuffer.wrap(new byte[]{ 0xf, 0xe });
        localDataTrackPublication.getLocalDataTrack().send(messageBuffer);
    }
}
```

### Listening for DataTrack events

The [RemoteParticipant](https://sdk.twilio.com/android/video/releases/7.9.1/docs/com/twilio/video/RemoteParticipant.html) class provides a listener interface. You can implement this interface to listen to published and unpublished DataTrack events.

```bash
RemoteParticipant.Listener participantListener = new RemoteParticipant.Listener() {

    // Participant has published data track
    @Override public void onDataTrackPublished(RemoteParticipant
            remoteParticipant, RemoteDataTrackPublication
            remoteDataTrackPublication) {}

    // Participant has unpublished data track
    @Override public void onDataTrackUnpublished(RemoteParticipant
            remoteParticipant, RemoteDataTrackPublication
            remoteDataTrackPublication) {}

    // Data track has been subscribed to and messages can be observed.
    @Override public void onDataTrackSubscribed(RemoteParticipant
            remoteParticipant, RemoteDataTrackPublication
            remoteDataTrackPublication,RemoteDataTrack remoteDataTrack) {}

    // Data track has been unsubsubscribed from and messages cannot be
    // observed.
    @Override public void onDataTrackUnsubscribed(RemoteParticipant
            remoteParticipant, RemoteDataTrackPublication
            remoteDataTrackPublication, RemoteDataTrack remoteDataTrack) {}
};
```

### Receiving messages from the DataTrack

```bash
RemoteDataTrack.Listener dataTrackListener = new RemoteDataTrack.Listener() {

    @Override
    public void onMessage(String message) {
        // Should print "Hello DataTrack!"
        Log.d(TAG, String.format("Received data track message: %s",
        message));
        }
    }

    @Override
    public void onMessage(ByteBuffer message) {
        Log.d(TAG, "Received message buffer on data track!");
    }
};
remoteDataTrack.setListener(dataTrackListener);
```

Take a look at the [Android Quickstart Application](https://github.com/twilio/video-quickstart-android/tree/master/exampleDataTrack) to learn more.

## Configuring DataTrack reliability

DataTracks are intended for low-latency communication between Participants. Importantly, to optimize for lowest latency possible, *delivery of DataTrack messages is not guaranteed*. You can think of them more like UDP messages, rather than TCP.

You can configure the `retry parameters` for your DataTrack with the following options:

* `maxPacketLifeTime` sets the time in milliseconds during which the DataTrack will transmit or retransmit a message until that message is acknowledged.
* `maxRetransmits` sets the maximum number of retransmit attempts that will be made.

DataTrack connections are established between Participants via the media server. Under the hood, there is one connection between a local Participant to the Media server and a second connection from the Media server to the remote Participant. Twilio's media server configures the same `maxPacketLifeTime` value on each remote Participant's connection. Therefore you should set the `maxPacketLifetime` to *half the acceptable max lifetime* for each message you send.
