如何在SQLite数据库中存储视频内容(不是视频路径)

问题描述 投票:0回答:2

我想在sqlite数据库中存储一个视频。附:我不想存储路径,而是存储实际的视频内容。我已经将字节数组中的视频和存储的字节数组转换为sqlite数据库。检索时,bytearray正在转换为File。但是视频没有播放。请帮忙。

android android-sqlite android-database
2个回答
2
投票

我想在sqlite数据库中存储一个视频。附:我不想存储路径,而是存储实际的视频内容。

除非视频非常短并占用很小的空间(比如每个最多200k,可能是1/10秒,但取决于保存的格式),否则您可能会遇到问题和异常/崩溃。

  • 使用手机约2秒黑色占用2.2Mb,实际录制视频2秒钟占用7Mb。

虽然SQLite能够按照以下方式存储相对较大的BLOB: -

  • 字符串或BLOB的最大长度 字符串中的最大字节数或SQLite中的BLOB由预处理器宏SQLITE_MAX_LENGTH定义。此宏的默认值为10亿(十亿或1,000,000,000)。您可以使用命令行选项在编译时提高或降低此值,如下所示: -DSQLITE_MAX_LENGTH = 123456789当前实现仅支持长度为231-1或2147483647的字符串或BLOB长度。而在此之前,某些内置函数(如hex())可能会失败。在安全敏感的应用程序中,最好不要尝试增加最大字符串和blob长度。事实上,如果可能的话,你最好将最大字符串和blob长度降低到几百万的范围内。 在SQLite的INSERT和SELECT处理过程中,数据库中每行的完整内容被编码为单个BLOB。因此,SQLITE_MAX_LENGTH参数还确定一行中的最大字节数。 可以使用sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size)接口在运行时降低最大字符串或BLOB长度。 Limits In SQLite

Android SDK的CursorWindow具有2Mb的限制,如果是缓冲区则适用于行的所有列。因此,即使您可以成功存储视频,也可能无法检索这些视频。

推荐的方式是您不想要的,即存储视频的路径。

如果我将视频存储在我的内部/外部存储中并存储路径,那么我将如何从其他设备访问该视频。

您将遇到与数据库相同的问题,因为它通常存储在受保护的应用程序数据中。这是除非数据库是预先存在的数据库(即填充有数据),在这种情况下,数据库通过APK与App一起分发。

如果后者是通过APK分发的预先存在的数据库,那么视频也可以作为APK的一部分进行分发,因此作为数据库受到保护和可曝光。

如果您打算在不属于APK的设备之间分发视频,那么SQlite可能不是正确的解决方案,因为它是嵌入式数据库并且没有内置客户端/服务器功能。

除了我的设备被格式化然后我将丢失所有数据。

在这种情况下,数据库将像任何其他数据一样易受攻击,因为所有数据库都是文件,就像视频,word文档等一样,都需要合适的应用程序来查看/更改内容。但是,如果数据库是预先存在的数据库,那么只需重新安装App即可从APK恢复数据库和其他文件。

Working Example

This uses the Suggested/Recommended method assuming the videos are to be distributed with the APK.

  • 注意视频由qazxsw poi提供

创建新项目后,下载4个视频并将其复制到res / raw文件夹中(创建原始文件夹后),如下所示: -

Sample Videos

Database Helper(SQLiteOpenHelper的子类)是为2列表创建的,带有-_id列(注释名为_id,用于SimpleCursorAdapter)。 - 用于存储视频路径/名称的video_path(不是完整路径,但足以确定存储数据的路径) - 注意UNIQUE已编码为停止添加重复项。

使用一些基本方法来允许添加和删除行以及提取所有行(通过Cursor与SimpleCursorAdapter一起使用)。

DBHelper.java

enter image description here

一个相当简单的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);
    }
}

Results

首次启动时(没有播放): -

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()); } } }

长按1Mb视频后(删除数据库条目): -

enter image description here

单击列表中的A Video后: -

enter image description here


0
投票

你可以使用这种方法

保存视频时,将其保存在应用程序专用存储文件夹中。

enter image description here

这将为您提供Context.getFilesDir() 中应用程序存储的路径,它将位于内部存储中。

其中..\Andorid\data\data\com.example.app将是您的应用程序包ID。您可以在此处创建一个新文件夹,如com.example.app,然后将视频保存在此文件夹中。将其路径保存在DB中。只有您的应用可以访问此文件夹。没有任何其他应用或设备用户可以访问此文件夹。所以没有人可以编辑或删除你的文件,除了你的应用程序。

此外,如果用户重置移动设备,在某些情况下,此数据将被删除,数据库也可能被删除。因此,无需担心您的文件将被删除,但数据库仍然是他们的路径。如果删除了文件,那么DB也会被删除,但仅限于app VideosUninstall, device reset

© www.soinside.com 2019 - 2024. All rights reserved.