○-○–○—○----○-----○------○ 呆萌的分割线 ○------○-----○----○—○–○-○
言归正传,总结一下Android循环录像的逻辑:
1.保存视频时,存储视频信息到数据库,包括:
id | 视频ID |
name | 视频名称 |
lock | 是否锁定(0,1) |
resolution | 分辨率(720,1080) |
2.每次开始录像和保存视频时检查剩余存储空间
sdFree < sdTotal * Constant.Record.SD_MIN_FREE_PERCENT || intSdFree < Constant.Record.SD_MIN_FREE_STORAGE
3.如果低于预设底限,则开始删除较旧的未加锁视频
4.如果删除所有的未加锁视频后,空间依然不足,则开始删除加锁视频
5.如果删除所有的加锁视频,空间依然不足,提示用户清理SD卡
[ Well well. Talk is cheap. Show me the code. ]
完整代码:
/**
-
获得SD卡总大小
-
@return 总大小,单位:字节B
*/
public static long getSDTotalSize(String SDCardPath) {
StatFs stat = new StatFs(SDCardPath);
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return blockSize * totalBlocks;
}
/**
-
获得sd卡剩余容量,即可用大小
-
@return 剩余空间,单位:字节B
*/
public static long getSDAvailableSize(String SDCardPath) {
// StatFs stat = new StatFs(“/storage/sdcard1”);
StatFs stat = new StatFs(SDCardPath);
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return blockSize * availableBlocks;
}
/**
-
录像SD卡是否存在
-
@return
*/
public static boolean isVideoCardExists() {
try {
String pathVideo = Constant.Path.SDCARD_1 + “/tachograph/”;
if (Constant.Record.saveVideoToSD2) {
pathVideo = Constant.Path.SDCARD_2 + “/tachograph/”;
}
File fileVideo = new File(pathVideo);
fileVideo.mkdirs();
File file = new File(pathVideo);
if (!file.exists()) {
return false;
}
} catch (Exception e) {
MyLog.e(“[StorageUtil]isVideoCardExists:Catch Exception!”);
return false;
}
return true;
}
package com.tchip.carlauncher.model;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DriveVideoDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = “video_db”;
private static final String VIDEO_TABLE_NAME = “video”;
private static final String VIDEO_COL_ID = “_id”;
private static final String VIDEO_COL_NAME = “name”; // 视频文件名称,如:2015-07-01_105536.mp4
private static final String VIDEO_COL_LOCK = “lock”; // 是否加锁:0-否 1-是
private static final String VIDEO_COL_RESOLUTION = “resolution”; // 视频分辨率:720/1080
private static final String[] VIDEO_COL_PROJECTION = new String[] {
VIDEO_COL_ID, VIDEO_COL_NAME, VIDEO_COL_LOCK, VIDEO_COL_RESOLUTION, };
public DriveVideoDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Create table
@Override
public void onCreate(SQLiteDatabase db) {
String createRouteTableSql = “CREATE TABLE " + VIDEO_TABLE_NAME + " (”
-
VIDEO_COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
-
VIDEO_COL_NAME + " TEXT," + VIDEO_COL_LOCK + " INTEGER,"
-
VIDEO_COL_RESOLUTION + " INTEGER" + “);”;
db.execSQL(createRouteTableSql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + VIDEO_TABLE_NAME);
// Create tables again
onCreate(db);
}
// Add new DriveVideo
public int addDriveVideo(DriveVideo driveVideo) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(VIDEO_COL_NAME, driveVideo.getName());
values.put(VIDEO_COL_LOCK, driveVideo.getLock());
values.put(VIDEO_COL_RESOLUTION, driveVideo.getResolution());
// Insert to database
long rowId = db.insert(VIDEO_TABLE_NAME, null, values);
// Close the database
db.close();
return (int) rowId;
}
// Get DriveVideo By ID
public DriveVideo getRouteDistanceById(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(VIDEO_TABLE_NAME, VIDEO_COL_PROJECTION,
VIDEO_COL_ID + “=?”, new String[] { String.valueOf(id) }, null,
null, null, null);
if (cursor != null)
cursor.moveToFirst();
DriveVideo driveVideo = new DriveVideo(cursor.getInt(0),
cursor.getString(1), cursor.getInt(2), cursor.getInt(3));
db.close();
cursor.close();
return driveVideo;
}
// Get DriveVideo By Name
public DriveVideo getDriveVideoByName(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(VIDEO_TABLE_NAME, VIDEO_COL_PROJECTION,
VIDEO_COL_NAME + “=?”, new String[] { name }, null, null, null,
null);
if (cursor != null)
cursor.moveToFirst();
DriveVideo driveVideo = new DriveVideo(cursor.getInt(0),
cursor.getString(1), cursor.getInt(2), cursor.getInt(3));
db.close();
cursor.close();
return driveVideo;
}
public boolean isVideoExist(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(VIDEO_TABLE_NAME, VIDEO_COL_PROJECTION,
VIDEO_COL_NAME + “=?”, new String[] { name }, null, null, null,
null);
if (cursor.getCount() > 0) {
db.close();
cursor.close();
return true;
} else {
db.close();
cursor.close();
return false;
}
}
/**
-
根据视频名查询是否加锁
-
@param name
-
@return
*/
public int getLockStateByVideoName(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(VIDEO_TABLE_NAME, VIDEO_COL_PROJECTION,
VIDEO_COL_NAME + “=?”, new String[] { name }, null, null, null,
null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
int videoLock = cursor
.getInt(cursor.getColumnIndex(VIDEO_COL_LOCK));
db.close();
cursor.close();
return videoLock;
} else {
db.close();
cursor.close();
return 0;
}
}
/**
-
获取所有的视频信息
-
@return
*/
public List getAllDriveVideo() {
List driveVideoList = new ArrayList();
String selectQuery = "SELECT * FROM " + VIDEO_TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
DriveVideo driveVideo = new DriveVideo(cursor.getInt(0),
cursor.getString(1), cursor.getInt(2), cursor.getInt(3));
driveVideoList.add(driveVideo);
} while (cursor.moveToNext());
}
db.close();
cursor.close();
// return list
return driveVideoList;
}
public Cursor getAllDriveVideoCursor() {
String selectQuery = "SELECT * FROM " + VIDEO_TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
return cursor;
}
/**
-
获取加锁视频Cursor
-
@return
*/
public Cursor getLockVideoCursor() {
String sqlLine = "SELECT * FROM " + VIDEO_TABLE_NAME + " WHERE "
- VIDEO_COL_LOCK + “=?”;
String selection[] = new String[] { “1” };
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(sqlLine, selection);
return cursor;
}
/**
-
获取最旧且未加锁视频ID
-
@return
*/
public int getOldestUnlockVideoId() {
String sqlLine = "SELECT * FROM " + VIDEO_TABLE_NAME + " WHERE "
- VIDEO_COL_LOCK + “=?”;
String selection[] = new String[] { “0” };
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(sqlLine, selection);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
int id = cursor.getInt(cursor.getColumnIndex(VIDEO_COL_ID));
db.close();
cursor.close();
return id;
} else {
db.close();
cursor.close();
return -1;
}
}
/**
-
获取最旧视频(包括加锁)ID
-
@return
*/
public int getOldestVideoId() {
String sqlLine = "SELECT * FROM " + VIDEO_TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(sqlLine, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
int id = cursor.getInt(cursor.getColumnIndex(VIDEO_COL_ID));
db.close();
cursor.close();
return id;
} else {
db.close();
cursor.close();
return -1;
}
}
public String getVideNameById(int id) {
String sqlLine = "SELECT * FROM " + VIDEO_TABLE_NAME + " WHERE "
- VIDEO_COL_ID + “=?”;
String selection[] = new String[] { String.valueOf(id) };
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(sqlLine, selection);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
String videoName = cursor.getString(cursor
.getColumnIndex(VIDEO_COL_NAME));
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
下图是我进阶学习所积累的历年腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节
整理不易,望各位看官老爷点个关注转发,谢谢!祝大家都能得到自己心仪工作。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
759296690)]
[外链图片转存中…(img-UGWy2tQf-1713759296691)]
[外链图片转存中…(img-pZfG0ujN-1713759296692)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
[外链图片转存中…(img-LUi9E3Ux-1713759296693)]
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
下图是我进阶学习所积累的历年腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节
[外链图片转存中…(img-Fp1pkBSo-1713759296696)]
整理不易,望各位看官老爷点个关注转发,谢谢!祝大家都能得到自己心仪工作。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!