Android 视频播放器第三方框架之 ijkplayer
一:介绍
ijkplayer 是 b 站开源的超级好用的视频播放器喔,置信大家都早有耳闻。ijkplayer Android 和 ios 都可用,还反对多种视频的硬解码
二:应用
第一步:增加依赖
dependencies {
// 个别这 2 个曾经足够用了,这是增加了一个 armv7a 的 cpu 架构,反对 armv7a 和 arm64 笼罩了大部分手机
//required, enough for most devices.
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
// Other ABIs: optional
// 这里 x86 x86_64 针对平板和模拟器
implementation 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
//ExoPlayer as IMediaPlayer: optional, experimental
implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
}
第二步:增加 3 个 so 库
看到咱们是在 libs 下配置的·so 库
须要 app 在 build.gradle 下
android{
defaultConfig{
ndk {
// 抉择要增加的对应 cpu 类型的.so 库。, 打包编译只会减轻一个 armeabi-v7a,so 库
abiFilters 'armeabi-v7a'
}
}
// 应为在 libs 下配置的须要定位到,如果是在 src/main 创立 jniLibs 文件夹就须要上面
sourceSets {
main {jniLibs.srcDirs = ['libs']
}
}
}
三个 so 库 libijkffmpeg.so 封装解码的应用,libijkplayer.so 视频播放的,libijksdl.so
第三步:创立一个 View
public class MyIjkVideoView extends FrameLayout {
private Context mContext;// 上下文
private IMediaPlayer mMediaPlayer = null;// 视屏播放
private TextView subtitleDisplay;// 字幕 View
private SurfaceView surfaceView;// 视图次要实用于被动更新,例如频繁地刷新
private VideoPlayerListener listener;//jiant
/**
* 视频文件地址
*/
private String mPath = "";
private boolean mEnableBackgroundPlay = false;// 是否开启后盾服务
public MyIjkVideoView(@NonNull Context context) {super(context);
initVideoView(context);
}
public MyIjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);
initVideoView(context);
}
public MyIjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
initVideoView(context);
}
/**
* 初始化 VideoView
*/
private void initVideoView(Context context) {
mContext = context;
// 是否开启后盾播放,如果开启了后盾播放,就启动一个 Service 来做后盾播放。initBackground();
// 初始化渲染器,创立 SurfaceView 或 TextureView,并 addView()。(IjkVideoView 是 FrameLayout)initRenders();
// 焦点
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
// 字幕 View
subtitleDisplay = new TextView(context);
subtitleDisplay.setTextSize(24);
subtitleDisplay.setGravity(Gravity.CENTER);
FrameLayout.LayoutParams layoutParams_txt = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM);
addView(subtitleDisplay, layoutParams_txt);
}
private void initRenders() {}
private void initBackground() {
// 这里相当于没有进去,具体须要再解决
if (mEnableBackgroundPlay) {MediaPlayerService.intentToStart(getContext());
mMediaPlayer = MediaPlayerService.getMediaPlayer();}
}
/**
* 设置视频地址。* 依据是否第一次播放视频,做不同的操作。*
* @param path the path of the video.
*/
public void setVideoPath(String path) {if (TextUtils.equals("", mPath)) {
// 如果是第一次播放视频,那就创立一个新的 surfaceView
mPath = path;
createSurfaceView();} else {
// 否则就间接 load
mPath = path;
load();}
}
/**
* 新建一个 SurfaceView
*/
private void createSurfaceView() {
// 生成一个新的 surface view
surfaceView = new SurfaceView(mContext);
surfaceView.getHolder().addCallback(new LmnSurfaceCallback());
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT
, LayoutParams.MATCH_PARENT, Gravity.CENTER);
surfaceView.setLayoutParams(layoutParams);
this.addView(surfaceView);
}
/**
* surfaceView 的监听器, 外部类
*/
private class LmnSurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {// 在 SurfaceView 创立}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
// 在 SurfaceView 扭转, 加载视屏
load();}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {// 在 SurfaceView 销毁}
}
/**
* 加载视屏
*/
private void load() {
// 每次都要从新创立 IMediaPlayer
createPlayer();
try {mMediaPlayer.setDataSource(mPath);
} catch (IOException e) {e.printStackTrace();
}
// 给 mediaPlayer 设置视图
mMediaPlayer.setDisplay(surfaceView.getHolder());
mMediaPlayer.prepareAsync();}
private void createPlayer() {
// 去除旧的
if (mMediaPlayer != null) {mMediaPlayer.stop();
mMediaPlayer.setDisplay(null);
mMediaPlayer.release();}
// 新建一个新的
IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);
// 开启硬解码 ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
mMediaPlayer = ijkMediaPlayer;
if (listener != null) {mMediaPlayer.setOnPreparedListener(listener);
mMediaPlayer.setOnErrorListener(listener);
mMediaPlayer.setOnCompletionListener(listener);
}
}
public void setListener(VideoPlayerListener listener) {
this.listener = listener;
if (mMediaPlayer != null) {mMediaPlayer.setOnPreparedListener(listener);
}
}
public interface VideoPlayerListener extends IMediaPlayer.OnPreparedListener,
IMediaPlayer.OnCompletionListener,
IMediaPlayer.OnErrorListener { }
/** 上面配置一些暂停,开始,进行等办法 */
public boolean isPlaying() {if (mMediaPlayer != null) {return mMediaPlayer.isPlaying();
}
return false;
}
public void start() {if (mMediaPlayer != null) {mMediaPlayer.start();
}
}
public void pause() {if (mMediaPlayer != null) {mMediaPlayer.pause();
}
}
public void stop() {if (mMediaPlayer != null) {mMediaPlayer.stop();
}
}
public void reset() {if (mMediaPlayer != null) {mMediaPlayer.reset();
}
}
public void release() {if (mMediaPlayer != null) {mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
在布局中应用 View
<com.ruan.mygitignore.MyIjkVideoView
android:id="@+id/ijk_video"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
第四步:调用
MyIjkVideoView ijkVideoView=findViewById(R.id.ijk_video);
String url = "https://wdl.wallstreetcn.com/41aae4d2-390a-48ff-9230-ee865552e72d";
// 加载本地库
IjkMediaPlayer.loadLibrariesOnce(null);
IjkMediaPlayer.native_profileBegin("libijkplayer.so");
// 监听
ijkVideoView.setListener(new MyIjkVideoView.VideoPlayerListener() {
@Override
public void onCompletion(IMediaPlayer iMediaPlayer) {Log.d("aa","实现");
}
@Override
public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {Log.d("aa","失败");
return false;
}
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {Log.d("aa","筹备");
}
});
// 设置门路
ijkVideoView.setVideoPath(url);
// 开始加载
ijkVideoView.start();
上面是一个 gitHub 上官网的例子
https://github.com/Bilibili/i…
结尾:不要伪装致力,后果不会陪你演戏