我想在sqlite数据库中存储一个视频。附:我不想存储路径,而是存储实际的视频内容。我已经将字节数组中的视频和存储的字节数组转换为sqlite数据库。检索时,bytearray正在转换为File。但是视频没有播放。请帮忙。
我想在sqlite数据库中存储一个视频。附:我不想存储路径,而是存储实际的视频内容。
除非视频非常短并占用很小的空间(比如每个最多200k,可能是1/10秒,但取决于保存的格式),否则您可能会遇到问题和异常/崩溃。
虽然SQLite能够按照以下方式存储相对较大的BLOB: -
Android SDK的CursorWindow具有2Mb的限制,如果是缓冲区则适用于行的所有列。因此,即使您可以成功存储视频,也可能无法检索这些视频。
推荐的方式是您不想要的,即存储视频的路径。
如果我将视频存储在我的内部/外部存储中并存储路径,那么我将如何从其他设备访问该视频。
您将遇到与数据库相同的问题,因为它通常存储在受保护的应用程序数据中。这是除非数据库是预先存在的数据库(即填充有数据),在这种情况下,数据库通过APK与App一起分发。
如果后者是通过APK分发的预先存在的数据库,那么视频也可以作为APK的一部分进行分发,因此作为数据库受到保护和可曝光。
如果您打算在不属于APK的设备之间分发视频,那么SQlite可能不是正确的解决方案,因为它是嵌入式数据库并且没有内置客户端/服务器功能。
除了我的设备被格式化然后我将丢失所有数据。
在这种情况下,数据库将像任何其他数据一样易受攻击,因为所有数据库都是文件,就像视频,word文档等一样,都需要合适的应用程序来查看/更改内容。但是,如果数据库是预先存在的数据库,那么只需重新安装App即可从APK恢复数据库和其他文件。
创建新项目后,下载4个视频并将其复制到res / raw文件夹中(创建原始文件夹后),如下所示: -
Database Helper(SQLiteOpenHelper的子类)是为2列表创建的,带有-_id列(注释名为_id,用于SimpleCursorAdapter)。 - 用于存储视频路径/名称的video_path(不是完整路径,但足以确定存储数据的路径) - 注意UNIQUE已编码为停止添加重复项。
使用一些基本方法来允许添加和删除行以及提取所有行(通过Cursor与SimpleCursorAdapter一起使用)。
一个相当简单的MainActivity.java(参见评论)
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "myvideos";
public static final int DBVERSION = 1;
public static final String TBL_VIDEO = "video";
public static final String COL_VIDEO_ID = BaseColumns._ID;
public static final String COL_VIDEO_PATH = "video_path";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_video_table = "CREATE TABLE IF NOT EXISTS " + TBL_VIDEO + "(" +
COL_VIDEO_ID + " INTEGER PRIMARY KEY," +
COL_VIDEO_PATH + " TEXT UNIQUE" +
")";
db.execSQL(crt_video_table);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addVideo(String path) {
ContentValues cv = new ContentValues();
cv.put(COL_VIDEO_PATH,path);
return mDB.insert(TBL_VIDEO,null,cv);
}
public Cursor getVideos() {
return mDB.query(TBL_VIDEO,null,null,null,null,null,null);
}
public int deleteVideoFromDB(long id) {
String whereclause = COL_VIDEO_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return mDB.delete(TBL_VIDEO,whereclause,whereargs);
}
}
public class MainActivity extends AppCompatActivity {
TextView mMyTextView;
ListView mVideoList;
VideoView mVideoViewer;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyTextView = this.findViewById(R.id.mytext);
mVideoList = this.findViewById(R.id.videolist);
mVideoViewer = this.findViewById(R.id.videoviewer);
mDBHlpr = new DBHelper(this);
addVideosFromRawResourceToDB();
}
@Override
protected void onDestroy() {
mCsr.close(); //<<<<<<<<<< clear up the Cursor
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
manageListView(); //<<<<<<<<<< rebuild and redisplay the List of Videos (in case they have changed)
}
/**
* Setup or Refresh the ListView adding the OnItemClick and OnItemLongClick listeners
*/
private void manageListView() {
mCsr = mDBHlpr.getVideos();
// Not setup so set it up
if (mSCA == null) {
// Instantiate the SimpleCursorAdapter
mSCA = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1, // Use stock layout
mCsr, // The Cursor with the list of videos
new String[]{DBHelper.COL_VIDEO_PATH}, // the column (columns)
new int[]{android.R.id.text1}, // the view id(s) into which the column(s) data will be placed
0
);
mVideoList.setAdapter(mSCA); // Set the adpater for the ListView
/**
* Add The Long Click Listener (will delete the video row from the DB (NOT the video))
*/
mVideoList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
mDBHlpr.deleteVideoFromDB(id);
manageListView(); // <<<<<<<<<< refresh the ListView as data has changed
return true;
}
});
/**
* Play the respective video when the item is clicked
* Note Cursor should be at the correct position so data can be extracted directly from the Cursor
*/
mVideoList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setCurrentVideo(mCsr.getString(mCsr.getColumnIndex(DBHelper.COL_VIDEO_PATH)));
}
});
} else {
mSCA.swapCursor(mCsr); //<<<<<<<<<< apply the changed Cursor
}
}
/**
* Set the currrent video and play it
* @param path the path (resource name of the video)
*/
private void setCurrentVideo(String path) {
mVideoViewer.setVideoURI(
Uri.parse(
"android.resource://" + getPackageName() + "/" + String.valueOf(
getResources().getIdentifier(
path,
"raw",
getPackageName())
)
)
);
mVideoViewer.start();
}
/**
* Look at all the resources in the res/raw folder and add the to the DB (not if they are duplicates due to UNQIUE)
*/
private void addVideosFromRawResourceToDB() {
Field[] fields=R.raw.class.getFields();
for(int count=0; count < fields.length; count++){
Log.i("Raw Asset: ", fields[count].getName());
mDBHlpr.addVideo(fields[count].getName());
}
}
}
你可以使用这种方法
保存视频时,将其保存在应用程序专用存储文件夹中。
这将为您提供Context.getFilesDir()
中应用程序存储的路径,它将位于内部存储中。
其中..\Andorid\data\data\com.example.app
将是您的应用程序包ID。您可以在此处创建一个新文件夹,如com.example.app
,然后将视频保存在此文件夹中。将其路径保存在DB中。只有您的应用可以访问此文件夹。没有任何其他应用或设备用户可以访问此文件夹。所以没有人可以编辑或删除你的文件,除了你的应用程序。
此外,如果用户重置移动设备,在某些情况下,此数据将被删除,数据库也可能被删除。因此,无需担心您的文件将被删除,但数据库仍然是他们的路径。如果删除了文件,那么DB也会被删除,但仅限于app Videos
或Uninstall, device reset
。