Teleport SDK for Android OS

Requirements and installation

For Teleport SDK to work, you need:

  • Version Android 5.0 and above.
  • Android system WebView version 58 and above. In case if Android system WebView does not meet the requirements, it can be updated from Google Play starting from Android 5.0.

Launch

Before using the SDK, you must add project dependencies to the gradle file. To do this, specify the Maven repository URL in the Repositories section and specify the dependency in the Dependencies section.

Example:

repositories {
    //Url Maven репозитория Teleport
    maven { url 'https://sdk.teleport.media/artifactory/android/'}
    jcenter()
}

dependencies {
    //TeleportSDK dependency
    implementation 'media.teleport.sdk:teleport-sdk:2.4.+'
}

You must also add to the AndroidManifest.xml manifest file the following permissions:

<uses-permission android:name="android.permission.INTERNET"/>

Application

Before initializing the player, you must initialize the Teleport SDK. Initialization takes place by calling the static init method. It is recommended that you initialize the Teleport SDK in the onCreate() method extending your Application class.

Example:

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        TeleportSDK.init(getApplicationContext());
    }
}

After the Teleport SDK is initialized, you must create an instance of the Teleport SDK class that is used to configure the operation.

Then the Teleport SDK is started by calling the start () method. Errors may occur when initializing the SDK. In such cases, when calling the start () method, the InitializationException exception must be wiped. The player will be initialized with the modified links to the manifest received from the SDK by calling getChangedManifestUrl(). Therefore Teleport SDK will not start, getChangedManifestUrl() will return the original manifest link, thus not disrupting the player.

Integration example with ExoPlayer

TeleportSDK teleportSdk = new TeleportSDK(apiKey);

try {
    // SDK Launch
    teleportSdk.start();
} catch (InitializationException ex) {
    Log.d("TeleportSDK",ex.getMessage().toString());
}

// Getting the modified or original (in case of an error) manifest URL
Uri manifestUriSdk = teleportSdk.getChangedManifestUrl(manifestUri);

// Player initialization
DataSource.Factory factory = new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "TeleportDemo"));
MediaSource mHlsMediaSource = new HlsMediaSource(changedUriFromSDK, factory, mainHandler, null);
simpleExoPlayerView.setPlayer(player);
player.prepare(mHlsMediaSource, false, false);

The following parameters are transmitted to the Teleport SDK constructor:

  • apiKey - API key. Cannot be null. You have to get the mobile Teleport SDK API key in the Teleport client area.
public TeleportSDK(@NonNull String apiKey)

Events

To get feedback in the Teleport SDK class, a class that implements the TeleportEvents interface can be transmitted using the setTeleportEventsListener(TeleportEvents eventsListener) method.

void onServerConnected(String peerId)

Is called when the SDK is initialized and connected to the Teleport server.

peerId - unique peer ID

void onSegmentLoaded(DownloadStatSegment stat)

Is called when a segment is loaded.

DownloadStatSegment - a class that contains information about the downloaded chunk.

void onSegmentUploaded(UploadStatSegment stat)

Is called when a chunk is sent to a peer-to-peer network.

UploadStatSegment - a class that contains information about the uploaded chunk.

void onPeerConnected(String peerId)

Is called with the new peer connection

peerId - unique peer ID

void onPeerDisconnected(String peerId)

Is called with the new peer disconnection

peerId - unique peer ID

void onPeeringModeChanged(PeeringMode mode)

Is called when the peering mode is changed.

PeeringMode - peering mode.

void onError(Throwable error)

It is called when interpreting manifest or segment calls leads to errors.

Methods

public void start() throws InitializationException

Starts the Teleport SDK. If an error occurs, while launch or initialization an exception is alerted.

public void buffering()

Reports on player buffering.

Example with ExoPlayer:

// Redefined method of the ExoPlayer listener
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
    if (playbackState == ExoPlayer.STATE_BUFFERING){
       teleportSdk.buffering();
    }
}

public void dispose()

A method releasing all resources used by the Teleport SDK.

public void setPeeringMode(PeeringMode mode)

Establishes the peering mode using the PeeringMode listing

Example:

teleportSdk.setPeeringMode(PeeringMode.FULL);

private void getStats(StatType type, StatsCallback callback)

Returns the total statistics for the traffic of the current SDK session.

  • type - type of requested statistics set using StatType enum.
  • callback - class implementing the StatsCallback interface.

Example:

teleportSdk.getStats(StatType.FULL, new StatsCallback() {
    @Override
    public void onStatsReady(Stats stats) {
       Log.i("TeleportStats", stats.toString());
    }
});

public Uri getChangedManifestUrl(Uri manifestUri)

Receives a modified link to the manifest after the SDK is initialized.

Settings

To improve the performance of P2P delivery, it worth setting up additional parameters before initialization.

public void setUrlCleaner(UrlCleaner urlCleaner)

Remove personalized information from the video segment or manifest URL to work correctly with the stream. This method sets a class implenting the UrlCleaner interface, containing the function cleanUrl, that is used to unify URL-addresses of video-segments and manifest of a video-stream.

Example:

teleportSdk.setUrlCleaner(new UrlCleaner() {
      @Override
      public String cleanUrl(Uri url) {
          return url.getPath();
       }
});

public void setQualityGetter(QualityGetter qualityGetter)

To improve the quality of Teleport PDN it is adviced to set the class implementing the QualityGetter interface to detect the active video-stream.

Example:

public class SimpleQualityGetter implements QualityGetter {

Map<Integer, Quality> id2qualitys;
    public FirstChannelQualityGetter() {
        id2qualitys = new HashMap<>();
        id2qualitys.put(1, Quality.Q720P);
        id2qualitys.put(2, Quality.Q720PLow);
        id2qualitys.put(3, Quality.Q360PHigh);
    }
    @Override
    public Quality getQuality(Segment segment) {
        try {
            int id = Integer.parseInt(segment.getQualityId());
            Quality res = id2qualitys.get(id);
            if (res == null)
                return Quality.Unknown;
                return res;
        } catch (NumberFormatException ex) {
              return Quality.Unknown;
       }
    }
}

. . .

teleportSdk.setQualityGetter(new SimpleQualityGetter());

public void setBufferSizeGetter(BufferSizeGetter bufferSizeGetter)

For Teleport PDN to work it is required to set the class implementing the BufferSizeGetter interface to detect the size of player's buffer size. Otherwise, segments will not be downloaded from the peer network.

Example with ExoPlayer:

this.sdk.setBufferSizeGetter(new BufferSizeGetter() {
    @Override
    public float getBufferSize() {
        if (player != null)
            return TimeUnit.MILLISECONDS.toSeconds(exoPlayer.getBufferedPosition() - exoPlayer.getCurrentPosition);
        else return 0;
    }
});

public void setManifestAcceptor(ManifestAcceptor accepter)

To find the necessary connections Teleport uses the video stream URL. By default, Teleport specifies the manifest for .m3u8 or .mpd extension. If your media server issues specific manifest URLs, you have to define a manifest search function.

Example:

teleportSdk.setManifestAcceptor(new ManifestAcceptor() {
     @Override
     public boolean acceptManifest(Uri manifestUrl) {
         return manifestUrl.getPath().contains("m3u8");
     }
 });

public void setSegmentAcceptor(SegmentAcceptor accepter)

To start data transfer with Teleport, it is necessary to define the exact request to download the video segment. By default, Teleport defines video segments by the following extensions:.ts, .mp4, .m4s.

If your media server issues specific manifest URLs, you have to define a manifest search function.

Example:

teleportSdk.setSegmentAcceptor(new SegmentAcceptor() {
     @Override
     public boolean acceptSegment(Segment segment) {
         return segment.getSegmentURL().contains(".ts");
     }
});

Security configuration

Teleport SDK processess requests sent from player to localhost. Starting from Android 9 (API 28) it is prohibited to send data in plaintext. For SDK to work it is necessary to allow sending data in plaintext to localhost. To do so we need to configure security settings. Teleport SDK automatically sets security settings, but if you use your own settings, allow sending plaintext data to localhost.

res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:android="http://schemas.android.com/apk/res/android">
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
    </domain-config>
</network-security-config>

Player Settings

ExoPlayer

Setting timeout

For optimal experience of using ExoPlayer with Teleport SDK it is recommended to multiply the default read time value by a factor of 2.

DefaultHttpDataSourceFactory defaultHttpDataSourceFactory =  new DefaultHttpDataSourceFactory(
    Util.getUserAgent(this, "ApplicationName"),
    null,
    DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
    DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS * 2,
    false
);

Buffer size

Starting from version 2.9.0 ExoPlayer requires access to the player from the main thread. To overcome this redefine looper() method in abstract class BufferSizeGetter. This methods returns a Looper connected with the main thread.

class ExoPlayerCustomBufferSizeGetter extends BufferSizeGetter {

    private ExoPlayer player;

    public ExoPlayerCustomBufferSizeGetter(ExoPlayer player) {
        this.player = player;
    }

    @Override
    public Looper looper() {
        return player.getApplicationLooper();
    }

    @Override
    public float getBufferSize() {
        if (player != null)
            return (player.getBufferedPosition() - player.getCurrentPosition()) / 1000f;
        else return 0;
    }
}

Enums

Quality

Video stream qualities enumeration

public enum Quality {
    Unknown,
    Q144P,
    Q240P,
    Q360P,
    Q480P,
    Q720P,
    Q1080P,
    Q4K
}

StatType

public enum StatType {
    FULL,
    FROM_LAST_CHECKPOINT
}

Available values:

  • FULL - requests full statistics from the moment Teleport SDK started working.
  • FROM_LAST_CHECKPOINT - statistics from the moment of last request.

PeeringMode

P2P modes enumeration

Available values:

  • Off - p2p mode is off
  • Download - peer downloads only from p2p
  • Upload - peer uploads only to p2p
  • Full - full duplex mode available
public enum PeeringMode {
    OFF,
    DOWNLOAD,
    UPLOAD,
    FULL
}

SegmentType

Segment type enumeration

public enum SegmentType {
    UNKNOWN,
    VIDEO,
    AUDIO,
    CAPTION,
    OTHER
}

Source

Segment download sources enumeration

public enum Source {
    PDN,
    CDN
}

Classes

class Segment

Provides information about the segment.

public class Segment {
    SegmentType type;
    String segmentURL; 
    String qualityId;
    double duration;
    int bandwidth;
}

class DownloadStatSegment

Provides statistics about the downloaded segment

public class DownloadStatSegment {
    long timestamp;     // Segment download time
    Result result;      // Object with the segment` download data
    Timings timings;    // Object with the measured timing data
    Request request;    // Object with the requested segment data
}

class UploadStatSegment

Provides statistics about the uploaded segment

public class UploadStatSegment {
    long timestamp;           // Segment upload time
    Result result;            // Object with the segment` download data
    Timings timings;          // Object with the measured timing data
    UploadRequest request;    // Object with the requested segment data
}

class Result

Segment load data

public class Result {
    String segmentId;       //Segment identifier
    Source sourceId;        //The source of segment download
    int waitTimeout;        //Download from p2p pending timeout
    int flags;              //Download flags
    int downloadTimeout;    //Download timeout from p2p
    long size;              //Segment size in bytes
    int haves;              //Amount of peers with target segment in a swarm
    boolean connected;      //Teleport connection with servers activity flag
    boolean active;         //Teleport p2p activity flag
    int swarmSize;          //Swarm size value
    PeeringMode mode;       //Peering mode
}

class Request

Segment query data

public class Request {
    String uri;          //Standardized URI of the segment after processing by the urlCleaner.
    String url;          //Segment source URL
    float bufferSize;    //Player buffer size in seconds
    float duration;      //Segment length in seconds
    int quality;         //Current video stream quality
    SegmentType type;    //Segment type
}

class Timings

Measured timings data

public class Timings {
    long reqStart;      //Timestamp of the segment request time
    long ttFinish;      //The difference between the end of segment processing and data transfer to the player
    int ttHave;         //The difference of the awaiting of the segment from p2p
    int ttlb;           //The Difference of the end of the chunk download
    int ttSent;         //The Difference of download initialization time
    int ttFb;           //The Difference of the awaiting of the first chunk
}

class UploadRequest

Segment upload data requests

public class UploadRequest {
    String connectionId;   //Peer identifier
    String segmentId;      //Segment identifier
}

class StatsTotals

Class with statistical data about upload and download.

public class Stats {
    long duration;
    Traffic cdn;      // Download from CDN
    Traffic pdn;      // Download from PDN
    Traffic upload;   // Upload to PDN
}

class Traffic

Class with statistics data.

public class Traffic {
    int size;      // Size in bytes
    int count;     // Total number of downloaded and uploaded segments
    long time;     // Total time of download and upload of segments in milliseconds
    double speed;  // Average speed of download and upload of segments in Mbps
}

Interfaces

TeleportEvents

Teleport SDK notifying events.

public interface TeleportEvents {
    void onServerConnected(String peerId);
    void onSegmentLoaded(DownloadStatSegment stat);
    void onSegmentUploaded(UploadStatSegment stat);
    void onPeerConnected(String userId);
    void onPeerDisconnected(String userId);
    void onPeeringModeChanged(PeeringMode mode);
}

StatsCallback

Interface contains a callback to onStatsReady that signals that statistical data is ready.

public interface StatsCallback {
    void onStatsReady(Stats stats);
}