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