前言:
Android中视频或者音频播放的话获取到播放进度和总时长是很常见的,最近有个需求需要在视频不播放时显示总时长,播放器默认状态的话是没有进度和时长的,调试断点发现时长总是为负数就感觉很不美妙了,本篇文章就是为了解决视频或音频默认状态下根据url获取视频的总时长。
1.获取视频时长的方法如下:
/**
* 根据url查询视频时长和宽高
*
* @param url
* @return
*/
public static long getPlayTime(String url) {
android.media.MediaMetadataRetriever metadataRetriever = new android.media.MediaMetadataRetriever();
try {
if (url != null) {
HashMap
headers = new HashMap<>();
headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; MW-KW-001 Build/JRO03C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/1.0.0.001 U4/0.8.0 Mobile Safari/533.1");
metadataRetriever.setDataSource(url, headers);
} else {
//mmr.setDataSource(mFD, mOffset, mLength);
}
durationTime = Long.valueOf(metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));//时长(毫秒)
String width = metadataRetriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);//宽
String height = metadataRetriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);//高
} catch (Exception ex) {
ex.printStackTrace();
} finally {
metadataRetriever.release();
}
return durationTime;
}
2.在项目中的实际使用:
private void initData() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
long time = VideoUtils.getPlayTime(videoUrl);
Log.d("--time--",time+"");
jzvdStd.totalTimeTextView.setText(JZUtils.stringForTime(time));
}
},200);
getDuration(videoUrl);
}
3.出现问题:直接使用MediaMetadataRetriever,如果网络不好或者在列表中使用非常卡顿,会出现anr问题,解决方法:使用rxjava异步方式处理.
使用rxjava方式代码如下:
public void getDuration(String url){
io.reactivex.Observable
@Override
public void subscribe(ObservableEmitter
android.media.MediaMetadataRetriever metadataRetriever = new android.media.MediaMetadataRetriever();
try {
if (url != null) {
HashMap
headers = new HashMap<>();
headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; MW-KW-001 Build/JRO03C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/1.0.0.001 U4/0.8.0 Mobile Safari/533.1");
metadataRetriever.setDataSource(url, headers);
} else {
//mmr.setDataSource(mFD, mOffset, mLength);
}
long durationTime = Long.parseLong(metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));//时长(毫秒)
String width = metadataRetriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);//宽
String height = metadataRetriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);//高
e.onNext(durationTime);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
metadataRetriever.release();
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
observable.subscribe(new Observer
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long time) {
Log.d("--time--",time.toString());
jzvdStd.totalTimeTextView.setText(JZUtils.stringForTime(time));
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
4.MainActivity的完整代码如下:
package com.example.videotimedemo;
import android.annotation.SuppressLint;
import android.media.MediaMetadataRetriever;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.example.videotimedemo.app.App;
import com.example.videotimedemo.util.VideoUtils;
import java.util.HashMap;
import cn.jzvd.JZMediaSystem;
import cn.jzvd.JZUtils;
import cn.jzvd.Jzvd;
import cn.jzvd.JzvdStd;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity {
public static final String videoUrl = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
private Handler mHandler;
private JzvdStd jzvdStd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
initView();
initData();
}
private void initData() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
long time = VideoUtils.getPlayTime(videoUrl);
Log.d("--time--",time+"");
jzvdStd.totalTimeTextView.setText(JZUtils.stringForTime(time));
}
},200);
getDuration(videoUrl);
}
public void getDuration(String url){
io.reactivex.Observable
@Override
public void subscribe(ObservableEmitter
android.media.MediaMetadataRetriever metadataRetriever = new android.media.MediaMetadataRetriever();
try {
if (url != null) {
HashMap
headers = new HashMap<>();
headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; MW-KW-001 Build/JRO03C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/1.0.0.001 U4/0.8.0 Mobile Safari/533.1");
metadataRetriever.setDataSource(url, headers);
} else {
//mmr.setDataSource(mFD, mOffset, mLength);
}
long durationTime = Long.parseLong(metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));//时长(毫秒)
String width = metadataRetriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);//宽
String height = metadataRetriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);//高
e.onNext(durationTime);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
metadataRetriever.release();
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
observable.subscribe(new Observer
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long time) {
Log.d("--time--",time.toString());
jzvdStd.totalTimeTextView.setText(JZUtils.stringForTime(time));
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
private void initView() {
jzvdStd = findViewById(R.id.videoplayer);
if (jzvdStd != null) {
String proxyUrl = App.getProxy(this).getProxyUrl(videoUrl);
jzvdStd.setUp(proxyUrl, "视频默认没有播放", JzvdStd.SCREEN_NORMAL, JZMediaSystem.class);
jzvdStd.onPrepared();
}
}
@Override
protected void onPause() {
super.onPause();
Jzvd.goOnPlayOnPause();
}
@Override
protected void onResume() {
super.onResume();
Jzvd.goOnPlayOnResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
Jzvd.releaseAllVideos();
}
}
5.项目运行后的日志打印如下:
6.实现的效果图如下:
7.源码地址如下:
https://gitee.com/jackning_admin/videotimedemo