這里以Exoplayer 2.5.4為例告私。
源碼里面我們主要關(guān)注這兩個(gè)java文件:
SampleChooserActivity
PlayerActivity
SampleChooserActivity
界面我們可以選擇流播放,PlayerActivity
界面播放流囚巴。
然而選擇不同的流, 有不同的播放, 但是播放界面都共用一個(gè)activity
彤叉, 是因?yàn)槊看吸c(diǎn)擊播放的時(shí)候會(huì)傳遞不同的參數(shù)庶柿。
public Intent buildIntent(Context context) {
return super.buildIntent(context)
.setData(Uri.parse(uri))
.putExtra(PlayerActivity.EXTENSION_EXTRA, extension)
.putExtra(PlayerActivity.AD_TAG_URI_EXTRA, adTagUri)
.setAction(PlayerActivity.ACTION_VIEW);
}
通過(guò)這個(gè), SampleChooserActivity
可以把流地址秽浇, 流后綴浮庐, 廣告地址
等等添加到Intent
來(lái)傳遞到PlayerActivity
播放界面, 而后PlayerActivity
對(duì)數(shù)據(jù)接收兼呵。
例如對(duì)格式的接收:
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid"
if (intent.getExtras().getString(DRM_SCHEME_UUID_EXTRA) != null) {
switch (intent.getExtras().getString(DRM_SCHEME_UUID_EXTRA)) {
case "widevine":
drmSchemeUuid = UUID.fromString(String.valueOf(C.WIDEVINE_UUID));
break;
case "playready":
drmSchemeUuid = UUID.fromString(String.valueOf(C.PLAYREADY_UUID));
break;
case "cenc":
drmSchemeUuid = UUID.fromString(String.valueOf(C.PLAYREADY_UUID));
break;
default:
Log.w(TAG, "Unsupported drm style!!!");
}
參數(shù)的傳遞兔辅, 無(wú)論是通過(guò)app直接啟動(dòng)下一個(gè)activity, 還是通過(guò)am start
击喂, 都是以鍵值對(duì)來(lái)傳遞的维苔。
public static final String EXTENSION_EXTRA = "extension";
intent.putExtra(PlayerActivity.EXTENSION_EXTRA, extension);
am start -W -a com.google.android.exoplayer.demo.action.VIEW -c android.intent.category.DEFAULT \
...
-e extension "mpd" \
"com.google.android.exoplayer2.demo/com.google.android.exoplayer2.demo.PlayerActivity"
PlayerActivity
會(huì)對(duì)不同的參數(shù)進(jìn)行解析, 實(shí)現(xiàn)流的播放懂昂。
從源碼里面的AndroidManifest
看:
<activity android:name="com.google.android.exoplayer2.demo.PlayerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:launchMode="singleTop"
android:label="@string/application_name"
android:theme="@style/PlayerTheme">
<intent-filter>
<action android:name="com.google.android.exoplayer.demo.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="content"/>
<data android:scheme="asset"/>
<data android:scheme="file"/>
</intent-filter>
<intent-filter>
<action android:name="com.google.android.exoplayer.demo.action.VIEW_LIST"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
PlayerActivity
會(huì)接受兩種不同的intent
:
<action android:name="com.google.android.exoplayer.demo.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
和
<action android:name="com.google.android.exoplayer.demo.action.VIEW_LIST"/>
<category android:name="android.intent.category.DEFAULT"/>
可以簡(jiǎn)單的認(rèn)為介时,前者是播放單個(gè)流的intent, 后者是播放多個(gè)混合流的intent凌彬。
如果我們以am start
在串口敲命令沸柔,可以有一下兩種情況:
am start -W -a com.google.android.exoplayer.demo.action.VIEW -c android.intent.category.DEFAULT \
-e link "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd" \
-e drm_scheme_uuid "widevine" \
-e drm_license_url "https://proxy.uat.widevine.com/proxy?provider=widevine_test" \
-e extension "mpd" \
"com.google.android.exoplayer2.demo/com.google.android.exoplayer2.demo.PlayerActivity"
am start -W -a com.google.android.exoplayer.demo.action.VIEW_LIST -c android.intent.category.DEFAULT \
--esa link "https://html5demos.com/assets/dizzy.mp4"\,\
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_sd.mpd"\,\
"https://html5demos.com/assets/dizzy.mp4"\,\
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_sd.mpd"\,\
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_sd.mpd" \
-e drm_scheme_uuid "widevine" \
-e drm_license_url "https://proxy.uat.widevine.com/proxy?provider=widevine_test" \
"com.google.android.exoplayer2.demo/com.google.android.exoplayer2.demo.PlayerActivity"
其中, 在串口輸入am
有以下提示:
<INTENT> specifications include these flags and arguments:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--efal <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]
(mutiple extras passed as List<Float>)
[--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
(mutiple extras passed as String[]; to embed a comma into a string,
escape it using "\,")
[--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
(mutiple extras passed as List<String>; to embed a comma into a string,
escape it using "\,")
[<URI> | <PACKAGE> | <COMPONENT>]
其中鍵值都是以String
傳入的, 要加上""
來(lái)識(shí)別铲敛。
流的相應(yīng)信息褐澎,在此例中,都是保存在media.exolist.json
文件中伐蒋, 例如:
{
"name": "WV: Secure SD (cbc1,MP4,H264)",
"uri": "https://storage.googleapis.com/wvmedia/cbc1/h264/tears/tears_aes_cbc1_sd.mpd",
"drm_scheme": "widevine",
"drm_license_url": "https://proxy.uat.widevine.com/proxy?provider=widevine_test"
}
但是局限也很多:
- 如果我們需要啟動(dòng)的
activity
不需要傳入?yún)?shù)工三,那很簡(jiǎn)單,知道activity
的名字就行先鱼,找源碼俭正,或者串口輸入
logcat | grep cmp
就可以找到相應(yīng)的activity
.
- 如果我們需要啟動(dòng)的
activity
需要傳入?yún)?shù), 那我們就只能從源碼入手了焙畔。
此例掸读,代碼中我加入了判斷:
public static final String STREAM_URL = "link";
if (intent.getExtras().getString(STREAM_URL) != null
|| intent.getStringArrayExtra(STREAM_URL) != null) {
//Run exoplayer from command line
Log.i(TAG, "Run exoplayer from command line");
...
} else {
//Run exoplayer from internal app
Log.i(TAG, "Run exoplayer from internal app");
}
“l(fā)ink”
這個(gè)鍵名是串口輸入指令時(shí)獨(dú)有的, 在app內(nèi)部啟動(dòng)這個(gè)PlayerActivity
不會(huì)輸入這個(gè)參數(shù)宏多。
這樣的話儿惫,安裝上此代碼編譯出的apk,無(wú)論是內(nèi)部啟動(dòng)播放流伸但,還是外部指令播放流姥闪,不會(huì)有沖突了。