Widevine sample player
For bug 4245169 Change-Id: Ie110d5603f19cd54878d2c4506e8ffad11207f10
15
proprietary/samplePlayer/Android.mk
Normal file
@@ -0,0 +1,15 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := WidevineSamplePlayer
|
||||
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
# Use the following include to make our test apk.
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||
48
proprietary/samplePlayer/AndroidManifest.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.widevine.demo"
|
||||
>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||
<activity android:name=".WidevineSamplePlayer"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".VideoPlayerView"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".StreamingActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".DownloadActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".SettingsActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
2
proprietary/samplePlayer/default.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
# Project target.
|
||||
target=android-12
|
||||
45
proprietary/samplePlayer/readme
Normal file
@@ -0,0 +1,45 @@
|
||||
README: WidevineSamplePlayer.apk
|
||||
|
||||
[Install application:]
|
||||
|
||||
Attach a device
|
||||
In a terminal window:
|
||||
change directory to vendor/widevine/proprietary/samplePlayer
|
||||
type the following commands:
|
||||
mm
|
||||
adb root
|
||||
adb remount
|
||||
adb sync
|
||||
adb reboot
|
||||
|
||||
demo is installed to out/target/product/stingray/system/app/WidevineSamplePlayer.apk
|
||||
|
||||
|
||||
[Download content for offline testing:]
|
||||
|
||||
View http://seawwws001.shibboleth.tv/android/oem.html source for asset names.
|
||||
|
||||
For example:
|
||||
|
||||
curl -sL "http://seawwws001.cdn.shibboleth.tv/videos/content/starz_demo_ffmpeg_hc_single_720p.wvm" -O
|
||||
adb shell mkdir -p /sdcard/Widevine
|
||||
adb push starz_demo_ffmpeg_hc_single_720p.wvm /sdcard/Widevine/
|
||||
|
||||
|
||||
[Running the application:]
|
||||
|
||||
On your device, open WidevineDemo.
|
||||
The Streaming tab should be highlighted, with content available in 480p and 720p encodings.
|
||||
Select an asset to play.
|
||||
You should see a player page. To successfully play back content:
|
||||
-Select Acquire Rights
|
||||
-Select Play (or click the player window to start playback)
|
||||
|
||||
Selecting Show Rights will provide the license time left for playback in the log screen next to the player.
|
||||
Selecting Remove Rights will stop further attempts to play back from succeeding for more than 10 seconds. You will need to then select Acquire Rights to allow playback again.
|
||||
|
||||
Stop video, and go back one screen to the video list.
|
||||
Select the Downloads tab.
|
||||
You should see the video we pushed to the device (starz_demo_ffmpeg_hc_single_720p.wvm).
|
||||
Behavior on this page should be the same as for the Streaming page, with the exception that once you Acquire Rights, you should be able to continue playback of the Downloaded asset offline as long as the rights are valid. You can check the status of your rights with the Show Rights button.
|
||||
|
||||
BIN
proprietary/samplePlayer/res/drawable-hdpi/background3.png
Normal file
|
After Width: | Height: | Size: 662 KiB |
BIN
proprietary/samplePlayer/res/drawable-hdpi/download_clip.jpg
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
proprietary/samplePlayer/res/drawable-hdpi/empty.png
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
proprietary/samplePlayer/res/drawable-hdpi/icon.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
proprietary/samplePlayer/res/drawable-hdpi/play_shield.png
Normal file
|
After Width: | Height: | Size: 376 KiB |
BIN
proprietary/samplePlayer/res/drawable-hdpi/selection_circle.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
proprietary/samplePlayer/res/drawable-hdpi/streaming_clip.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
proprietary/samplePlayer/res/drawable-ldpi/background3.png
Normal file
|
After Width: | Height: | Size: 662 KiB |
BIN
proprietary/samplePlayer/res/drawable-ldpi/download_clip.jpg
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
proprietary/samplePlayer/res/drawable-ldpi/empty.png
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
proprietary/samplePlayer/res/drawable-ldpi/icon.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
proprietary/samplePlayer/res/drawable-ldpi/play_shield.png
Normal file
|
After Width: | Height: | Size: 376 KiB |
BIN
proprietary/samplePlayer/res/drawable-ldpi/selection_circle.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
proprietary/samplePlayer/res/drawable-ldpi/streaming_clip.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
proprietary/samplePlayer/res/drawable-mdpi/background3.png
Normal file
|
After Width: | Height: | Size: 662 KiB |
BIN
proprietary/samplePlayer/res/drawable-mdpi/download_clip.jpg
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
proprietary/samplePlayer/res/drawable-mdpi/empty.png
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
proprietary/samplePlayer/res/drawable-mdpi/icon.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
proprietary/samplePlayer/res/drawable-mdpi/play_shield.png
Normal file
|
After Width: | Height: | Size: 376 KiB |
BIN
proprietary/samplePlayer/res/drawable-mdpi/selection_circle.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
proprietary/samplePlayer/res/drawable-mdpi/streaming_clip.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
7
proprietary/samplePlayer/res/layout/empty.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView android:id="@+id/textView1" android:text="@string/no_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="40pt" android:background="@drawable/background3" android:gravity="center"></TextView>
|
||||
</LinearLayout>
|
||||
21
proprietary/samplePlayer/res/layout/main.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/tabhost"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="5dp">
|
||||
<TabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</TabHost>
|
||||
88
proprietary/samplePlayer/res/layout/settings.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:stretchColumns="1"
|
||||
android:background="@drawable/background3">
|
||||
|
||||
<TableRow android:paddingTop="50dip" >
|
||||
<TextView
|
||||
android:layout_width="200dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:typeface="serif"
|
||||
android:textSize="30sp"
|
||||
android:paddingLeft="100dip"
|
||||
android:text="@string/drm_server"/>
|
||||
<EditText
|
||||
android:layout_width="600dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/drm_server"
|
||||
/>
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:layout_width="200dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:typeface="serif"
|
||||
android:textSize="30sp"
|
||||
android:paddingLeft="100dip"
|
||||
android:text="@string/device_id"/>
|
||||
<EditText
|
||||
android:layout_width="600dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/device_id"
|
||||
/>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="200dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:typeface="serif"
|
||||
android:textSize="30sp"
|
||||
android:paddingLeft="100dip"
|
||||
android:text="@string/portal_id"/>
|
||||
<EditText
|
||||
android:layout_width="600dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/portal_id"
|
||||
/>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="200dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_column="1"
|
||||
android:typeface="serif"
|
||||
android:textSize="30sp"
|
||||
android:paddingLeft="100dip"
|
||||
android:text="@string/content_page"/>
|
||||
<EditText
|
||||
android:layout_width="600dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/content_page"
|
||||
/>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center"
|
||||
>
|
||||
<Button
|
||||
android:text="@string/update_button"
|
||||
android:id="@+id/update_button"
|
||||
/>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
19
proprietary/samplePlayer/res/values/strings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Widevine Demo</string>
|
||||
<string name="no_content">No Content Found</string>
|
||||
<string name="play">Play</string>
|
||||
<string name="stop">Stop</string>
|
||||
<string name="constraints">Constraints</string>
|
||||
<string name="acquire_rights">Acquire Rights</string>
|
||||
<string name="remove_rights">Remove Rights</string>
|
||||
<string name="show_rights">Show Rights</string>
|
||||
<string name="streaming">Streaming</string>
|
||||
<string name="downloads">Downloads</string>
|
||||
|
||||
<string name="content_page">Content Page</string>
|
||||
<string name="device_id">Device Id</string>
|
||||
<string name="drm_server">Drm Server</string>
|
||||
<string name="portal_id">Portal Name</string>
|
||||
<string name="update_button">Update Button</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Button;
|
||||
|
||||
public abstract class AssetActivity extends Activity {
|
||||
|
||||
private int currentPage;
|
||||
protected ArrayList<AssetsPage> pages;
|
||||
private Context context;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
context = this;
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
currentPage = 0;
|
||||
|
||||
pages = new ArrayList<AssetsPage>();
|
||||
|
||||
if (setUpAssetPages()) {
|
||||
setContentView(createView(this));
|
||||
} else {
|
||||
setContentView(R.layout.empty);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean setUpAssetPages();
|
||||
|
||||
private View createView(Context ctxt) {
|
||||
|
||||
ImageView empty = new ImageView(this);
|
||||
empty.setBackgroundDrawable(getResources().getDrawable(R.drawable.empty));
|
||||
|
||||
View[] clips = new View[6];
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inDither = true;
|
||||
|
||||
AssetsPage page = pages.get(currentPage);
|
||||
|
||||
for (int i = 0; i < page.getPageCount(); i++) {
|
||||
|
||||
AssetItem assetItem = page.getPage(i);
|
||||
clips[i] = createViewItem(getBitmapFromAssetItem(assetItem), assetItem.getAssetPath(),
|
||||
assetItem.getTitle());
|
||||
|
||||
}
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.FILL_PARENT, 1);
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
|
||||
|
||||
LinearLayout.LayoutParams paramsMain = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.FILL_PARENT, 1);
|
||||
paramsMain.gravity = Gravity.CENTER;
|
||||
|
||||
LinearLayout left = new LinearLayout(ctxt);
|
||||
left.setOrientation(LinearLayout.VERTICAL);
|
||||
if (clips[0] != null) {
|
||||
left.addView(clips[0], params);
|
||||
}
|
||||
if (clips[3] != null) {
|
||||
left.addView(clips[3], params);
|
||||
} else {
|
||||
left.addView(createEmptyView(), params);
|
||||
}
|
||||
|
||||
LinearLayout middle = new LinearLayout(ctxt);
|
||||
middle.setOrientation(LinearLayout.VERTICAL);
|
||||
if (clips[1] != null) {
|
||||
middle.addView(clips[1], params);
|
||||
}
|
||||
if (clips[4] != null) {
|
||||
middle.addView(clips[4], params);
|
||||
} else {
|
||||
middle.addView(createEmptyView(), params);
|
||||
}
|
||||
|
||||
LinearLayout right = new LinearLayout(ctxt);
|
||||
right.setOrientation(LinearLayout.VERTICAL);
|
||||
if (clips[2] != null) {
|
||||
right.addView(clips[2], params);
|
||||
}
|
||||
params.gravity = Gravity.BOTTOM;
|
||||
if (clips[5] != null) {
|
||||
right.addView(clips[5], params);
|
||||
} else {
|
||||
right.addView(createEmptyView(), params);
|
||||
}
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
|
||||
|
||||
LinearLayout body = new LinearLayout(ctxt);
|
||||
|
||||
body.addView(left, paramsMain);
|
||||
body.addView(middle, paramsMain);
|
||||
body.addView(right, paramsMain);
|
||||
|
||||
// Next button listener
|
||||
View.OnClickListener nextButtonListener = new View.OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
currentPage++;
|
||||
if (currentPage >= pages.size()) {
|
||||
currentPage = 0;
|
||||
}
|
||||
setContentView(createView(context));
|
||||
}
|
||||
};
|
||||
|
||||
Button next = new Button(this);
|
||||
next.setText(">>");
|
||||
next.setOnClickListener(nextButtonListener);
|
||||
|
||||
// Previous button listener
|
||||
View.OnClickListener prevButtonListener = new View.OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
|
||||
currentPage--;
|
||||
if (currentPage < 0) {
|
||||
currentPage = pages.size() - 1;
|
||||
}
|
||||
setContentView(createView(context));
|
||||
|
||||
}
|
||||
};
|
||||
Button prev = new Button(this);
|
||||
prev.setText("<<");
|
||||
prev.setOnClickListener(prevButtonListener);
|
||||
|
||||
LinearLayout buttons = new LinearLayout(this);
|
||||
buttons.addView(prev, params);
|
||||
buttons.addView(next, params);
|
||||
|
||||
body.setBackgroundDrawable(this.getResources().getDrawable(R.drawable.background3));
|
||||
|
||||
SwipeLinearLayout main = new SwipeLinearLayout(this);
|
||||
main.setNext(nextButtonListener);
|
||||
main.setPrev(prevButtonListener);
|
||||
main.setOrientation(LinearLayout.VERTICAL);
|
||||
main.addView(body, params);
|
||||
|
||||
LinearLayout.LayoutParams paramButtons = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
paramButtons.gravity = Gravity.CENTER;
|
||||
|
||||
main.addView(buttons, paramButtons);
|
||||
return main;
|
||||
}
|
||||
|
||||
private View createEmptyView() {
|
||||
ImageView empty = new ImageView(this);
|
||||
empty.setBackgroundDrawable(getResources().getDrawable(R.drawable.empty));
|
||||
|
||||
TextView emptyText = new TextView(this);
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, 1);
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
|
||||
LinearLayout body = new LinearLayout(this);
|
||||
|
||||
body.setOrientation(LinearLayout.VERTICAL);
|
||||
body.addView(empty, params);
|
||||
|
||||
body.addView(emptyText, params);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
private View createViewItem(Bitmap image, String path, String title) {
|
||||
|
||||
final String assetPath = path;
|
||||
|
||||
ClipImageView clip = new ClipImageView(this);
|
||||
|
||||
clip.setImageBitmap(image);
|
||||
|
||||
// Set the onClick listener for each image
|
||||
clip.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(context, VideoPlayerView.class);
|
||||
intent.putExtra("com.widevine.demo.Path", assetPath);
|
||||
context.startActivity(intent);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
TextView text = new TextView(this);
|
||||
text.setText((title == null) ? path : title);
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, 1);
|
||||
params.gravity = Gravity.CENTER;
|
||||
LinearLayout body = new LinearLayout(this);
|
||||
|
||||
body.setOrientation(LinearLayout.VERTICAL);
|
||||
body.addView(clip, params);
|
||||
|
||||
body.addView(text, params);
|
||||
|
||||
return body;
|
||||
|
||||
}
|
||||
|
||||
private Bitmap getBitmapFromAssetItem(AssetItem assetItem) {
|
||||
Bitmap clipImage = null;
|
||||
String imageUrl = null;
|
||||
|
||||
if (assetItem.getImagePath() == null || assetItem.getImagePath().equals("")) {
|
||||
if (assetItem.getAssetPath().indexOf("http") == -1)
|
||||
clipImage = BitmapFactory.decodeResource(getResources(), R.drawable.download_clip);
|
||||
else
|
||||
clipImage = BitmapFactory.decodeResource(getResources(), R.drawable.streaming_clip);
|
||||
} else {
|
||||
InputStream bitmapStream = null;
|
||||
if (assetItem.getAssetPath().indexOf("http") != -1) {
|
||||
|
||||
imageUrl = assetItem.getImagePath();
|
||||
if (imageUrl != null) {
|
||||
ImageHandler imageHandler = new ImageHandler(imageUrl);
|
||||
imageHandler.start();
|
||||
try {
|
||||
imageHandler.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
clipImage = imageHandler.getBitmap();
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
bitmapStream = new FileInputStream(assetItem.getImagePath());
|
||||
} catch (FileNotFoundException e) {
|
||||
bitmapStream = null;
|
||||
}
|
||||
|
||||
clipImage = BitmapFactory.decodeStream(bitmapStream);
|
||||
}
|
||||
|
||||
if (clipImage == null) {
|
||||
clipImage = BitmapFactory.decodeResource(getResources(), R.drawable.streaming_clip);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return clipImage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
/**
|
||||
* Describes one asset in the list view
|
||||
*/
|
||||
public class AssetDescriptor {
|
||||
private String mThumbnail;
|
||||
private String mTitle;
|
||||
private String mDescription;
|
||||
private String mUri;
|
||||
private String mStatus;
|
||||
|
||||
public AssetDescriptor copy() {
|
||||
AssetDescriptor ad = new AssetDescriptor();
|
||||
ad.setTitle(mTitle);
|
||||
ad.setThumbnail(mThumbnail);
|
||||
ad.setDescription(mDescription);
|
||||
ad.setUri(mUri);
|
||||
return ad;
|
||||
}
|
||||
|
||||
public String getThumbnail() {
|
||||
return mThumbnail;
|
||||
}
|
||||
|
||||
public void setThumbnail(String thumbnail) {
|
||||
mThumbnail = thumbnail;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return mUri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
mUri = uri;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
mStatus = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
public class AssetItem {
|
||||
private String assetPath;
|
||||
private String imagePath;
|
||||
private String title;
|
||||
|
||||
public AssetItem() {
|
||||
assetPath = null;
|
||||
imagePath = null;
|
||||
title = null;
|
||||
}
|
||||
|
||||
public AssetItem(String assetPath, String imagePath, String title) {
|
||||
this.assetPath = assetPath;
|
||||
this.imagePath = imagePath;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAssetPath() {
|
||||
return assetPath;
|
||||
}
|
||||
|
||||
public String getImagePath() {
|
||||
return imagePath;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class AssetsPage {
|
||||
public static final int MAX_ITEMS = 6;
|
||||
|
||||
private ArrayList<AssetItem> assets;
|
||||
|
||||
public AssetsPage() {
|
||||
assets = new ArrayList<AssetItem>();
|
||||
}
|
||||
|
||||
public void addPage(String assetPath, String imagePath, String title) {
|
||||
assets.add(new AssetItem(assetPath, imagePath, title));
|
||||
}
|
||||
|
||||
public AssetItem getPage(int pageNumber) {
|
||||
return assets.get(pageNumber);
|
||||
}
|
||||
|
||||
public int getPageCount() {
|
||||
return assets.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import android.widget.ImageView;
|
||||
import android.view.MotionEvent;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public class ClipImageView extends ImageView {
|
||||
|
||||
private boolean touchedDown;
|
||||
private float touchX, touchY, radius;
|
||||
private boolean radiusInc;
|
||||
|
||||
private Bitmap selectCircle;
|
||||
|
||||
public ClipImageView(Context ctxt) {
|
||||
super(ctxt);
|
||||
|
||||
touchedDown = false;
|
||||
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inDither = true;
|
||||
selectCircle = BitmapFactory.decodeResource(getResources(), R.drawable.selection_circle,
|
||||
options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent e) {
|
||||
|
||||
if (e.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
touchX = e.getX();
|
||||
touchY = e.getY();
|
||||
radius = 60;
|
||||
radiusInc = false;
|
||||
touchedDown = true;
|
||||
|
||||
} else if (e.getAction() == MotionEvent.ACTION_UP) {
|
||||
touchedDown = false;
|
||||
|
||||
}
|
||||
// return true;
|
||||
return super.onTouchEvent(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (touchedDown) {
|
||||
canvas.drawBitmap(selectCircle, null, new Rect((int) (touchX - radius),
|
||||
(int) (touchY - radius), (int) (touchX + radius),
|
||||
(int) (touchY + radius)), null);
|
||||
if (radiusInc) {
|
||||
radius += 5;
|
||||
}
|
||||
else {
|
||||
radius -= 5;
|
||||
}
|
||||
if (radius >= 60 || radius <= 0) {
|
||||
radiusInc = !radiusInc;
|
||||
}
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.sax.Element;
|
||||
import android.sax.EndElementListener;
|
||||
import android.sax.EndTextElementListener;
|
||||
import android.sax.RootElement;
|
||||
import android.util.Xml;
|
||||
|
||||
/**
|
||||
* Parser for the XML configuration file that defines the assets available to
|
||||
* play
|
||||
*/
|
||||
public class ConfigXMLParser {
|
||||
|
||||
private URL mFeedUrl;
|
||||
private InputStream inputStream;
|
||||
|
||||
protected InputStream getInputStream() {
|
||||
try {
|
||||
if (inputStream != null)
|
||||
return inputStream;
|
||||
else
|
||||
return mFeedUrl.openConnection().getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigXMLParser(URL feedUrl) {
|
||||
mFeedUrl = feedUrl;
|
||||
}
|
||||
|
||||
public ConfigXMLParser(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public List<AssetDescriptor> parse() {
|
||||
final AssetDescriptor currentAssetDescriptor = new AssetDescriptor();
|
||||
RootElement root = new RootElement("widevine");
|
||||
final List<AssetDescriptor> assetDescriptors = new ArrayList<AssetDescriptor>();
|
||||
Element assetlist = root.getChild("asset-list");
|
||||
Element asset = assetlist.getChild("asset");
|
||||
asset.setEndElementListener(new EndElementListener() {
|
||||
public void end() {
|
||||
if (currentAssetDescriptor.getUri().indexOf("http") != -1
|
||||
&& (currentAssetDescriptor.getUri().indexOf(".wvm") != -1
|
||||
|| !currentAssetDescriptor.getUri().substring(currentAssetDescriptor
|
||||
.getUri().lastIndexOf("/")).contains("."))) {
|
||||
assetDescriptors.add(currentAssetDescriptor.copy());
|
||||
}
|
||||
}
|
||||
});
|
||||
asset.getChild("title").setEndTextElementListener(new EndTextElementListener() {
|
||||
public void end(String body) {
|
||||
currentAssetDescriptor.setTitle(body);
|
||||
}
|
||||
});
|
||||
asset.getChild("uri").setEndTextElementListener(new EndTextElementListener() {
|
||||
public void end(String body) {
|
||||
currentAssetDescriptor.setUri(body);
|
||||
}
|
||||
});
|
||||
asset.getChild("description").setEndTextElementListener(new EndTextElementListener() {
|
||||
public void end(String body) {
|
||||
currentAssetDescriptor.setDescription(body);
|
||||
}
|
||||
});
|
||||
asset.getChild("thumbnail").setEndTextElementListener(new EndTextElementListener() {
|
||||
public void end(String body) {
|
||||
currentAssetDescriptor.setThumbnail(body);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return assetDescriptors;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DownloadActivity extends AssetActivity {
|
||||
|
||||
protected boolean setUpAssetPages() {
|
||||
pages = new ArrayList<AssetsPage>();
|
||||
|
||||
File[] assets = getDownloadedClips();
|
||||
|
||||
if (assets != null && assets.length > 0) {
|
||||
for (int i = 0; i < assets.length;) {
|
||||
AssetsPage page = new AssetsPage();
|
||||
for (int j = 0; j < AssetsPage.MAX_ITEMS && i < assets.length; j++, i++) {
|
||||
page.addPage(assets[i].getAbsolutePath(), null, null);
|
||||
}
|
||||
pages.add(page);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private File[] getDownloadedClips() {
|
||||
|
||||
File file = new File("/sdcard/Widevine");
|
||||
|
||||
FilenameFilter filter = new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
File file = new File(dir.getAbsolutePath() + File.separator + name);
|
||||
if (!file.isDirectory()
|
||||
&& !name.equals("curl")
|
||||
&& (name.contains(".wvm") || name.contains(".mp4") || !name.contains(".")))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return file.listFiles(filter);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.VideoView;
|
||||
|
||||
public class FullScreenVideoView extends VideoView {
|
||||
|
||||
private boolean fullscreen;
|
||||
private int rLeft, rRight, rTop, rBottom, regularHeight, regularWidth;
|
||||
private int fullScreenWidth, fullScreenHeight;
|
||||
|
||||
public FullScreenVideoView(Context context) {
|
||||
super(context);
|
||||
fullscreen = false;
|
||||
regularHeight = 0;
|
||||
regularWidth = 0;
|
||||
rBottom = 0;
|
||||
rRight = 0;
|
||||
rTop = 0;
|
||||
rLeft = 0;
|
||||
fullScreenWidth = 1280;
|
||||
fullScreenHeight = 800;
|
||||
}
|
||||
|
||||
public void setFullScreenDimensions(int width, int height) {
|
||||
fullScreenWidth = width;
|
||||
fullScreenHeight = height;
|
||||
}
|
||||
|
||||
public void setFullScreen(boolean fullscreen) {
|
||||
this.fullscreen = fullscreen;
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public boolean getFullScreen() {
|
||||
return this.fullscreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (rLeft == 0 && rRight == 0 && rTop == 0 && rBottom == 0) {
|
||||
rBottom = bottom;
|
||||
rRight = right;
|
||||
rTop = top;
|
||||
rLeft = left;
|
||||
}
|
||||
if (fullscreen) {
|
||||
super.onLayout(true, left, top, fullScreenWidth, fullScreenHeight);
|
||||
} else {
|
||||
if (rLeft == 0 && rRight == 0 && rTop == 0 && rBottom == 0) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
} else {
|
||||
super.onLayout(changed, rLeft, rTop, rRight, rBottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (regularHeight == 0 && regularWidth == 0) {
|
||||
regularHeight = heightMeasureSpec;
|
||||
regularWidth = widthMeasureSpec;
|
||||
}
|
||||
if (fullscreen) {
|
||||
this.setMeasuredDimension(fullScreenWidth, fullScreenHeight);
|
||||
} else {
|
||||
if (regularHeight == 0 && regularWidth == 0) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
} else {
|
||||
super.onMeasure(regularWidth, regularHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
111
proprietary/samplePlayer/src/com/widevine/demo/HttpParser.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
|
||||
public class HttpParser extends Thread {
|
||||
|
||||
private ArrayList<AssetItem> assets;
|
||||
private String urlString;
|
||||
private String rootUrl;
|
||||
|
||||
public HttpParser(String urlString) {
|
||||
this.urlString = urlString;
|
||||
this.assets = new ArrayList<AssetItem>();
|
||||
this.rootUrl = this.urlString.substring(0, this.urlString.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
|
||||
DefaultHttpClient httpClient = new DefaultHttpClient();
|
||||
HttpGet request = new HttpGet(urlString);
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
|
||||
InputStream reader = response.getEntity().getContent();
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
int data = 0;
|
||||
do {
|
||||
data = reader.read();
|
||||
if (data == -1) {
|
||||
break;
|
||||
}
|
||||
buffer.append((char) data);
|
||||
|
||||
} while (true);
|
||||
|
||||
if (urlString.contains(".htm")) {
|
||||
parseHtml(buffer.toString());
|
||||
} else if (urlString.contains(".xml")) {
|
||||
parseXML(buffer.toString());
|
||||
}
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void parseXML(String xmlText) {
|
||||
ConfigXMLParser parser = new ConfigXMLParser(new ByteArrayInputStream(xmlText.getBytes()));
|
||||
|
||||
ArrayList<AssetDescriptor> descrs = (ArrayList<AssetDescriptor>) parser.parse();
|
||||
|
||||
for (int i = 0; i < descrs.size(); i++) {
|
||||
AssetDescriptor asset = descrs.get(i);
|
||||
String imagePath = asset.getThumbnail();
|
||||
if (!imagePath.contains("http")) {
|
||||
imagePath = rootUrl + imagePath;
|
||||
}
|
||||
assets.add(new AssetItem(asset.getUri(), asset.getThumbnail(), asset.getTitle()));
|
||||
}
|
||||
}
|
||||
|
||||
private void parseHtml(String htmlText) {
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
|
||||
while (true) {
|
||||
String assetPath = null;
|
||||
String title = null;
|
||||
String imagePath = null;
|
||||
start = htmlText.indexOf(":", start);
|
||||
if (start == -1) {
|
||||
break;
|
||||
} else {
|
||||
end = htmlText.indexOf("\"", start);
|
||||
assetPath = "http" + htmlText.substring(start, end);
|
||||
start = end + 1;
|
||||
start = htmlText.indexOf("\"", start) + 1;
|
||||
end = htmlText.indexOf("\"", start);
|
||||
imagePath = htmlText.substring(start, end);
|
||||
if (!imagePath.contains("http")) {
|
||||
imagePath = rootUrl + imagePath;
|
||||
}
|
||||
start = htmlText.indexOf("<p>", start) + "<p>".length();
|
||||
end = htmlText.indexOf("</p>", start);
|
||||
title = htmlText.substring(start, end);
|
||||
start = end + 1;
|
||||
assets.add(new AssetItem(assetPath, imagePath, title));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<AssetItem> getAssets() {
|
||||
return this.assets;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
public class ImageHandler extends Thread {
|
||||
|
||||
private boolean scale;
|
||||
private String imageUrl;
|
||||
private Bitmap clipImage = null;
|
||||
|
||||
public ImageHandler(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
this.clipImage = null;
|
||||
}
|
||||
|
||||
public void setScale(boolean scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
|
||||
DefaultHttpClient httpClient = new DefaultHttpClient();
|
||||
HttpGet request = new HttpGet(imageUrl);
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
|
||||
this.clipImage = BitmapFactory.decodeStream(response.getEntity().getContent());
|
||||
if (scale) {
|
||||
this.clipImage = Bitmap.createScaledBitmap(this.clipImage, 150, 200, false);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
this.clipImage = null;
|
||||
} catch (IOException e) {
|
||||
this.clipImage = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return this.clipImage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public class SettingsActivity extends Activity {
|
||||
// public static String CONTENT_PAGE = "/sdcard/Widevine/config.xml";
|
||||
public static String CONTENT_PAGE = "http://seawwws001.shibboleth.tv/android/oem.html";
|
||||
|
||||
private Context context;
|
||||
private Button updateButton;
|
||||
private EditText drmServer, portalName, deviceId, contentPage;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
context = this;
|
||||
|
||||
setContentView(R.layout.settings);
|
||||
|
||||
updateButton = (Button) findViewById(R.id.update_button);
|
||||
|
||||
View.OnClickListener clickListener = new View.OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
WidevineDrm.Settings.DRM_SERVER_URI = drmServer.getText().toString();
|
||||
WidevineDrm.Settings.DEVICE_ID = deviceId.getText().toString();
|
||||
WidevineDrm.Settings.PORTAL_NAME = portalName.getText().toString();
|
||||
SettingsActivity.CONTENT_PAGE = contentPage.getText().toString();
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage("DRM Settings Updated").setCancelable(false)
|
||||
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
}
|
||||
};
|
||||
|
||||
updateButton.setOnClickListener(clickListener);
|
||||
|
||||
drmServer = (EditText) findViewById(R.id.drm_server);
|
||||
drmServer.setText(WidevineDrm.Settings.DRM_SERVER_URI);
|
||||
|
||||
deviceId = (EditText) findViewById(R.id.device_id);
|
||||
deviceId.setText(WidevineDrm.Settings.DEVICE_ID);
|
||||
|
||||
portalName = (EditText) findViewById(R.id.portal_id);
|
||||
portalName.setText(WidevineDrm.Settings.PORTAL_NAME);
|
||||
|
||||
contentPage = (EditText) findViewById(R.id.content_page);
|
||||
contentPage.setText(SettingsActivity.CONTENT_PAGE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
public class StreamingActivity extends AssetActivity {
|
||||
private String contentPage;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
contentPage = SettingsActivity.CONTENT_PAGE;
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (!contentPage.equals(SettingsActivity.CONTENT_PAGE)) {
|
||||
contentPage = SettingsActivity.CONTENT_PAGE;
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean setUpAssetPages() {
|
||||
pages = new ArrayList<AssetsPage>();
|
||||
|
||||
if (contentPage.contains(".htm")) {
|
||||
ArrayList<AssetItem> assets = getStreamingClipsHttp();
|
||||
|
||||
if (assets == null || assets.size() == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < assets.size();) {
|
||||
AssetsPage page = new AssetsPage();
|
||||
for (int j = 0; j < AssetsPage.MAX_ITEMS && i < assets.size(); j++, i++) {
|
||||
page.addPage(assets.get(i).getAssetPath(), assets.get(i).getImagePath(), assets
|
||||
.get(i).getTitle());
|
||||
}
|
||||
pages.add(page);
|
||||
}
|
||||
} else {
|
||||
ArrayList<AssetDescriptor> assets = getStreamingClipsXml();
|
||||
|
||||
if (assets == null || assets.size() == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < assets.size();) {
|
||||
AssetsPage page = new AssetsPage();
|
||||
for (int j = 0; j < AssetsPage.MAX_ITEMS && i < assets.size(); j++, i++) {
|
||||
page.addPage(assets.get(i).getUri(), assets.get(i).getThumbnail(), assets
|
||||
.get(i).getTitle());
|
||||
}
|
||||
pages.add(page);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private ArrayList<AssetDescriptor> getStreamingClipsXml() {
|
||||
|
||||
try {
|
||||
File file = new File(contentPage);
|
||||
if (file.exists()) {
|
||||
ConfigXMLParser parser = new ConfigXMLParser(file.toURL());
|
||||
|
||||
ArrayList<AssetDescriptor> assets = (ArrayList<AssetDescriptor>) parser.parse();
|
||||
return assets;
|
||||
} else {
|
||||
return new ArrayList<AssetDescriptor>();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
return new ArrayList<AssetDescriptor>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ArrayList<AssetItem> getStreamingClipsHttp() {
|
||||
HttpParser parser = new HttpParser(contentPage);
|
||||
parser.start();
|
||||
try {
|
||||
parser.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return parser.getAssets();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
public class SwipeLinearLayout extends LinearLayout {
|
||||
private View.OnClickListener prev;
|
||||
private View.OnClickListener next;
|
||||
|
||||
float startX, startY, endX, endY;
|
||||
|
||||
public SwipeLinearLayout(Context c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public void setNext(View.OnClickListener next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public void setPrev(View.OnClickListener prev) {
|
||||
this.prev = prev;
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent e) {
|
||||
if (e.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
startX = e.getX();
|
||||
startY = e.getY();
|
||||
return true;
|
||||
} else if (e.getAction() == MotionEvent.ACTION_UP) {
|
||||
endX = e.getX();
|
||||
endY = e.getY();
|
||||
|
||||
if (Math.abs(startY - endY) < 75) {
|
||||
if ((startX - endX) > 200.0) {
|
||||
// go forward
|
||||
if (next != null) {
|
||||
next.onClick(null);
|
||||
}
|
||||
} else if ((startX - endX) < -200.0) {
|
||||
// go back
|
||||
if (prev != null) {
|
||||
prev.onClick(null);
|
||||
}
|
||||
}
|
||||
startX = startY = endX = endY = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.MediaController;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Button;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.content.Context;
|
||||
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.MediaPlayer.OnErrorListener;
|
||||
import android.media.MediaPlayer.OnCompletionListener;
|
||||
|
||||
public class VideoPlayerView extends Activity {
|
||||
private final static String EXIT_FULLSCREEN = "Exit Full Screen";
|
||||
private final static String FULLSCREEN = "Enter Full Screen";
|
||||
private final static String PLAY = "Play";
|
||||
private final static int REFRESH = 1;
|
||||
|
||||
private WidevineDrm drm;
|
||||
private FullScreenVideoView videoView;
|
||||
private String assetUri;
|
||||
private TextView logs;
|
||||
private ScrollView scrollView;
|
||||
private Context context;
|
||||
private ClipImageView bgImage;
|
||||
private Button playButton;
|
||||
private Button fullScreen;
|
||||
private Handler hRefresh;
|
||||
private View contentView;
|
||||
private LinearLayout main;
|
||||
private LinearLayout sidePanel;
|
||||
private boolean enteringFullScreen;
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
context = this;
|
||||
contentView = createView();
|
||||
setContentView(contentView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
if (videoView != null) {
|
||||
if (videoView.isPlaying()) {
|
||||
stopPlayback();
|
||||
}
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
private View createView() {
|
||||
enteringFullScreen = false;
|
||||
assetUri = this.getIntent().getStringExtra("com.widevine.demo.Path");
|
||||
|
||||
drm = new WidevineDrm(this);
|
||||
drm.logBuffer.append("Asset Uri: " + assetUri + "\n");
|
||||
drm.logBuffer.append("Drm Server: " + WidevineDrm.Settings.DRM_SERVER_URI + "\n");
|
||||
drm.logBuffer.append("Device Id: " + WidevineDrm.Settings.DEVICE_ID + "\n");
|
||||
drm.logBuffer.append("Portal Name: " + WidevineDrm.Settings.PORTAL_NAME + "\n");
|
||||
|
||||
// Set log update listener
|
||||
WidevineDrm.WidevineDrmLogEventListener drmLogListener =
|
||||
new WidevineDrm.WidevineDrmLogEventListener() {
|
||||
|
||||
public void logUpdated() {
|
||||
updateLogs();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
videoView = new FullScreenVideoView(this);
|
||||
|
||||
logs = new TextView(this);
|
||||
drm.setLogListener(drmLogListener);
|
||||
|
||||
scrollView = new ScrollView(this);
|
||||
scrollView.addView(logs);
|
||||
|
||||
// Set message handler for log events
|
||||
hRefresh = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case REFRESH:
|
||||
/* Refresh UI */
|
||||
logs.setText(drm.logBuffer.toString());
|
||||
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateLogs();
|
||||
|
||||
sidePanel = new LinearLayout(this);
|
||||
sidePanel.setOrientation(LinearLayout.VERTICAL);
|
||||
sidePanel.addView(scrollView, new LinearLayout.LayoutParams(300, 450));
|
||||
|
||||
LinearLayout.LayoutParams paramsSidePanel = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
paramsSidePanel.gravity = Gravity.CENTER;
|
||||
sidePanel.addView(createButtons(), paramsSidePanel);
|
||||
|
||||
FrameLayout playerFrame = new FrameLayout(this);
|
||||
playerFrame.addView(videoView, new FrameLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
|
||||
bgImage = new ClipImageView(this);
|
||||
bgImage.setBackgroundDrawable(getResources().getDrawable(R.drawable.play_shield));
|
||||
|
||||
bgImage.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
startPlayback();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
fullScreen = new Button(this);
|
||||
fullScreen.setText(FULLSCREEN);
|
||||
|
||||
fullScreen.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
int currentPosition = videoView.getCurrentPosition();
|
||||
videoView.setVisibility(View.INVISIBLE);
|
||||
if (fullScreen.getText().equals(FULLSCREEN)) {
|
||||
|
||||
videoView.setFullScreen(true);
|
||||
fullScreen.setText(EXIT_FULLSCREEN);
|
||||
enteringFullScreen = true;
|
||||
} else {
|
||||
videoView.setFullScreen(false);
|
||||
fullScreen.setText(FULLSCREEN);
|
||||
}
|
||||
videoView.setVisibility(View.VISIBLE);
|
||||
|
||||
stopPlayback();
|
||||
startPlayback();
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
videoView.seekTo(currentPosition);
|
||||
}
|
||||
});
|
||||
playerFrame.addView(fullScreen, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT));
|
||||
fullScreen.setVisibility(View.INVISIBLE);
|
||||
playerFrame.addView(bgImage, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
main = new LinearLayout(this);
|
||||
main.addView(playerFrame, new LinearLayout.LayoutParams(900,
|
||||
LinearLayout.LayoutParams.FILL_PARENT, 1));
|
||||
main.addView(sidePanel, new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.FILL_PARENT, 3));
|
||||
|
||||
return main;
|
||||
}
|
||||
|
||||
private void startPlayback() {
|
||||
playButton.setText(R.string.stop);
|
||||
|
||||
bgImage.setVisibility(View.GONE);
|
||||
|
||||
videoView.setVideoPath(assetUri);
|
||||
videoView.setMediaController(new MediaController(context));
|
||||
|
||||
videoView.setOnErrorListener(new OnErrorListener() {
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
String message = "Unknown error";
|
||||
switch (what) {
|
||||
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
|
||||
message = "Unable to play media";
|
||||
break;
|
||||
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
|
||||
message = "Server failed";
|
||||
break;
|
||||
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
|
||||
message = "Invalid media";
|
||||
break;
|
||||
}
|
||||
drm.logBuffer.append(message + "\n");
|
||||
updateLogs();
|
||||
bgImage.setVisibility(View.VISIBLE);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
videoView.setOnCompletionListener(new OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
stopPlayback();
|
||||
}
|
||||
});
|
||||
videoView.requestFocus();
|
||||
|
||||
videoView.start();
|
||||
|
||||
if (videoView.getFullScreen()) {
|
||||
sidePanel.setVisibility(View.GONE);
|
||||
} else {
|
||||
sidePanel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
fullScreen.setVisibility(View.VISIBLE);
|
||||
videoView.setFullScreenDimensions(contentView.getRight() - contentView.getLeft(),
|
||||
contentView.getBottom() - contentView.getTop());
|
||||
}
|
||||
|
||||
private void stopPlayback() {
|
||||
playButton.setText(R.string.play);
|
||||
videoView.stopPlayback();
|
||||
fullScreen.setVisibility(View.INVISIBLE);
|
||||
bgImage.setVisibility(View.VISIBLE);
|
||||
|
||||
if (videoView.getFullScreen() && !enteringFullScreen) {
|
||||
videoView.setVisibility(View.INVISIBLE);
|
||||
videoView.setFullScreen(false);
|
||||
videoView.setVisibility(View.VISIBLE);
|
||||
sidePanel.setVisibility(View.VISIBLE);
|
||||
fullScreen.setText(FULLSCREEN);
|
||||
}
|
||||
enteringFullScreen = false;
|
||||
|
||||
}
|
||||
|
||||
private View createButtons() {
|
||||
playButton = new Button(this);
|
||||
playButton.setText(R.string.play);
|
||||
|
||||
playButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
Button b = (Button) v;
|
||||
if (b.getText().equals(PLAY)) {
|
||||
startPlayback();
|
||||
} else {
|
||||
stopPlayback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Button rightsButton = new Button(this);
|
||||
rightsButton.setText(R.string.acquire_rights);
|
||||
|
||||
rightsButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
drm.acquireRights(assetUri);
|
||||
updateLogs();
|
||||
}
|
||||
});
|
||||
|
||||
Button removeButton = new Button(this);
|
||||
removeButton.setText(R.string.remove_rights);
|
||||
|
||||
removeButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
drm.removeRights(assetUri);
|
||||
updateLogs();
|
||||
}
|
||||
});
|
||||
|
||||
Button checkButton = new Button(this);
|
||||
checkButton.setText(R.string.show_rights);
|
||||
|
||||
checkButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
drm.showRights(assetUri);
|
||||
updateLogs();
|
||||
}
|
||||
});
|
||||
|
||||
Button checkConstraints = new Button(this);
|
||||
checkConstraints.setText(R.string.constraints);
|
||||
|
||||
checkConstraints.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
drm.getConstraints(assetUri);
|
||||
updateLogs();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.FILL_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, 1);
|
||||
params.setMargins(0, 0, 0, 5);
|
||||
LinearLayout buttonsLeft = new LinearLayout(this);
|
||||
|
||||
buttonsLeft.setOrientation(LinearLayout.VERTICAL);
|
||||
buttonsLeft.addView(playButton, params);
|
||||
buttonsLeft.addView(rightsButton, params);
|
||||
buttonsLeft.addView(checkConstraints, params);
|
||||
|
||||
LinearLayout buttonsRight = new LinearLayout(this);
|
||||
buttonsRight.setOrientation(LinearLayout.VERTICAL);
|
||||
buttonsRight.addView(checkButton, params);
|
||||
buttonsRight.addView(removeButton, params);
|
||||
|
||||
LinearLayout.LayoutParams paramsSides = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.FILL_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, 1);
|
||||
paramsSides.gravity = Gravity.BOTTOM;
|
||||
|
||||
LinearLayout buttons = new LinearLayout(this);
|
||||
buttons.addView(buttonsLeft, paramsSides);
|
||||
buttons.addView(buttonsRight, paramsSides);
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
private void updateLogs() {
|
||||
hRefresh.sendEmptyMessage(REFRESH);
|
||||
}
|
||||
}
|
||||
252
proprietary/samplePlayer/src/com/widevine/demo/WidevineDrm.java
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import java.util.EventListener;
|
||||
//import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
|
||||
import android.drm.DrmErrorEvent;
|
||||
import android.drm.DrmEvent;
|
||||
import android.drm.DrmInfoEvent;
|
||||
import android.drm.DrmInfoRequest;
|
||||
import android.drm.DrmManagerClient;
|
||||
import android.drm.DrmStore;
|
||||
|
||||
public class WidevineDrm {
|
||||
|
||||
interface WidevineDrmLogEventListener extends EventListener {
|
||||
public void logUpdated();
|
||||
}
|
||||
|
||||
private WidevineDrmLogEventListener logEventListener;
|
||||
|
||||
public StringBuffer logBuffer = new StringBuffer();
|
||||
|
||||
/**
|
||||
* Drm Manager Configuration Methods
|
||||
*/
|
||||
|
||||
public static class Settings {
|
||||
public static String WIDEVINE_MIME_TYPE = "video/wvm";
|
||||
public static String DRM_SERVER_URI = "https://wstfcps005.shibboleth.tv/widevine/cypherpc/cgi-bin/GetEMMs.cgi";
|
||||
public static String DEVICE_ID = "device12345"; // use a unique device ID
|
||||
public static String PORTAL_NAME = "OEM";
|
||||
|
||||
// test with a sizeable block of user data...
|
||||
public static String USER_DATA = "01234567890123456789012345678901234567890123456789"
|
||||
+ "01234567890123456789012345678901234567890123456789"
|
||||
+ "01234567890123456789012345678901234567890123456789"
|
||||
+ "01234567890123456789012345678901234567890123456789"
|
||||
+ "01234567890123456789012345678901234567890123456789"
|
||||
+ "01234567890123456789012345678901234567890123456789";
|
||||
};
|
||||
|
||||
private DrmManagerClient mDrmManager;
|
||||
|
||||
// private Context mContext;
|
||||
|
||||
public WidevineDrm(Context context) {
|
||||
|
||||
// mContext = context;
|
||||
mDrmManager = new DrmManagerClient(context);
|
||||
|
||||
mDrmManager.setOnInfoListener(new DrmManagerClient.OnInfoListener() {
|
||||
// @Override
|
||||
public void onInfo(DrmManagerClient client, DrmInfoEvent event) {
|
||||
if (event.getType() == DrmInfoEvent.TYPE_RIGHTS_INSTALLED) {
|
||||
logMessage("Rights installed\n");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mDrmManager.setOnEventListener(new DrmManagerClient.OnEventListener() {
|
||||
|
||||
public void onEvent(DrmManagerClient client, DrmEvent event) {
|
||||
switch (event.getType()) {
|
||||
case DrmEvent.TYPE_DRM_INFO_PROCESSED:
|
||||
logMessage("Info Processed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mDrmManager.setOnErrorListener(new DrmManagerClient.OnErrorListener() {
|
||||
public void onError(DrmManagerClient client, DrmErrorEvent event) {
|
||||
switch (event.getType()) {
|
||||
case DrmErrorEvent.TYPE_ALL_RIGHTS_REMOVED:
|
||||
logMessage("Remove All Rights failed\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_DRM_INFO_PROCESSED:
|
||||
logMessage("Info Processed failed\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_NO_INTERNET_CONNECTION:
|
||||
logMessage("No Internet Connection\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_NOT_SUPPORTED:
|
||||
logMessage("Not Supported\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_OUT_OF_MEMORY:
|
||||
logMessage("Out of Memory\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_PROCESS_DRM_INFO_FAILED:
|
||||
logMessage("Process DRM Info failed\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_REMOVE_ALL_RIGHTS_FAILED:
|
||||
logMessage("Remove all rights\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_RIGHTS_NOT_INSTALLED:
|
||||
logMessage("Rights not installed\n");
|
||||
break;
|
||||
case DrmErrorEvent.TYPE_RIGHTS_RENEWAL_NOT_ALLOWED:
|
||||
logMessage("Rights renewal not allowed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DrmInfoRequest getDrmInfoRequest(String assetUri) {
|
||||
DrmInfoRequest rightsAcquisitionInfo;
|
||||
rightsAcquisitionInfo = new DrmInfoRequest(DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO,
|
||||
Settings.WIDEVINE_MIME_TYPE);
|
||||
|
||||
rightsAcquisitionInfo.put("WVDRMServerKey", Settings.DRM_SERVER_URI);
|
||||
rightsAcquisitionInfo.put("WVAssetURIKey", assetUri);
|
||||
rightsAcquisitionInfo.put("WVDeviceIDKey", Settings.DEVICE_ID);
|
||||
rightsAcquisitionInfo.put("WVPortalKey", Settings.PORTAL_NAME);
|
||||
rightsAcquisitionInfo.put("WVCAUserDataKey", Settings.USER_DATA);
|
||||
return rightsAcquisitionInfo;
|
||||
}
|
||||
|
||||
public int acquireRights(String assetUri) {
|
||||
|
||||
int rights = mDrmManager.acquireRights(getDrmInfoRequest(assetUri));
|
||||
logMessage("acquireRights = " + rights + "\n");
|
||||
|
||||
return rights;
|
||||
}
|
||||
|
||||
public int checkRightsStatus(String assetUri) {
|
||||
|
||||
// Need to use acquireDrmInfo prior to calling checkRightsStatus
|
||||
mDrmManager.acquireDrmInfo(getDrmInfoRequest(assetUri));
|
||||
int status = mDrmManager.checkRightsStatus(assetUri);
|
||||
logMessage("checkRightsStatus = " + status + "\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
public void getConstraints(String assetUri) {
|
||||
|
||||
// Need to use acquireDrmInfo prior to calling checkRightsStatus
|
||||
mDrmManager.acquireDrmInfo(getDrmInfoRequest(assetUri));
|
||||
ContentValues values = mDrmManager.getConstraints(assetUri, DrmStore.Action.PLAY);
|
||||
logContentValues(values, "No Contraints");
|
||||
}
|
||||
|
||||
public void showRights(String assetUri) {
|
||||
logMessage("showRights\n");
|
||||
|
||||
// Need to use acquireDrmInfo prior to calling getConstraints
|
||||
mDrmManager.acquireDrmInfo(getDrmInfoRequest(assetUri));
|
||||
|
||||
ContentValues values = mDrmManager.getConstraints(assetUri, DrmStore.Action.PLAY);
|
||||
logContentValues(values, "No Rights");
|
||||
|
||||
}
|
||||
|
||||
private void logContentValues(ContentValues values, String defaultMessage) {
|
||||
if (values != null) {
|
||||
|
||||
Set<String> keys = values.keySet();
|
||||
for (String key : keys) {
|
||||
if (key.toLowerCase().contains("time")) {
|
||||
logMessage(key + " = " + SecondsToDHMS(values.getAsLong(key)) + "\n");
|
||||
} else if (key.toLowerCase().contains("licensetype")) {
|
||||
logMessage(key + " = " + licenseType(values.getAsInteger(key)) + "\n");
|
||||
} else if (key.toLowerCase().contains("licensedresolution")) {
|
||||
logMessage(key + " = " + licenseResolution(values.getAsInteger(key)) + "\n");
|
||||
} else {
|
||||
logMessage(key + " = " + values.get(key) + "\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logMessage(defaultMessage + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static final long seconds_per_minute = 60;
|
||||
private static final long seconds_per_hour = 60 * seconds_per_minute;
|
||||
private static final long seconds_per_day = 24 * seconds_per_hour;
|
||||
|
||||
private String SecondsToDHMS(long seconds) {
|
||||
int days = (int) (seconds / seconds_per_day);
|
||||
seconds -= days * seconds_per_day;
|
||||
int hours = (int) (seconds / seconds_per_hour);
|
||||
seconds -= hours * seconds_per_hour;
|
||||
int minutes = (int) (seconds / seconds_per_minute);
|
||||
seconds -= minutes * seconds_per_minute;
|
||||
return Integer.toString(days) + "d " + Integer.toString(hours) + "h "
|
||||
+ Integer.toString(minutes) + "m " + Long.toString(seconds)
|
||||
+ "s";
|
||||
}
|
||||
|
||||
private String licenseType(int code) {
|
||||
switch (code) {
|
||||
case 1:
|
||||
return "Streaming";
|
||||
case 2:
|
||||
return "Offline";
|
||||
case 3:
|
||||
return "Both";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private String licenseResolution(int code) {
|
||||
switch (code) {
|
||||
case 1:
|
||||
return "SD only";
|
||||
case 2:
|
||||
return "HD or SD content";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public int removeRights(String assetUri) {
|
||||
|
||||
// Need to use acquireDrmInfo prior to calling removeRights
|
||||
mDrmManager.acquireDrmInfo(getDrmInfoRequest(assetUri));
|
||||
int removeStatus = mDrmManager.removeRights(assetUri);
|
||||
logMessage("removeRights = " + removeStatus + "\n");
|
||||
|
||||
return removeStatus;
|
||||
}
|
||||
|
||||
public int removeAllRights() {
|
||||
int removeAllStatus = mDrmManager.removeAllRights();
|
||||
logMessage("removeAllRights = " + removeAllStatus + "\n");
|
||||
return removeAllStatus;
|
||||
}
|
||||
|
||||
public void setLogListener(WidevineDrmLogEventListener logEventListener) {
|
||||
this.logEventListener = logEventListener;
|
||||
}
|
||||
|
||||
private void logMessage(String message) {
|
||||
logBuffer.append(message);
|
||||
|
||||
if (logEventListener != null) {
|
||||
logEventListener.logUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* (c)Copyright 2011 Widevine Technologies, Inc
|
||||
*/
|
||||
|
||||
package com.widevine.demo;
|
||||
|
||||
import android.app.TabActivity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TabHost;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
public class WidevineSamplePlayer extends TabActivity {
|
||||
|
||||
public static final String PREFS_NAME = "DrmPrefs";
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
|
||||
WidevineDrm.Settings.DRM_SERVER_URI = settings.getString("drmServer",
|
||||
WidevineDrm.Settings.DRM_SERVER_URI);
|
||||
WidevineDrm.Settings.DEVICE_ID = settings.getString("deviceId",
|
||||
WidevineDrm.Settings.DEVICE_ID);
|
||||
WidevineDrm.Settings.PORTAL_NAME = settings.getString("portalId",
|
||||
WidevineDrm.Settings.PORTAL_NAME);
|
||||
SettingsActivity.CONTENT_PAGE = settings.getString("contentPage",
|
||||
SettingsActivity.CONTENT_PAGE);
|
||||
|
||||
setContentView(R.layout.main);
|
||||
|
||||
TabHost tab = getTabHost();
|
||||
|
||||
// Setup Streaming tab
|
||||
TabHost.TabSpec streamingTab = tab.newTabSpec("Streaming");
|
||||
|
||||
streamingTab.setIndicator("Streaming");
|
||||
|
||||
Intent streamingIntent = new Intent(this, StreamingActivity.class);
|
||||
streamingTab.setContent(streamingIntent);
|
||||
|
||||
tab.addTab(streamingTab);
|
||||
|
||||
// Setup Down load tab
|
||||
TabHost.TabSpec downloadTab = tab.newTabSpec("Downloads");
|
||||
|
||||
downloadTab.setIndicator("Downloads");
|
||||
|
||||
Intent downloadIntent = new Intent(this, DownloadActivity.class);
|
||||
downloadTab.setContent(downloadIntent);
|
||||
|
||||
tab.addTab(downloadTab);
|
||||
|
||||
// Setup Settings tab
|
||||
TabHost.TabSpec settingsTab = tab.newTabSpec("Settings");
|
||||
|
||||
settingsTab.setIndicator("Settings");
|
||||
|
||||
Intent settingsIntent = new Intent(this, SettingsActivity.class);
|
||||
settingsTab.setContent(settingsIntent);
|
||||
|
||||
tab.addTab(settingsTab);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// We need an Editor object to make preference changes.
|
||||
// All objects are from android.context.Context
|
||||
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
|
||||
|
||||
SharedPreferences.Editor editor = settings.edit();
|
||||
editor.putString("drmServer", WidevineDrm.Settings.DRM_SERVER_URI);
|
||||
editor.putString("deviceId", WidevineDrm.Settings.DEVICE_ID);
|
||||
editor.putString("portalId", WidevineDrm.Settings.PORTAL_NAME);
|
||||
editor.putString("contentPage", SettingsActivity.CONTENT_PAGE);
|
||||
// Commit the edits!
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
}
|
||||