摘要:為了給用戶帶來多媒體方面的體驗福利,一刻也不能停,現(xiàn)在要提升主要視頻應(yīng)用全屏播放的觀看體驗。
為了給用戶帶來多媒體方面的體驗福利,一刻也不能停,現(xiàn)在要提升主要視頻應(yīng)用全屏播放的觀看體驗。
逐個分析突破
這些視頻應(yīng)用基本上都是第三方的比如騰訊視頻,優(yōu)酷,愛奇藝等,全部由第三方開發(fā)商實現(xiàn),不受控制,需要從系統(tǒng)入手,對播放比較熟悉的話首先想到的是這些播放器會使用到一些系統(tǒng)控件進行播放,顯示等。比如MediaPlayer,MediaCodec,SurfaceView,TextureView等,MediaPlayer第三方很少用基本都用自己的框架,MediaCodec只有在硬解碼的時候才會用,SurfaceView或TextureView顯示控件基本都會用,很少能繞過去,從這兩個view入手,基本可以hack住想要的視頻應(yīng)用,而且雖然android有很多視頻顯示的控件,但基本上都是繼承自這兩個view。
通過這兩個控件就可以hack到應(yīng)用里了。
首先定義下什么是全屏播放呢,一定是橫屏嗎,像騰訊,優(yōu)酷等的電視劇電影綜藝等,不一定,比如快手,抖音一類的短視頻很多都是豎屏的全屏。
其次我們可以從SurfaceView和TextureVIew里拿到Surface的大小,也就是視頻區(qū)域的寬高。
這樣我們通過一個簡單的算法就可以判斷是否是全屏了。
video height > screen height || video width > screen height
通過1,2操作后所有的視頻應(yīng)用在跑到相應(yīng)邏輯后都會使能體驗效果,比如在系統(tǒng)設(shè)置里有一些user guide視頻的播放,比如多任務(wù)欄里一些動畫的播放等,這些都不是我們想要的,也會給用戶帶來困惑造成不確定感。
沒有別的辦法只能通過名單來控制了,由于hack在app的java層,可以很容易的得到當前進程的包名,所以方案是通過包名過濾特定的名單。
比如。
//video apps
"com.tencent.qqlive.player.meizu","com.youku.phone.player.meizu", "com.meizu.media.video", "com.qiyi.video","tv.pps.mobile", "com.tencent.qqlive", "com.youku.phone","com.letv.android.client", "com.pplive.androidphone", "com.storm.smart","com.funshion.video.mobile", "com.cmcc.cmvideo", "com.mobile.videonews.li.video","com.sohu.sohuvideo", "com.baidu.video", “com.hunantv.imgo.activity",“tv.danmaku.bili",
//short videos
"com.flyme.videoclips", "com.smile.gifmaker", "com.ss.android.ugc.aweme","com.ss.android.ugc.live", "com.ss.android.article.video", "com.hupu.games","com.kuaiest.video", “com.tencent.weishi”,
//live videos
"com.duowan.mobile", "air.tv.douyu.android", "com.duowan.kiwi","com.panda.videoliveplatform", "com.huajiao", “com.tencent.now"
那名單做成靜態(tài)的還是在線的比較好?如何條件允許的話做成在線的當然最好。原理比較簡單把這個配置文件txt也好jason也好csv也好放在你的域名的某個目錄下,通過http或https下載就可以了。
具體到這里最好采用jason或者csv的格式,或者其他比較好操作的格式,方便管理。
比如
Jason:
{“bussiness":{"bussiness1":{"package_name":"["com.meizu","com.tencent"]"}}}
Csv:
Name1,name2,name3,name4,name5,name6,…
然后配置你的服務(wù)就可以了,需要更新的時候刷新下cdn。
這里有個比較特殊的地方,在終端如何去管理這個名單,由于下載更新比較耗時而且為了省時且不頻繁訪問服務(wù)器需要在本地管理備份,但是hack到別人的應(yīng)用里,所以不能在hack的代碼里處理,這個時候需要一個service,而且是system service,它是一個多帶帶的進程開機運行,用來管理一些唯一的資源,比如這個白名單的下載更新本地管理,效果模式的管理等等。
然后在hack里實現(xiàn)client與之通信,具體如何實現(xiàn)一個system service這里不表,后邊由于生命周期管理的需要也會需要這個service的,后邊再討論。
service取名VideoService,有點像Android AudioService的意思它是用來管理audio相關(guān)邏輯的可以通過AudioManager訪問,android沒有VideoService,這里添加VideoService后也可以擴展到其他video相關(guān)邏輯的場景,同理設(shè)計了可以通過VideoManager訪問的機制。
說的直白一點,需要效果的時候一定要有效果,不需要的時候千萬不能有效果。這里就涉及到用戶的交互了。
在介紹體驗效果的生命周期之前,是不是有個疑問,效果的打開關(guān)閉時在哪里做的,是怎么做的?
打開關(guān)閉時在SurfaceView和TextureView里做的,利用了它們的生命周期。
SurfaceView的生命周期, surfaceCreated, surfaceChanged, surfaceDestroyed
TextureView的生命周期,onSurfaceTextureAvaliable, onSurfaceTextureSizeChanged, onSurfaceTextureDestroyed, onSurfaceTextureUpdated
通過view生命周期的創(chuàng)建,更新,銷毀以及包含的寬高信息,來做到相應(yīng)的打開,關(guān)閉效果。
比如SurfaceView,surfaceCreated的時候,如果判斷是全屏,就打開它,用戶從全屏切換到了小窗口觸發(fā)了surfaceChanged,判斷是否全屏,不是就關(guān)閉它,或者用戶退出視頻觸發(fā)了surfaceDestroyed,就關(guān)閉它。
這兩個view的生命周期和用戶場景交互式密切相關(guān)的,正是由于這種機制,實現(xiàn)了體驗效果的生命周期的管理,除了剛才說的全屏/小窗口切換,視頻退出場景,還有幾種比較典型的場景介紹下。以surfaceview為例
(1)視頻在全屏幕狀態(tài),直接退到桌面;然后再點擊app進入全屏
觸發(fā)surfaceDestroyed,關(guān)閉效果;觸發(fā)surfaceCreated, surfaceChanged,判斷是否全屏,是打開效果
(2)調(diào)出多任務(wù)欄
觸發(fā)surfaceDestroyed,關(guān)閉效果
(3)在設(shè)置里殺死視頻
如果要進入的設(shè)置里去殺死視頻,需要先回到桌面進入設(shè)置或通過多任務(wù)進入設(shè)置,無論回到桌面還是進入多任務(wù),都會觸發(fā)surfaceDestroyed關(guān)閉效果,所以在設(shè)置里殺死視頻,體驗效果是關(guān)閉狀態(tài)。
(4)在多任務(wù)里殺死視頻
同理,進入多任務(wù),會觸發(fā)surfaceDestroyed關(guān)閉效果,所以在多任務(wù)殺死視頻,體驗效果是關(guān)閉狀態(tài)。
(5)視頻進入后臺后,被一些省電或內(nèi)存管理機制殺掉
同理,視頻先進入后臺,會觸發(fā)surfaceDestroyed關(guān)閉效果,所以視頻進入后臺后,被一些省電或內(nèi)存管理機制殺掉,體驗效果是關(guān)閉狀態(tài)。
(6)正在全屏播放時,視頻崩潰或用被kill
體驗效果不能正常關(guān)閉,因為這個時候之前的生命周期不能正常走到。
需要為這種情況多帶帶設(shè)計一種機制,本身設(shè)計是c/s結(jié)構(gòu)的,所以很容易想到利用binder die來監(jiān)聽client die。不同的是根據(jù)binder die的規(guī)則,視頻app也要作為一個binder的service。
在VideoManager里實現(xiàn),然后VideoManager運行在視頻app的進程。
private final Binder mICallback = new Binder();
然后通過binder調(diào)用將這個mICallback對象傳到VideoService,在VideoService里實現(xiàn)IBinder.DeathRecipient
mICallback.linkToDeath(this, 0)
當die發(fā)生的時候binderDied()回調(diào)會被執(zhí)行,可以在這個回調(diào)里關(guān)閉效果,完成這種情況下生命周期的設(shè)計。
這里也涉及到用戶的交互,怎么理解呢?可以看兩個比較典型的場景
(1)瀏覽短視頻的時候,比如抖音,從第一個開始快速滑動到第n個,這個中間可能發(fā)生了很多次打開/關(guān)閉效果,在很短的時間內(nèi),不停地切換效果會造成用戶視覺上的體驗不是很好
(2)另外一種不停地切換效果的情況是,頻繁全屏/小窗切換
這種快速切換帶來的頻繁打開/關(guān)閉應(yīng)該盡量避免。
所以在VideoService里設(shè)計了一個worker thread來專門串行處理各個client發(fā)過來請求,如果關(guān)閉打開關(guān)閉在很短的時間內(nèi)發(fā)生,可以選擇忽略。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/11069.html
摘要:可以支持多種視頻播放類型,比如,原生封裝視頻播放器,還有基于封裝的播放器。并且還支持刪除視頻播放位置狀態(tài)。拓展功能產(chǎn)品需求類似優(yōu)酷,愛奇藝視頻播放器部分邏輯。 目錄介紹 1.關(guān)于此視頻封裝庫介紹 1.1 能夠滿足那些業(yè)務(wù)需求 1.2 對比同類型的庫有哪些優(yōu)勢 2.關(guān)于使用方法說明 2.1 關(guān)于gradle引用說明 2.2 添加布局 2.3 最簡單的視頻播放器參數(shù)設(shè)定 2.4 注意的問...
閱讀 2561·2023-04-25 20:50
閱讀 3904·2023-04-25 18:45
閱讀 2192·2021-11-17 17:00
閱讀 3304·2021-10-08 10:05
閱讀 3048·2019-08-30 15:55
閱讀 3475·2019-08-30 15:44
閱讀 2339·2019-08-29 13:51
閱讀 1088·2019-08-29 12:47