最近在重构个人视频播放器,项目有点点复杂,不可能全面的记录
接下来,挑一些要点来记录一下,上下文铺设比较繁琐,有兴趣的能够本系列源码:githubgit
一些播放信息的记录感受仍是放在数据库里好一些,否则感受很生硬
之前的SQLite介绍文章有点无病呻吟的感受,此次来实际用一下,相信感触会更深
1.解决视频播放量的记录问题
2.解决视频进入时恢复到上次播放进度
3.解决查询最近播放的n条记录的问题
4.解决查询播放最多的n条记录的问题
复制代码
表字段
id 标识 主键,自增
path 视频名称 varchar(120) 惟一 非空
current_pos 当前播放进度 TINYINT 默认为0
last_play_time 上次播放时间 CHAR(24) 2019-3-1 16:20:00
play_count 播放次数 INT 默认为0
|--- 建表语句 -------------------------------
CREATE TABLE video_player (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
path VARCHAR(120) UNIQUE NOT NULL,
current_pos TINYINT NOT NULL DEFAULT 0,
last_play_time CHAR(24) NOT NULL,
play_count INT NOT NULL DEFAULT 0
);
复制代码
/**
* 做者:张风捷特烈<br/>
* 时间:2019/4/4/004:13:19<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:数据库辅助类
*/
public class VideoDatabaseHelper extends SQLiteOpenHelper {
private static String DATABASE_NAME = "i_video.db";//数据库名
private static int DATABASE_VERSION = 1;//数据库版本
public VideoDatabaseHelper(@Nullable Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
createSwordTable(db);
}
private void createSwordTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE video_player (\n" +
"id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" +
"path VARCHAR(120) UNIQUE NOT NULL,\n" +
"current_pos TINYINT NOT NULL DEFAULT 0,\n" +
"last_play_time CHAR(24) NOT NULL,\n" +
"play_count INT NOT NULL DEFAULT 0\n" +
"); ");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
复制代码
/**
* 做者:张风捷特烈<br></br>
* 时间:2019/4/4/004:13:29<br></br>
* 邮箱:1981462002@qq.com<br></br>
* 说明:视屏播放实体类
*/
class VideoBean {
var id: Int = 0
var path: String = ""
var current_pos: Int = 0
var last_play_time: String = ""
var play_count: Int = 1
}
复制代码
用个单例来获取VideoDao方便操做github
/**
* 做者:张风捷特烈<br/>
* 时间:2019/4/4/004:13:26<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:数据库操做层
*/
public class VideoDao {
private static VideoDao sVideoDao;
private SQLiteOpenHelper mHelper;
public void setHelper(SQLiteOpenHelper helper) {
mHelper = helper;
}
private VideoDao() {
}
public static VideoDao newInstance() {
if (sVideoDao == null) {
synchronized (VideoDao.class) {
if (sVideoDao == null) {
sVideoDao = new VideoDao();
}
}
}
return sVideoDao;
}
/**
* 插入
*
* @param video
*/
public void insert(VideoBean video) {
if (contains(video.getPath())) {
addPlayCount(video.getPath());
} else {
mHelper.getWritableDatabase().execSQL(
"INSERT INTO video_player(path,current_pos,last_play_time,play_count) VALUES(?,?,?,?)",
new String[]{
video.getPath(),
video.getCurrent_pos() + "",
video.getLast_play_time(),
video.getPlay_count() + ""});
}
}
/**
* 将某视频播放量+1,并更新时间
*
* @param path 视频路径
*/
private void addPlayCount(String path) {
int count = getPlayCount(path);
count++;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
String now = format.format(System.currentTimeMillis());
mHelper.getWritableDatabase().execSQL(
"UPDATE video_player SET play_count=? , last_play_time=?",
new String[]{count + "", now});
}
/**
* 根据路径获取播放量
*
* @param path 视频路径
* @return 播放量
*/
private int getPlayCount(String path) {
int result = 0;
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT play_count FROM video_player WHERE path=?", new String[]{path});
if (cursor.moveToNext()) {
result = cursor.getInt(cursor.getColumnIndex("play_count"));
}
cursor.close();
return result;
}
/**
* 检测是否包含某视频
*
* @param path 视频路径
* @return 否包含某视频
*/
public boolean contains(String path) {
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT path FROM video_player WHERE path=?", new String[]{path});
boolean has = cursor.moveToNext();
cursor.close();
return has;
}
}
复制代码
视屏播放器功能由VideoView实现,我上面封了一层VideoPlayerManager用来管理
在每次设置播放资源时插入数据,上面的插入方法在已经有值时,播放次数会 + 1数据库
|--- 在每次设置播放资源时插入 -------------------------------
VideoBean videoBean = new VideoBean();
videoBean.setPath(info.getDataUrl());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA);
videoBean.setLast_play_time(format.format(System.currentTimeMillis()));
VideoDao.newInstance().insert(videoBean);
复制代码
注意点击先后的播放量数字bash
核心在于暂停时保存进度,在恰当的时机进行 seekTo 和界面数据回显及渲染
使用MVP来解耦很方便,Presenter中获取数据库进度,顺便seekTo,
再将进度数据设置给Model,调用View的render() 方法进行渲染ide
---->[VideoView#pause]------------------------------
@Override
public void pause() {
saveProgress();//保存进度
if (canPlay() && mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
}
}
private void saveProgress() {
int per = (int) (getCurrentPosition() * 1.f / getDuration() * 100);
VideoDao.newInstance().saveProgress(mUri.getPath(), per);
}
---->[VideoDao#saveProgress]------------------------------
/**
* 保存播放进度
*/
public void saveProgress(String path, int per) {
if (contains(path)) {
mHelper.getWritableDatabase().execSQL(
"UPDATE video_player SET current_pos=? WHERE path =?",
new String[]{per + "", path});
}
}
---->[VideoDao#getProgress]------------------------------
/**
* 根据路径获取播放进度
*
* @param path 视频路径
* @return 播放进度
*/
public int getProgress(String path) {
int result = 0;
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT current_pos FROM video_player WHERE path=?", new String[]{path});
if (cursor.moveToNext()) {
result = cursor.getInt(cursor.getColumnIndex("current_pos"));
}
cursor.close();
return result;
}
复制代码
/**
* 获取最近播放的记录
*
* @param count 条数
* @return 最近播放的count条记录
*/
public String[] getRecent(int count) {
String[] strings = new String[count];
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT path FROM video_player ORDER BY last_play_time DESC LIMIT ?",
new String[]{count + ""});
int i = 0;
while (cursor.moveToNext()) {
String path = cursor.getString(cursor.getColumnIndex("path"));
strings[i] = path;
i++;
}
cursor.close();
return strings;
}
|--- 使用 ---------------------------------
VideoDao.newInstance().getRecent(5);
复制代码
/**
* 获取播放最多的n条记录
*
* @param count 条数
* @return 获取播放最多的n条记录
*/
public String[] getMost(int count) {
String[] strings = new String[count];
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT path FROM video_player ORDER BY play_count DESC LIMIT ?",
new String[]{count + ""});
int i = 0;
while (cursor.moveToNext()) {
String path = cursor.getString(cursor.getColumnIndex("path"));
strings[i] = path;
i++;
}
cursor.close();
return strings;
}
复制代码
小插曲:很诡异的一件事,我视图将这两个方法封装成一个ui
|--- 一开始我是这样的 ---------------------
/**
* 获取最近播放的记录
*
* @param count 条数
* @return 最近播放的count条记录
*/
public String[] getLimit(String by, int count) {
String[] strings = new String[count];
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT path FROM video_player ORDER BY ? DESC LIMIT ?",
new String[]{by,count + ""});
int i = 0;
while (cursor.moveToNext()) {
String path = cursor.getString(cursor.getColumnIndex("path"));
strings[i] = path;
i++;
}
cursor.close();
return strings;
}
|--- 而后怎么都搞不出想要的结果,郁闷... 这里说一下,问号只能用来传值,其余的能够拼接字符串
/**
* 获取最近播放的记录
*
* @param count 条数
* @return 最近播放的count条记录
*/
public String[] getLimit(String by, int count) {
String[] strings = new String[count];
Cursor cursor = mHelper.getReadableDatabase().
rawQuery("SELECT path FROM video_player ORDER BY " + by + " DESC LIMIT ?",
new String[]{count + ""});
int i = 0;
while (cursor.moveToNext()) {
String path = cursor.getString(cursor.getColumnIndex("path"));
strings[i] = path;
i++;
}
cursor.close();
return strings;
}
/**
* 获取播放最多的n条记录
*
* @param count 条数
* @return 获取播放最多的n条记录
*/
public String[] getMost(int count) {
return getLimit("play_count", 3);
}
/**
* 获取最近播放的记录
*
* @param count 条数
* @return 最近播放的count条记录
*/
public String[] getRecent(int count) {
return getLimit("last_play_time", count);
}
复制代码
想增长其余的记录,能够本身扩展。Over 本篇记录 就这样。spa