項(xiàng)目開發(fā)使用框架多多少少會(huì)遇到各種棘手問題,但是并不是給你一個(gè)框架啥的你放進(jìn)去就能用,一般簡(jiǎn)單的操作很容易解決,當(dāng)設(shè)計(jì)到自己開發(fā)的東西比較老,復(fù)雜;而且你又想用這些新技術(shù),那么你就的對(duì)它各種處理使得與你的項(xiàng)目兼容才行 ;但是如果你是大牛的話完全可以忽略這種做法,完全可以自己封裝一個(gè)視頻處理框架##
雖然有很多人在用JCVideoPlayer做視頻播放,也有很多人在寫博客,每個(gè)人都會(huì)遇到相同或者不同的問題需要解決,我遇到的問題我總會(huì)想方設(shè)法把它記錄下來(lái),不希望自己走過的坑再走第二遍,也希望與我遇見同樣問題的人能夠快速的脫離苦海;其次也是希望自己能多研究這方面的東西,向?yàn)橹袊?guó)互聯(lián)網(wǎng)做出貢獻(xiàn)的前輩致敬;雖然自己現(xiàn)在還在連菜鳥都算不上,但是希望自己以后更加努力學(xué)習(xí)也能寫出一些類似的框架。
首先既然我在這里寫到了我們還是來(lái)簡(jiǎn)單看看節(jié)操videoplayer的簡(jiǎn)單用法:
第一步:
第一種方式:
可以通過添加jar包
這種方式的話如果你不希望在他的基礎(chǔ)上采用二次開發(fā)的最后的選擇方法,用起來(lái)比較簡(jiǎn)單,自己寫入的時(shí)候變可以考慮他的兼容性,在此作者采用了第二種方式
這種方式的是通過導(dǎo)入model的形式進(jìn)行添加,添加成功以后既可以在源碼的基礎(chǔ)上進(jìn)行二次開發(fā)
第二步:
在用到layout的xml文件夾下面添加類似videoview這種的控件如下圖,將它替換即可
第三步:
在用到節(jié)操player的控件的地方設(shè)置他的uri,縮略圖,標(biāo)題等,在這里節(jié)操videoplayer給我們提供的是String類型的視頻網(wǎng)址,但是如果遇到URI類型的只需要將struri = uri.toString();struri 就能夠支持加載URI了。
下面這個(gè)是原來(lái)作者的寫法
第四步:
在用到的播放器activity或者fragment的調(diào)用,在清單文件中設(shè)置
下面這是jcplayer原作者的GitHub地址,遇到的一些問題在這還得感謝原作者給我的幫助,喜歡的可以去start一下,不懂的盡量Issues:
https://github.com/lipangit/JieCaoVideoPlayer
以上就是原來(lái)的用法,可以參照原作者的就行不需要像我的這么大費(fèi)周折,下面是我使用后遇到的問題以及解決辦法
這里可以看看我用到的項(xiàng)目中activity的父類是繼承于activity的;然而jcplayer得繼承AppCompatActivity的基礎(chǔ)上才行,如果不繼承在全屏的時(shí)候無(wú)法隱藏toolbar,所以便會(huì)導(dǎo)致一個(gè)結(jié)果就是點(diǎn)擊全屏出現(xiàn)以下異常:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zontonec.ztgarden, PID: 27388
java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v7.app.ActionBar android.support.v7.app.AppCompatActivity.getSupportActionBar()' on a null object reference
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.hideSupportActionBar(JCVideoPlayer.java:864)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.startWindowFullscreen(JCVideoPlayer.java:638)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.onClick(JCVideoPlayer.java:190)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard.onClick(JCVideoPlayerStandard.java:176)
at android.view.View.performClick(View.java:5210)
at android.view.View$PerformClick.run(View.java:20976)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6145)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
分析后他給我們反映的是需要支持v7包下面.AppCompatActivity調(diào)用getSupportActionBar出現(xiàn)空指針異常,也就是說此時(shí)我們用到的項(xiàng)目中不能進(jìn)行隱藏toolbar,從而出現(xiàn)空指針異常,那么知道問啥了我們也就知道如何下手了,在此我們項(xiàng)目中用到的關(guān)于繼承activity的內(nèi)容過多,如果冒然修改為繼承AppCompatActivity的話我們的工作量將會(huì)相當(dāng)?shù)拇螅形覀兊膹膉cplayer的源碼入手解決問題,讓他來(lái)兼容我們的項(xiàng)目。
public static void hideSupportActionBar(Context context) {
// if (ACTION_BAR_EXIST) {
// ActionBar ab = JCUtils.getAppCompActivity(context).getSupportActionBar();
// if (ab != null) {
// ab.setShowHideAnimationEnabled(false);
// ab.hide();
// }
// }
if (TOOL_BAR_EXIST) {
JCUtils.getAppCompActivity(context).getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
public static void showSupportActionBar(Context context) {
// if (ACTION_BAR_EXIST) {
// ActionBar ab = JCUtils.getAppCompActivity(context).getSupportActionBar();
// if (ab != null) {
// ab.setShowHideAnimationEnabled(false);
// ab.show();
// }
// }
if (TOOL_BAR_EXIST) {
JCUtils.getAppCompActivity(context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
在源碼jcvideoplayer下面,我們可以發(fā)現(xiàn)下面條件是,如果點(diǎn)擊全屏?xí)r候actionbar存在的話,我們的將它隱藏,然而我們的activity并不支持,解決辦法也就得從這里入手了,我們只需要將用到隱藏actionbar的代碼,注釋或者刪除掉就行,你以為這樣就行了嗎?不行事情還沒解決,運(yùn)行照樣崩潰,再看下面這段代碼
/**
* Get activity from context object
*
* @param context something
* @return object of Activity or null if it is not Activity
*/
//源碼中這里是AppCompatActivity我們將它改為activity即、可,下面這段代碼就是我修改過后的
public static ***AppCompatActivity*** scanForActivity(Context context) {
if (context == null) return null;
if (context instanceof ***AppCompatActivity***) {
return (***AppCompatActivity***) context;
} else if (context instanceof ContextWrapper) {
return scanForActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}
/**
* Get AppCompatActivity from context
*
* @param context
* @return AppCompatActivity if it's not null
*/
//修改過的,同樣上面那個(gè)代碼需要修改了和static后面的activity的一致,源碼地方修改到了這,砸門運(yùn)行看看,絕對(duì)能進(jìn)入全屏了
public static Activity getAppCompActivity(Context context) {
if (context == null) return null;
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextThemeWrapper) {
return getAppCompActivity(((ContextThemeWrapper) context).getBaseContext());
}
return null;
}
但是在此時(shí)你又會(huì)遇到第三個(gè)問題,就是如果你播放的是本地相機(jī)錄制的視頻時(shí),他將會(huì)會(huì)對(duì)視頻全屏?xí)r的寬高進(jìn)行設(shè)置,同樣視頻播放完畢是又出現(xiàn)下面這個(gè)問題了
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zontonec.ztgarden, PID: 10376
java.lang.NullPointerException: Attempt to invoke virtual method 'void fm.jiecao.jcvideoplayer_lib.JCResizeTextureView.setVideoSize(android.graphics.Point)' on a null object reference
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.onVideoSizeChanged(JCVideoPlayer.java:578)
at fm.jiecao.jcvideoplayer_lib.JCMediaManager$7.run(JCMediaManager.java:228)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6145)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
他說我們?cè)趕etVideoSize時(shí)出現(xiàn)了空指針異常,為啥出現(xiàn)這問題呢?按理說在這里根本不會(huì)出現(xiàn)這個(gè)問題的了,根據(jù)異常的地方JCResizeTextureView這里在我們項(xiàng)目中出現(xiàn)問題了。好的下面就是解決問題的地方了,我們需要將源碼中的兩句代碼 判空部分注釋掉
//JCMediaManager.textureView = null;
//JCMediaManager.savedSurfaceTexture = null;
public void onAutoCompletion() {
//加上這句,避免循環(huán)播放video的時(shí)候,內(nèi)存不斷飆升。
Runtime.getRuntime().gc();
Log.i(TAG, "onAutoCompletion " + " [" + this.hashCode() + "] ");
onEvent(JCUserAction.ON_AUTO_COMPLETE);
dismissVolumeDialog();
dismissProgressDialog();
dismissBrightnessDialog();
cancelProgressTimer();
setUiWitStateAndScreen(CURRENT_STATE_AUTO_COMPLETE);
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
backPress();
}
JCUtils.saveProgress(getContext(), url, 0);
/**
* Created by kris-liutao on 2017.
* 此處需要注釋 不然會(huì)報(bào)setvideosize異常
*/
// JCMediaManager.textureView = null;
// JCMediaManager.savedSurfaceTexture = null;
}
幾經(jīng)波折,在運(yùn)行試試,好的所有問題全部解決了全屏正常播放。但是在此我更建議采用原作者的用法,這也是沒有辦法的辦法的,如果能在原基礎(chǔ)上解決問題的盡量在原基礎(chǔ)上,找起來(lái)問題來(lái)也不是很容易的。