一、前言:
在使用饺子视频的时候,在部分安卓手机不兼容,比如,金立手机,华为部分手机,一直显示加载框,不能播放视频。
demo地址:https://github.com/lipangit/JiaoZiVideoPlayer
1. 引包
implementation 'cn.jzvd:jiaozivideoplayer:6.2.12'
或者下载lib(不推荐)。
(https://github.com/lipangit/JiaoZiVideoPlayer/releases/tag/v6.2.12) (not recommended).
2. 添加JZVideoPlayer你的布局:
<cn.jzvd.JZVideoPlayerStandard
android:id="@+id/videoplayer"
android:layout_width="match_parent"
android:layout_height="200dp"/>
3. 设置视频uri,视频拇指网址和视频标题:
JZVideoPlayerStandard jzVideoPlayerStandard = (JZVideoPlayerStandard) findViewById(R.id.videoplayer);
// 图片等比例放大
jzVideoPlayerStandard .thumbImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
//设置视频裁剪方式(导致部分页面被裁切)
//Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP);
//设置容器内播放器高(能完整显示)
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT);
jzVideoPlayerStandard.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4", "饺子闭眼睛",
JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL
);
jzVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
4.在 Activity:
@Override
public void onBackPressed() {
if (JZVideoPlayer.backPress()) {
return;
}
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
JZVideoPlayer.releaseAllVideos();
}
5. 在 AndroidManifest.xml:(清单文件)
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" />
<!-- or android:screenOrientation="landscape"-->
二、解决部分手机不兼容(更换bilibili内核):
方式:通过更换饺子视频播放内核就可以了。
注意:bilibili内核不支持https视频链接。
1. 引入bilibili内核
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
implementation 'cn.jzvd:jiaozivideoplayer:6.2.12'
2. 更换内核
bilibili内核: JZMediaIjk.class
// 这个播放地址有问题
"https://sumansoul.oss-cn-shanghai.aliyuncs.com/admin/video/XdPTxKFjH28Xhc7BWWxrnnwmBRt7x8mH.mp4";
JZVideoPlayerStandard jzVideoPlayerStandard = (JZVideoPlayerStandard) findViewById(R.id.videoplayer);
// 图片等比例放大
jzVideoPlayerStandard .thumbImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
//设置视频裁剪方式(导致部分页面被裁切)
//Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP);
//设置容器内播放器高(能完整显示)
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT);
jzVideoPlayerStandard.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4", "饺子闭眼睛" ,
JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL,
JZMediaIjk.class);
jzVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
2. JZMediaIjk文件:
package com.sumansoul.student.widget.video;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.view.Surface;
import java.io.IOException;
import cn.jzvd.JZMediaInterface;
import cn.jzvd.Jzvd;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.IjkTimedText;
/**
*
* Created by Nathen on 2017/11/18.
*/
public class JZMediaIjk extends JZMediaInterface implements IMediaPlayer.OnPreparedListener, IMediaPlayer.OnVideoSizeChangedListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnTimedTextListener {
IjkMediaPlayer ijkMediaPlayer;
public JZMediaIjk(Jzvd jzvd) {
super(jzvd);
}
@Override
public void start() {
if (ijkMediaPlayer != null) ijkMediaPlayer.start();
}
@Override
public void prepare() {
release();
mMediaHandlerThread = new HandlerThread("JZVD");
mMediaHandlerThread.start();
mMediaHandler = new Handler(mMediaHandlerThread.getLooper());//主线程还是非主线程,就在这里
handler = new Handler();
mMediaHandler.post(() -> {
ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 1024 * 1024);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
ijkMediaPlayer.setOnPreparedListener(JZMediaIjk.this);
ijkMediaPlayer.setOnVideoSizeChangedListener(JZMediaIjk.this);
ijkMediaPlayer.setOnCompletionListener(JZMediaIjk.this);
ijkMediaPlayer.setOnErrorListener(JZMediaIjk.this);
ijkMediaPlayer.setOnInfoListener(JZMediaIjk.this);
ijkMediaPlayer.setOnBufferingUpdateListener(JZMediaIjk.this);
ijkMediaPlayer.setOnSeekCompleteListener(JZMediaIjk.this);
ijkMediaPlayer.setOnTimedTextListener(JZMediaIjk.this);
try {
ijkMediaPlayer.setDataSource(jzvd.jzDataSource.getCurrentUrl().toString());
ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
ijkMediaPlayer.setScreenOnWhilePlaying(true);
ijkMediaPlayer.prepareAsync();
ijkMediaPlayer.setSurface(new Surface(jzvd.textureView.getSurfaceTexture()));
} catch (IOException e) {
e.printStackTrace();
}
});
}
@Override
public void pause() {
ijkMediaPlayer.pause();
}
@Override
public boolean isPlaying() {
return ijkMediaPlayer.isPlaying();
}
@Override
public void seekTo(long time) {
ijkMediaPlayer.seekTo(time);
}
@Override
public void release() {
if (mMediaHandler != null && mMediaHandlerThread != null && ijkMediaPlayer != null) {//不知道有没有妖孽
HandlerThread tmpHandlerThread = mMediaHandlerThread;
IjkMediaPlayer tmpMediaPlayer = ijkMediaPlayer;
JZMediaInterface.SAVED_SURFACE = null;
mMediaHandler.post(() -> {
tmpMediaPlayer.setSurface(null);
tmpMediaPlayer.release();
tmpHandlerThread.quit();
});
ijkMediaPlayer = null;
}
}
@Override
public long getCurrentPosition() {
return ijkMediaPlayer.getCurrentPosition();
}
@Override
public long getDuration() {
return ijkMediaPlayer.getDuration();
}
@Override
public void setVolume(float leftVolume, float rightVolume) {
ijkMediaPlayer.setVolume(leftVolume, rightVolume);
}
@Override
public void setSpeed(float speed) {
ijkMediaPlayer.setSpeed(speed);
}
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {
handler.post(() -> jzvd.onPrepared());
}
@Override
public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int i, int i1, int i2, int i3) {
handler.post(() -> jzvd.onVideoSizeChanged(iMediaPlayer.getVideoWidth(), iMediaPlayer.getVideoHeight()));
}
@Override
public boolean onError(IMediaPlayer iMediaPlayer, final int what, final int extra) {
handler.post(() -> jzvd.onError(what, extra));
return true;
}
@Override
public boolean onInfo(IMediaPlayer iMediaPlayer, final int what, final int extra) {
handler.post(() -> jzvd.onInfo(what, extra));
return false;
}
@Override
public void onBufferingUpdate(IMediaPlayer iMediaPlayer, final int percent) {
handler.post(() -> jzvd.setBufferProgress(percent));
}
@Override
public void onSeekComplete(IMediaPlayer iMediaPlayer) {
handler.post(() -> jzvd.onSeekComplete());
}
@Override
public void onTimedText(IMediaPlayer iMediaPlayer, IjkTimedText ijkTimedText) {
}
@Override
public void setSurface(Surface surface) {
ijkMediaPlayer.setSurface(surface);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if (SAVED_SURFACE == null) {
SAVED_SURFACE = surface;
prepare();
} else {
jzvd.textureView.setSurfaceTexture(SAVED_SURFACE);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
@Override
public void onCompletion(IMediaPlayer iMediaPlayer) {
handler.post(() -> jzvd.onAutoCompletion());
}
}
三、解决部分手机不兼容(更换exoplayer内核):
方式:通过更换饺子视频播放内核就可以了。
1. 引入exoplayer内核
implementation 'com.google.android.exoplayer:exoplayer:2.9.1'
implementation 'cn.jzvd:jiaozivideoplayer:6.2.12'
2. 更换内核
exoplayer内核: JZMediaExo.class
// 这个播放地址有问题
"https://sumansoul.oss-cn-shanghai.aliyuncs.com/admin/video/XdPTxKFjH28Xhc7BWWxrnnwmBRt7x8mH.mp4";
JZVideoPlayerStandard jzVideoPlayerStandard = (JZVideoPlayerStandard) findViewById(R.id.videoplayer);
// 图片等比例放大
jzVideoPlayerStandard .thumbImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
//设置视频裁剪方式(导致部分页面被裁切)
//Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP);
//设置容器内播放器高(能完整显示)
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT);
jzVideoPlayerStandard.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4", "饺子闭眼睛" ,
JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL,
JZMediaExo.class);
jzVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
2. JZMediaExo文件:
/**
* Created by MinhDV on 5/3/18.
*/
public class JZMediaExo extends JZMediaInterface implements Player.EventListener, VideoListener {
private SimpleExoPlayer simpleExoPlayer;
private Runnable callback;
private String TAG = "JZMediaExo";
private long previousSeek = 0;
public JZMediaExo(Jzvd jzvd) {
super(jzvd);
}
@Override
public void start() {
simpleExoPlayer.setPlayWhenReady(true);
}
@Override
public void prepare() {
Log.e(TAG, "prepare");
Context context = jzvd.getContext();
release();
mMediaHandlerThread = new HandlerThread("JZVD");
mMediaHandlerThread.start();
mMediaHandler = new Handler(mMediaHandlerThread.getLooper());//主线程还是非主线程,就在这里
handler = new Handler();
mMediaHandler.post(() -> {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl(new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
360000, 600000, 1000, 5000,
C.LENGTH_UNSET,
false);
// 2. Create the player
RenderersFactory renderersFactory = new DefaultRenderersFactory(context);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(context, renderersFactory, trackSelector, loadControl);
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, context.getResources().getString(R.string.app_name)));
String currUrl = jzvd.jzDataSource.getCurrentUrl().toString();
MediaSource videoSource;
if (currUrl.contains(".m3u8")) {
videoSource = new HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(currUrl), handler, null);
} else {
videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(currUrl));
}
simpleExoPlayer.addVideoListener(this);
Log.e(TAG, "URL Link = " + currUrl);
simpleExoPlayer.addListener(this);
Boolean isLoop = jzvd.jzDataSource.looping;
if (isLoop) {
simpleExoPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
} else {
simpleExoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF);
}
simpleExoPlayer.prepare(videoSource);
simpleExoPlayer.setPlayWhenReady(true);
callback = new onBufferingUpdate();
simpleExoPlayer.setVideoSurface(new Surface(jzvd.textureView.getSurfaceTexture()));
});
}
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
handler.post(() -> jzvd.onVideoSizeChanged(width, height));
}
@Override
public void onRenderedFirstFrame() {
Log.e(TAG, "onRenderedFirstFrame");
}
@Override
public void pause() {
simpleExoPlayer.setPlayWhenReady(false);
}
@Override
public boolean isPlaying() {
return simpleExoPlayer.getPlayWhenReady();
}
@Override
public void seekTo(long time) {
if (time != previousSeek) {
simpleExoPlayer.seekTo(time);
previousSeek = time;
jzvd.seekToInAdvance = time;
}
}
@Override
public void release() {
if (mMediaHandler != null && mMediaHandlerThread != null && simpleExoPlayer != null) {//不知道有没有妖孽
HandlerThread tmpHandlerThread = mMediaHandlerThread;
SimpleExoPlayer tmpMediaPlayer = simpleExoPlayer;
JZMediaInterface.SAVED_SURFACE = null;
mMediaHandler.post(() -> {
tmpMediaPlayer.release();//release就不能放到主线程里,界面会卡顿
tmpHandlerThread.quit();
});
simpleExoPlayer = null;
}
}
@Override
public long getCurrentPosition() {
if (simpleExoPlayer != null)
return simpleExoPlayer.getCurrentPosition();
else return 0;
}
@Override
public long getDuration() {
if (simpleExoPlayer != null)
return simpleExoPlayer.getDuration();
else return 0;
}
@Override
public void setVolume(float leftVolume, float rightVolume) {
simpleExoPlayer.setVolume(leftVolume);
simpleExoPlayer.setVolume(rightVolume);
}
@Override
public void setSpeed(float speed) {
PlaybackParameters playbackParameters = new PlaybackParameters(speed, 1.0F);
simpleExoPlayer.setPlaybackParameters(playbackParameters);
}
@Override
public void onTimelineChanged(final Timeline timeline, Object manifest, final int reason) {
Log.e(TAG, "onTimelineChanged");
// JZMediaPlayer.instance().mainThreadHandler.post(() -> {
// if (reason == 0) {
//
// JzvdMgr.getCurrentJzvd().onInfo(reason, timeline.getPeriodCount());
// }
// });
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
Log.e(TAG, "onLoadingChanged");
}
@Override
public void onPlayerStateChanged(final boolean playWhenReady, final int playbackState) {
Log.e(TAG, "onPlayerStateChanged" + playbackState + "/ready=" + String.valueOf(playWhenReady));
handler.post(() -> {
switch (playbackState) {
case Player.STATE_IDLE: {
}
break;
case Player.STATE_BUFFERING: {
handler.post(callback);
}
break;
case Player.STATE_READY: {
if (playWhenReady) {
jzvd.onStatePlaying();
} else {
}
}
break;
case Player.STATE_ENDED: {
jzvd.onAutoCompletion();
}
break;
}
});
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
Log.e(TAG, "onPlayerError" + error.toString());
handler.post(() -> jzvd.onError(1000, 1000));
}
@Override
public void onPositionDiscontinuity(int reason) {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
@Override
public void onSeekProcessed() {
handler.post(() -> jzvd.onSeekComplete());
}
@Override
public void setSurface(Surface surface) {
simpleExoPlayer.setVideoSurface(surface);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if (SAVED_SURFACE == null) {
SAVED_SURFACE = surface;
prepare();
} else {
jzvd.textureView.setSurfaceTexture(SAVED_SURFACE);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
private class onBufferingUpdate implements Runnable {
@Override
public void run() {
if (simpleExoPlayer != null) {
final int percent = simpleExoPlayer.getBufferedPercentage();
handler.post(() -> jzvd.setBufferProgress(percent));
if (percent < 100) {
handler.postDelayed(callback, 300);
} else {
handler.removeCallbacks(callback);
}
}
}
}
}
四、解决部分手机不兼容(Android系统播放内核):
1. 引入jar包:
implementation 'cn.jzvd:jiaozivideoplayer:6.2.12'
2. 更换内核
系统播放内核: JZMediaSystemAssertFolder.class
// 这个播放地址有问题
"https://sumansoul.oss-cn-shanghai.aliyuncs.com/admin/video/XdPTxKFjH28Xhc7BWWxrnnwmBRt7x8mH.mp4";
JZVideoPlayerStandard jzVideoPlayerStandard = (JZVideoPlayerStandard) findViewById(R.id.videoplayer);
// 图片等比例放大
jzVideoPlayerStandard .thumbImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
//设置视频裁剪方式(导致部分页面被裁切)
//Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP);
//设置容器内播放器高(能完整显示)
Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT);
jzVideoPlayerStandard.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4", "饺子闭眼睛" ,
JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL,
JZMediaSystemAssertFolder.class);
jzVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
2. JZMediaSystemAssertFolder文件:
/**
* Created by Nathen on 2017/11/8.
* 实现系统的播放引擎
*/
public class JZMediaSystemAssertFolder extends JZMediaInterface implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener, MediaPlayer.OnVideoSizeChangedListener {
public MediaPlayer mediaPlayer;
public JZMediaSystemAssertFolder(Jzvd jzvd) {
super(jzvd);
}
@Override
public void prepare() {
release();
mMediaHandlerThread = new HandlerThread("JZVD");
mMediaHandlerThread.start();
mMediaHandler = new Handler(mMediaHandlerThread.getLooper());//主线程还是非主线程,就在这里
handler = new Handler();
mMediaHandler.post(() -> {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setLooping(jzvd.jzDataSource.looping);
mediaPlayer.setOnPreparedListener(JZMediaSystemAssertFolder.this);
mediaPlayer.setOnCompletionListener(JZMediaSystemAssertFolder.this);
mediaPlayer.setOnBufferingUpdateListener(JZMediaSystemAssertFolder.this);
mediaPlayer.setScreenOnWhilePlaying(true);
mediaPlayer.setOnSeekCompleteListener(JZMediaSystemAssertFolder.this);
mediaPlayer.setOnErrorListener(JZMediaSystemAssertFolder.this);
mediaPlayer.setOnInfoListener(JZMediaSystemAssertFolder.this);
mediaPlayer.setOnVideoSizeChangedListener(JZMediaSystemAssertFolder.this);
//two lines are different
AssetFileDescriptor assetFileDescriptor = (AssetFileDescriptor) jzvd.jzDataSource.getCurrentUrl();
mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());
mediaPlayer.prepareAsync();
mediaPlayer.setSurface(new Surface(jzvd.textureView.getSurfaceTexture()));
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void start() {
mMediaHandler.post(() -> mediaPlayer.start());
}
@Override
public void pause() {
mMediaHandler.post(() -> mediaPlayer.pause());
}
@Override
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
@Override
public void seekTo(long time) {
mMediaHandler.post(() -> {
try {
mediaPlayer.seekTo((int) time);
} catch (IllegalStateException e) {
e.printStackTrace();
}
});
}
@Override
public void release() {
if (mMediaHandler != null && mMediaHandlerThread != null && mediaPlayer != null) {//不知道有没有妖孽
HandlerThread tmpHandlerThread = mMediaHandlerThread;
MediaPlayer tmpMediaPlayer = mediaPlayer;
JZMediaInterface.SAVED_SURFACE = null;
mMediaHandler.post(() -> {
tmpMediaPlayer.release();//release就不能放到主线程里,界面会卡顿
tmpHandlerThread.quit();
});
mediaPlayer = null;
}
}
//TODO 测试这种问题是否在threadHandler中是否正常,所有的操作mediaplayer是否不需要thread,挨个测试,是否有问题
@Override
public long getCurrentPosition() {
if (mediaPlayer != null) {
return mediaPlayer.getCurrentPosition();
} else {
return 0;
}
}
@Override
public long getDuration() {
if (mediaPlayer != null) {
return mediaPlayer.getDuration();
} else {
return 0;
}
}
@Override
public void setVolume(float leftVolume, float rightVolume) {
if (mMediaHandler == null) return;
mMediaHandler.post(() -> {
if (mediaPlayer != null) mediaPlayer.setVolume(leftVolume, rightVolume);
});
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void setSpeed(float speed) {
PlaybackParams pp = mediaPlayer.getPlaybackParams();
pp.setSpeed(speed);
mediaPlayer.setPlaybackParams(pp);
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
if (jzvd.jzDataSource.getCurrentUrl().toString().toLowerCase().contains("mp3") ||
jzvd.jzDataSource.getCurrentUrl().toString().toLowerCase().contains("wav")) {
handler.post(() -> jzvd.onPrepared());
}
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
handler.post(() -> jzvd.onAutoCompletion());
}
@Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, final int percent) {
handler.post(() -> jzvd.setBufferProgress(percent));
}
@Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
handler.post(() -> jzvd.onSeekComplete());
}
@Override
public boolean onError(MediaPlayer mediaPlayer, final int what, final int extra) {
handler.post(() -> jzvd.onError(what, extra));
return true;
}
@Override
public boolean onInfo(MediaPlayer mediaPlayer, final int what, final int extra) {
handler.post(() -> {
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
if (jzvd.state == Jzvd.STATE_PREPARING
|| jzvd.state == Jzvd.STATE_PREPARING_CHANGING_URL) {
jzvd.onPrepared();
}
} else {
jzvd.onInfo(what, extra);
}
});
return false;
}
@Override
public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
handler.post(() -> jzvd.onVideoSizeChanged(width, height));
}
@Override
public void setSurface(Surface surface) {
mediaPlayer.setSurface(surface);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if (SAVED_SURFACE == null) {
SAVED_SURFACE = surface;
prepare();
} else {
jzvd.textureView.setSurfaceTexture(SAVED_SURFACE);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}
五、结尾:
- bilibili不支持https链接,可以采用工具生成.so包,可以支持https链接,但是视频加载速度有点慢;
- exoplayer内核支持https链接,视频加载速度比较慢;
- 可以考虑采用七牛云视频播放器,加载速度飞快,需要二次封装能力;
4.也可以考虑腾讯云播放器的;
网友评论