Skip to main content
Skip table of contents

Insight analytics

To test this feature and view the example code, please see the Android SDK 5 Example Code Quick Start guide.

The application can report player metrics to the Insight servers using the Insight Agent class. It uses the Agent to manage Insight sessions alongside playback, during which content information and playback monitoring information is collated and uploaded to the Insight servers. A session lifecycle normally equates to playback of one content, starting when the content is loaded into the player and ending when the content is unloaded from the player.

The application is responsible for:

  • Instantiating and driving the player

  • Providing metadata about the content

The Agent is responsible for:

  • Observing metrics and events on the player

  • Reporting metrics and events to the Insight servers

Prerequisites

An additional library in the opy-sdk-android-5.32.x-insight-agent-1.2.2.aar package performs the reporting mechanism to Insight servers. There is no need to modify your build.gradle file as the player SDK includes all the dependency declarations. You will need to copy the Insight library file to the common/libs directory of the example code project (or wherever your application defines it as the library directory).

The Agent library is provided with the player SDK library for your convenience. This additional library can be obtained through the Insight Customer Service Desk. However, the Agent wrapper in the SDK is designed to work with the version provided in the SDK package.

Example code

Configuration file

For Insight to be available, a configuration file must be present at src/res/raw/analytics.json of the integrating application. The Insight Agent will read the configuration file when the application creates the Agent. 

Click here to view an example configuration file.
JS
{
  "insightCollectorURL" : "http://validator.insight-stats.com",
  "reportingPeriodInitialDelay" : "3000",
  "reportingPeriod" : "30000",
  "appName":"Sample App",
  "appVersion":"1.0.0",
  "deviceType":"handheld",
  "osType":"Android",
  "videoDecoderType":"H.264",
  "audioDecoderType":"AAC",
  "streamingFormat":"HLS",
  "drmName":"DRM",
  "drmVersion":"1",
  "gpuModel":"None",
  "operatorId":"opId",
  "accessToken":"token"
}

When using this as a reference, be sure to update fields specific to your account and application.

Import classes

The Insight Analytics Agent is delivered along with the Android SDK. To use the Insight Agent the integrating application needs to import the classes.

JAVA
import nagra.insight.agent.Agent;
import nagra.insight.agent.utils.ContentInfoHolder;
import nagra.insight.agent.utils.UserInfoHolder;

Request READ_PHONE_STATE permission (API 29 and above)

Before setting up Insight, runtime permission requests for `READ_PHONE_STATE` are necessary when both of the following conditions are true:

  • The application will run on Android Q devices

  • The application's targetSdkVersion is 29 (Android Q) or higher

Click here to view the code which will show a system dialogue box requesting approval from the user.
JAVA
if (checkReadPhoneStatePermission()) {
  // Permission granted. Can continue.
} else {
  // Permission not granted yet. Need to wait for user's approval.
}

public boolean checkReadPhoneStatePermission() {
  boolean hasPermission = (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED);
  if (!hasPermission) {
    requestReadPhoneStatePermission();
  }
  return hasPermission;
}

@TargetApi(23)
public void requestReadPhoneStatePermission() {
  if (shouldShowRequestPermissionRationale(Manifest.permission.READ_PHONE_STATE)) {
	// Show our own request permission dialog before popping the system one.
	AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
	dialogBuilder.setTitle("External permission required for Read Phone State");
	dialogBuilder.setPositiveButton("Ok", (dialog, which) ->
	  requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, 1))
	  .show();
  } else {
	// Show system dialog to request permission
	requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, 1);
  }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  // Dialogue results callback
  if (requestCode != 1) {
	// Not coming from our request, tagged as 1
	return;
  }
  if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
	// Permission refused/not granted by user
  } else {
	// Permission granted by user
  }
}

If permission has not already been granted, the user's approval comes back asynchronously in the onRequestPermissionsResult() callback, which is an Activity override.

Create Agent

Once the package has been imported, the application can create the Agent in the correct place:

JAVA
mInsightAgent = new Agent(mContext, deviceId, integrationMode);
  • If the specified deviceId is null then the final value for the device ID will be set to Settings.Secure.ANDROID_ID

  • If integrationMode set to true, it allows non-valid operations to be detected during the integration by throwing RuntimeException exceptions. If set to false then the errors will only be logged. The integration flag must be set to false for a production build

The same Agent can be reused for multiple playback sessions, so there is usually no need to instantiate this class more than once.

Click here to see an alternative way the application can create the Agent.
JAVA
// To create an Agent with out the Integration Mode. This will keep the integration mode false by default.
mInsightAgent = new Agent(mContext, deviceId);

or

// To create an Agent by configuring the agent programmatically instead of using the analytics.json configuration file. The config file in the resource folder can exist but will just be ignored.
// If the specified deviceId in the InsightConfig object is null then the final value for the device ID will be set to Settings.Secure.ANDROID_ID.
mInsightAgent = new Agent(mContext, insightConfig);

or

// To create an Agent by configuring the agent programmatically instead of using the analytics.json configuration file. The config file in the resource folder can exist but will just be ignored.
// If the specified deviceId in the InsightConfig object is null then the final value for the device ID will be set to Settings.Secure.ANDROID_ID.
// The 'agentConfig' parameter below stands for the agent wrapper configuration if any.
mInsightAgent = new Agent(mContext, insightConfig, agentConfig);

Session control

The Agent is only responsible for collating the analytics data, it needs the application to control an Insight session alongside playback.

The application should start and end the session to align with the playback of the stream.

  • For both live and VOD, a session should start when playback commences.

  • For VOD streams a session should stop when the playback finishes, whether by error, user action or playout.

  • For live streams, a session should end when the stream is switched or is stopped by an error.

Prepare content information

When starting the session, the application should prepare the content information and user information which will be needed by the session; this includes metadata related to the stream currently playing. If the application has all the metadata available before a stream is selected, it can be created on stream selection. If not, some can be obtained from the video view once it is prepared, in which case something similar to the following snippet would need to be called after receiving the OnPreparedListener.onPrepared event.

Click here to see the example code.
JAVA
// Set stream metadata
ContentInfoHolder contentInfoHolder = new ContentInfoHolder();
contentInfoHolder.setName(mStream.getStreamName());
contentInfoHolder.setUri(mLastVideoUri);
contentInfoHolder.setDuration(mNmpVideoView.getDuration());
contentInfoHolder.setChannelName(mLastVideoUri);
contentInfoHolder.setFramesPerSecondNominal(mNmpVideoView.getRenderingStatistics().getFramesPerSecondNominal());
contentInfoHolder.setType((mNmpVideoView.getDuration() == -1) ? "LIVE" : "VOD");
ArrayList<Integer> bitrateList = new ArrayList<Integer>() {{ for (int i : NetworkStatistics.getAdaptiveStreaming().getAvailableBitrates()) add(i); }};
contentInfoHolder.setBitrates(bitrateList);
if(DRMHandler.getInstance() != null){
  if(!DRMHandler.getInstance().getContentId().isEmpty()) {
    contentInfoHolder.setScrambled(true);
    contentInfoHolder.setContentId(DRMHandler.getInstance().getContentId());
    contentInfoHolder.setChannelName(DRMHandler.getInstance().getContentName());
  }
}

// Set user metadata
UserInfoHolder userInfoHolder = new UserInfoHolder();
userInfoHolder.setUserId("UserId");
userInfoHolder.setAccountId("AccountId");
userInfoHolder.setGender("Gender");
userInfoHolder.setAge(21);
userInfoHolder.setAgeRange("AgeRange");
userInfoHolder.setCategory("Category");
userInfoHolder.setFullName("FullName");
userInfoHolder.setStreet("Street");
userInfoHolder.setCity("City");
userInfoHolder.setState("State");
userInfoHolder.setPostcode("Postcode");
userInfoHolder.setCountry("Country");
userInfoHolder.setCorp("Corp");
userInfoHolder.setNode("Node");

Start session

To start the insight session, the application needs mainly two things OTVVideoView and ContentInfoHolder(content metadata). The UserInfoHolder(user metadata) is optional. The application can start the insight session before starting the player playback session with whatever content information is available. Once and then OTVVideoView receives the onPrepared() event listener callback, it can collect the rest of the content information and update to insight session using updateContent(contentInfoHolder).   For the DRM encrypted content, make sure that the mOTVVideoView holds the right DRM callback before passing it to startSession() API. So that the Insight Wrapper registers the hooks with DRM callbacks for network events.
The network events are used to measure the time consumed to start the playback with the break ups of time spend on the network to download DRM license, manifest, and segments.

JAVA
mInsightAgent.startSession(mOTVVideoView, contentInfoHolder, userInfoHolder);

The application can choose to start the Insight session without the user information,

JAVA
mInsightAgent.startSession(mOTVVideoView, contentInfoHolder);

Stop Session

The application should stop the session if started when the playback finishes, whether by error or the user stopping the playback. Note that the agent resources are still intact and are reused when the session is started again if the application just stops the session.

JAVA
// Stop the Insight session when playback completes
mOTVVideoView.setOnCompletionListener(mp -> {
  OTVLog.i(TAG, "Playback complete");
  mInsightAgent.stopSession();
});
// Stop the Insight session when there is an error during playback
mOTVVideoView.setOnErrorListener((mp, what, extra) -> {
  OTVLog.i(TAG, "Playback error");
  mInsightAgent.stopSession();
  return true;
});

Release Session

The application can stop the session if started and release the agent resources when playback completes or after an error is encountered in playback. This will terminate the active insight session.

JAVA
// Release the Insight session when playback completes
mOTVVideoView.setOnCompletionListener(mp -> {
  OTVLog.i(TAG, "Playback complete");
  mInsightAgent.release();
});
// Release the Insight session when there is an error during playback
mOTVVideoView.setOnErrorListener((mp, what, extra) -> {
  OTVLog.i(TAG, "Playback error");
  mInsightAgent.release();
  return true;
});

The application needs to instantiate the agent and start the session again when it needs the agent further after releasing the session.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.