The foreword 0.

Recently in the reconstruction of my video player, the project is a little complex, it is impossible to record the comprehensive next, pick some points to record, the context laid more cumbersome, interested in this series of source code: Github

Some playback information recording feeling or put in the database some better, otherwise the feeling is very blunt before SQLite introduction article a bit of a moan about nothing feeling, this time to actually use, I believe that the feeling will be deeper 1. Solve the problem of recording the number of videos played. 2. Solve the problem of restoring the last playing progress 3 when the video is entered. Solve the problem of querying the n records played most recently 4. Solve the problem of querying the N records played most frequentlyCopy the code


Steps to use SQLite

1. The table analysis
Table field ID identifies primary key, Add path Video name vARCHar (120) Unique non-empty current_pos Current playing progress TINYINT Default to 0 last_play_time Last playing time CHAR(24) 2019-3-1 16:20:00 | play_count plays INT default to 0 - built predicate sentence -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the 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 );Copy the code

2. Create VideoDatabaseHelper inherited from SQLiteOpenHelper
Time: 2019/4/4/004:13:19<br/> * Email: [email protected]<br/> * Description: 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) {

    }
}
Copy the code

3. Simple encapsulation of entity classes
/ * * * the author: packer jet fierce < br > < br > * time: 2019/4/4/004: supposing, < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: */ class VideoBean {var ID: Int = 0 var path: String =""
    var current_pos: Int = 0
    var last_play_time: String = ""
    var play_count: Int = 1
}
Copy the code

4. Create a Dao to operate the database

Use a singleton to get the VideoDao for easy operation

<br/> * Time: 2019/4/4/004:13:26<br/> * Email: [email protected]<br/> * Public class VideoDao {private static VideoDao sVideoDao; private SQLiteOpenHelper mHelper; public voidsetHelper(SQLiteOpenHelper helper) {
        mHelper = helper;
    }

    private VideoDao() {
    }

    public static VideoDao newInstance() {
        if (sVideoDao == null) {
            synchronized (VideoDao.class) {
                if(sVideoDao == null) { sVideoDao = new VideoDao(); }}}returnsVideoDao; } /** * insert ** @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() + ""}); ** @param path Video 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}); } /** ** Get the number of plays by path ** @param path Video 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();
        returnresult; } /** * check whether a video is included ** @param path Video path * @returnNo contains a video * / 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();
        returnhas; }}Copy the code

Second, the use of

1. About insertion

The video player function is realized by VideoView. I have enclosed a layer of VideoPlayerManager to manage the insertion of data every time the resource is set to play. When the insertion method above has a value, the playback times will be + 1

| - inserted in each set play resources -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 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);
Copy the code

Note the number of plays before and after the click


2. Record the playback progress

The key is to save progress while pausing, and to decouble seekTo from the interface data display and render at the right time. MVP is a convenient way to decouble the database progress from Presenter, which in turn gets the progress from seekTo, and then sets the progress data to Model by calling the Render () method of the View

---->[VideoView#pause]------------------------------
@Override
public void pause() { saveProgress(); // Save the progressif (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]------------------------------/** * get playback progress by path ** @param path Video 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;
}
Copy the code

3. N records played recently

/** * get the most recently played record ** @param count number * @returnPublic 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();
    returnstrings; Use} | -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - VideoDao. NewInstance (). GetRecent (5);Copy the code

4. Obtain the n most-played packets

/** * get the most played n records ** @param count number of records * @returnPublic 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;
}
Copy the code

Vignette: The weird thing is that I want to encapsulate these two methods into one

| - at first I was such a -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / get recently played records * * * * * @ param count number * @returnPublic 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();
    returnstrings; } | - then how all don't want, depressed... For example, the question mark can only be used to pass values, the other can be concatenated string /** ** to get the most recently played record ** @param count number * @returnPublic 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();
    returnstrings; } /** * get the most played n records ** @param count number * @returnPublic String[] getMost(int count) {public String[] getMost(int count) {return getLimit("play_count", 3); } /** * get the most recently played record ** @param count number * @returnPublic String[] getRecent(int count) {public String[] getRecent(int count) {return getLimit("last_play_time", count);
}
Copy the code

If you want to add other records, you can extend them yourself. That’s all for the record.