Play DRM-protected content (Android)

Learn how to enable digital rights management (DRM) protected playback for an Android app.


Digital rights management depends upon the hardware that is being used and allows you to protect the digital media in your app. On Android 4.3+, DRM-protected playback is supported for any DRM scheme for which a modular DRM component exists on the device. All Android devices are required to support Widevine modular DRM (with L3 security, although many devices also support L1).



Requirements

  • Android 4.3+
  • DRM license server URL


Supported DRM provider

Google Widevine

πŸ“˜

Not all Android devices may have secure decoders for every video codec. You can use Android's MediaCodecList class to find out if secure playback for a particular codec is supported on a device.



Configure the playback

Regardless of the DRM provider that you use, the following steps generally apply to enable the playback of DRM-protected content:

  1. Add a Util.java to your project. This utility is used by the MediaDrmCallback class to download data.

    public class Util {
    
       public static byte[] executePost(String url, byte[] data, Map<String, String> requestProperties)
               throws IOException {
           HttpURLConnection urlConnection = null;
           try {
               urlConnection = (HttpURLConnection) new URL(url).openConnection();
               urlConnection.setRequestMethod("POST");
               urlConnection.setDoOutput(data != null);
               urlConnection.setDoInput(true);
               if (requestProperties != null) {
                   for (Map.Entry<String, String> requestProperty : requestProperties.entrySet()) {
                       urlConnection.setRequestProperty(requestProperty.getKey(), requestProperty.getValue());
                   }
               }
               // Write the request body, if there is one.
               if (data != null) {
                   OutputStream out = urlConnection.getOutputStream();
                   try {
                       out.write(data);
                   } finally {
                       out.close();
                   }
               }
               // Read and return the response body.
               InputStream inputStream = urlConnection.getInputStream();
               try {
                   return toByteArray(inputStream);
               } finally {
                   inputStream.close();
               }
           } finally {
               if (urlConnection != null) {
                   urlConnection.disconnect();
               }
           }
       }
    }
    
  2. Add the appropriate DRM provider callback .java file to your project. Contact your DRM provider for its suggested MediaDrmCallback implementation for Android.

    For the following generic Widevine implementation example, assume that each new PlaylistItem requires a unique contentId and provider. This implementation enables you to specify these required values for every instance of WidevineMediaDrmCallback.

    @TargetApi(18)
    public class WidevineMediaDrmCallback implements MediaDrmCallback {
    
       private static final String WIDEVINE_GTS_DEFAULT_BASE_URI =
               "https://proxy.uat.widevine.com/proxy";
    
       private final String defaultUri;
    
       public WidevineMediaDrmCallback(String contentId, String provider) {
           String params = "?video_id=" + contentId + "&provider=" + provider;
           defaultUri = WIDEVINE_GTS_DEFAULT_BASE_URI + params;
       }
    
       protected WidevineMediaDrmCallback(Parcel in) {
           defaultUri = in.readString();
       }
    
       public static final Creator<WidevineMediaDrmCallback> CREATOR = new Creator<WidevineMediaDrmCallback>() {
           @Override
           public WidevineMediaDrmCallback createFromParcel(Parcel in) {
               return new WidevineMediaDrmCallback(in);
           }
    
           @Override
           public WidevineMediaDrmCallback[] newArray(int size) {
               return new WidevineMediaDrmCallback[size];
           }
       };
    
       @Override
       public byte[] executeProvisionRequest(UUID uuid, ExoMediaDrm.ProvisionRequest request) throws IOException {
           String url = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
           return Util.executePost(url, null, null);
       }
    
       @Override
       public byte[] executeKeyRequest(UUID uuid, ExoMediaDrm.KeyRequest request) throws IOException {
           String url = request.getLicenseServerUrl();
           if (TextUtils.isEmpty(url)) {
               url = defaultUri;
           }
           return Util.executePost(url, request.getData(), null);
       }
    
       @Override
       public int describeContents() {
           return 0;
       }
    
       @Override
       public void writeToParcel(Parcel dest, int flags) {
           dest.writeString(defaultUri);
       }
    }
    
  3. Set the video URL of your DRM-protected video to a PlaylistItem (file).

  4. Create a new instance of your MediaDrmCallback implementation and set it to the PlaylistItem.

    // Create a list to contain the PlaylistItems
    List<PlaylistItem> playlist = new ArrayList<>();
    
    // Add a PlaylistItem pointing to the first piece of content
    PlaylistItem content = new PlaylistItem.Builder()
      .file("https://content/drm-protected-content.m3u8")
      .mediaDrmCallback(new WidevineMediaDrmCallback("{INSERT_CONTENT_ID}", "{INSERT_PROVIDER}"))
      .build();
    
    // Add the content to the playlist
    playlist.add(content);