Using the PolyNet™ SDK

This document is for PolyNetSDK version 3 for Android.

Imports

You will need to import classes from com.system73.polynet.android.sdk and com.system73.polynet.android.sdk.core.metrics packages. The following classes are required:

import com.system73.polynet.android.sdk.PolyNet;
import com.system73.polynet.android.sdk.PolyNetConfiguration;
import com.system73.polynet.android.sdk.PolyNetListener;
import com.system73.polynet.android.sdk.core.metrics.PolyNetMetrics;
import com.system73.polynet.android.sdk.core.metrics.PolyNetOutboundMetrics;
import com.system73.polynet.android.sdk.exception.PolyNetException;

Connecting

The following parameters are needed for a successful integration with PolyNet SDK:

Name Type Description
manifestUrl Mandatory The amount of data as payload received from the CDN since the session started. (Kilobits).
apiKey Mandatory Api Key provided by System73. Contact us in order to obtain it.
context Mandatory Android Context of the Activity where the video player is shown.
channelId Optional Custom identifier for the channel.
playerBufferSize Optional The video player's buffer size in seconds, if you know it or can get it from the player.

Initialize an instance of PolyNet object and uses the property localManifestUrl to initialize the player.

try {
    PolyNetConfiguration configuration = PolyNetConfiguration.builder()
       .setManifestUrl(manifestUrl)
       .setChannelId(channelId)
       .setApiKey(apiKey)
       .setBufferSize(playerBufferSize)
       .setContext(context)
       .build();

    PolyNet polyNet = new PolyNet(configuration);
    polyNet.setListener(polyNetListener);

    // Init the player with the local manifest URL.
    //
    // For example:
    // initializePlayer(polyNet.getLocalManifestUrl())
} catch {
    // The PolyNet CANNOT be used as there was an initialisation issue.
    // Init the player with the original manifest URL.
    //
    // For example:
    // initializePlayer(manifesUrl)
    // Where manifestUrl is the original URL of the manifest.
}

Important: Initialise the player instance with the localManifestUrl property of the PolyNet instance. Do not start the player with the original manifest URL unless the PolyNet object fails to init.

If any required parameter is missing, invalid, or there are other problems during initialization, an exception of class PolyNetException might be thrown. You should catch it, examine the error message, and check your integration. If problem persists, contact support at support@system73.com.

List of initialization errors

This is the list of the possible initialization errors that may be thrown. You can obtain the error code with the getCode() method of class PolyNetException.

Code Description
-600 Check your API Key. If problem persists, contact support at support@system73.com.
-601 Check your API Key. If problem persists, contact support at support@system73.com.
-602 Check your API Key. Detail: (...). If problem persists, contact support at support@system73.com.
-603 The PolyNet SDK has failed to build. Detail: (...). If problem persists, contact support at support@system73.com.

Providing metrics

You MUST provide the PolyNet instance with some of the video player's metrics. For each reported metric, call the specific report methods of the PolyNet instance as explained below.

For PolyNet to work properly you MUST regularly provide the buffer health metric.

Each video player provides access to the metrics in different ways.

The PolyNet instance supports both ways:

// ... rest of code

player.addListener(new PlayerEventAdapter() {
   @Override
   public void onPlayerStateChanged(boolean playWhenReady, int state) {
      if (state == Player.STATE_READY) {
         if (polyNet != null) {
            polyNet.reportPlayBackStarted();
         }
      }
   }
});

// ... rest of code

player.setVideoDebugListener(new VideoRendererEventAdapter() {
   @Override
   public void onDroppedFrames(int count, long elapsed) {
      for (int n = 0; n < count; n++) {
         if (polyNet != null) {
            polyNet.reportDroppedFrame();
         }
      }
   }
});

// ... rest of code

In our Sample App using ExoPlayer 2, this source code is inside the PlayerActivity class.

private final PolyNetListener polyNetListener = new PolyNetListener() {

        @Override
        public void onBufferHealthRequest(PolyNet polyNet) {
            if (player != null) {
                // Report the buffer health only if we can compute it
                long bufferPos = player.getBufferedPosition();
                long currentPos = player.getCurrentPosition();
                long bufferHealthInMs = bufferPos - currentPos;
                polyNet.reportBufferHealth(bufferHealthInMs);
            }
        }

        @Override
        public void onDroppedFramesRequest(PolyNet polyNet) {
            // No need to implement it for ExoPlayer.
        }

        @Override
        public void onPlayBackStartedRequest(PolyNet polyNet) {
            // No need to implement it for ExoPlayer.
        }

        // ... rest of code

};

This source code is shown in the PlayerActivity class of the System73 Sample App using ExoPlayer 2.

Handling events [Optional]

Error event

When the SDK finds a run-time problem (such as the Internet could not be accessed, etc.), a corresponding PolyNetException can be obtained from the onError() method inside the polyNetListener.

Nevertheless, the SDK will keep working as reliably as possible. This method is useful in the debugging of the integration process.

For example in our Sample App using ExoPlayer 2, this source code is added in the PlayerActivity class.

private final PolyNetListener polyNetListener = new PolyNetListener() {

        // ... rest of code

        public void onError(PolyNet polyNet, PolyNetException e) {
            Log.e(TAG, "PolyNet error", e);
        }

        // ... rest of code

};

You should print it to the logs, examine the error message, and check your integration. If problem persists, contact support at support@system73.com.

List of run-time errors

This is the list of the possible run-time errors that may be thrown. You can obtain the error code with the getCode() method of class PolyNetException.

Code Description
-700 The PolyNet SDK has failed and raised an exception. Detail: (...). If problem persists, contact support at support@system73.com.
-701 The PolyNet SDK is not compatible with the backend provided. Backend code: (...). This may happen in transitions to newer versions. If problem persists, contact support at support@system73.com.
-702 Error communicating with backend. Detail: (...). If problem persists, contact support at support@system73.com.
-703 Error communicating with backend metrics endpoint. Detail: (...). If problem persists, contact support at support@system73.com.

Metrics event

You can get some of PolyNet metrics from the onMetrics method inside the polyNetListener. For each reported metric, call the specific get method of the PolyNetMetrics instance:

private final PolyNetListener polyNetListener = new PolyNetListener() {

        // ... rest of code

        @Override
        public void onMetrics(PolyNetMetrics polyNetMetrics) {
            // Access metrics
        }

        // ... rest of code

};

The reported metrics are as following:

Name Type Description
accumulatedCdnDownThroughput String The amount of data as payload received from the CDN since the session started. (Kilobits).
accumulatedP2pDownThroughput String The amount of data as payload received from P2P since the session started. (Kilobits).
bufferFillingRate String The rate at which the content is received versus playing time.
cdnDownThroughput String The amount of data as payload received from the CDN during the last reporting period. (Kilobits).
connectionStatus String Describes the current connection status of the node.
date String The timestamp on which the metrics object was created.
deviceId String Unique identifier for the device running the PolyNet.
inboundNodeId String Unique identifier for the inbound connection if connected to other peer or the value “POI” if downloading from CDN.
nodeId String Unique identifier for the PolyNet node.
outboundMetrics Array Metrics for outbound peers. See below Outbound Metrics.
p2pDownThroughput String The amount of data as payload received from P2P during the last reporting period. (Kilobits).
playerBufferHealth String The amount of milliseconds (playback time) that are left for playing in the player's video read-ahead buffer.
playerTimeToFirstFrame String The amount of milliseconds from the start of the PolyNet until the player starts playback.
primaryManifestUrl String HLS: This is the master playlist URL with .m3u or .m3u8 extensions. DASH: This is the manifest URL with .mpd extension.
representationId String Unique identifier for the current representation or rendition being displayed.
roundTripTime String The amount of time between sending a data packet from a child node to its inbound P2P peer and back. (milliseconds).
secondaryManifestUrl String HLS: This is the media playlist URL with .m3u or .m3u8 extensions.
source String The source specifies where the content is downloaded from.
streamId String Unique identifier for the current stream being displayed.

Outbound metrics:

Name Type Description
bufferFillingRate String The rate at which the content is received in the PolyNet outbound peer versus playing time.
nodeId String Unique identifier for the PolyNet outbound peer.
status String The status of the connection for the PolyNet outbound peer.

Disconnecting from PolyNet

Listeners can be unsubscribed from the PolyNet instance as follows:

polyNet.removeListener();

To disconnect:

polyNet.dispose();

IMPORTANT: Once you dispose of this PolyNet instance, you MAY NOT use it again. If you want to connect to a new channel or the same channel, go back to the initialization steps and create a new instance.

Other considerations [Optional]

Streams with encryption keys

The optional property manageEncryptionKeys can be used to initialize the PolyNet instance. You may call the corresponding manageEncryptionKeys method in the PolyNetConfiguration.Builder to set or unset it:

PolyNetConfiguration configuration = PolyNetConfiguration.builder()
   .setManifestUrl(manifestUrl)
   .setChannelId(channelId)
   // ... rest of code
   .manageEncryptionKeys(false) // true by default
   .build();

PolyNet polyNet = new PolyNet(configuration);

// ... rest of code

Setting or unsetting this property is relevant on some scenarios where the stream is encrypted: when the media segments need to be decrypted, the player usually needs to retrieve specific Key files. With the manageEncryptionKeys property you can choose whether these Key files are handled by the PolyNet SDK (true) or by the player (false). This is relevant depending on the authentication scheme required to access the license servers and Key files.

When this property is set to false, the PolyNet SDK delegates to the player all requests related to Key files. This is useful when authentication is managed with cookies that need to be handled externally or prior the player is initialized.

This property is set to true by default on the PolyNetConfiguration.

Sharing content

The optional property sharingContent controls whether the PolyNet shares the video content with other peers. This property is used after initializing the PolyNet instance.

Accepts values from the SharingContent enum which are the following:

Option Description
NEVER The video content will never be shared with other peers.
ONLY_ON_LAN The video content will be shared only if connected via WIFI or ETHERNET.
ALWAYS The video content will be shared with other peers whenever possible.

This property is set to ONLY_ON_LAN by default.

You will need to import the following class from com.system73.polynet.android.sdk package.

import com.system73.polynet.android.sdk.SharingContent;

After this, you may call the corresponding sharingContent method to set or unset it. For example:

PolyNet polyNet = new PolyNet(configuration);

// ... rest of code

polyNet.sharingContent(SharingContent.ONLY_ON_LAN);

Using cookies containing authentication tokens

Some content providers implement authentication with cookies containing the access tokens. Properly handling those cookies is necessary to grant access to the content.

To support content streams with cookies, the PolyNet instance needs access to an Android CookieHandler. Video players (like ExoPlayer) should be able to access one, in order to properly handle cookies themselves. You should share the same CookieHandler instance between the video player and the PolyNet SDK instance. If you don't explicitly provide the SDK with a CookieHandler, it will try to access the system-wide default CookieHandler instead.

The method to set the cookie handler is setCookieHandler in PolyNetConfiguration.Builder.