Как хранить видеоконтент в базе данных SQLite (не путь к видео)

Я хочу сохранить видео в базе данных sqlite. P.S. Я не хочу хранить путь, а фактическое содержимое видео. Я преобразовал видео в массив байтов и сохранил массив байтов в базе данных sqlite. После извлечения bytearray преобразуется в файл. Но видео не воспроизводится. Пожалуйста помоги.

Это абсолютно неправильно. Вы не можете сохранить его в БД. Если вы добавите 2 3 записи, вы не сможете запрашивать в БД после этого. Почему ты хочешь этого?

Abdur Rahman 15.02.2019 11:42

Может быть, тогда я смогу дать вам хороший ответ на это

Abdur Rahman 15.02.2019 11:42

тогда каким должен быть подход? Если я сохраню видео во внутреннем/внешнем хранилище и вместо этого сохраню путь, то как я смогу получить к нему доступ с какого-либо другого устройства. Кроме того, если мое устройство будет отформатировано, я потеряю все данные.

Getsetgo 15.02.2019 11:54

как прикрепить мой код? Когда я копирую и вставляю код, он не позволяет мне вставлять то же самое, поскольку помечает много ошибок.

Getsetgo 15.02.2019 12:39

Курсор SQLite имеет ограничение по размеру в 1 МБ. Таким образом, вы не можете хранить видео в SQLite.

Fustigador 15.02.2019 12:48

это плохая идея

user1209216 15.02.2019 17:39
0
6
6 298
2

Ответы 2

Вы можете использовать этот подход

При сохранении видео сохраните его в папке личного хранилища приложения.

Context.getFilesDir()

Это даст вам путь к хранилищу приложений в ..\Andorid\data\data\com.example.app и он будет во внутренней памяти.

Где com.example.app будет вашим идентификатором пакета приложения. Вы можете создать новую папку здесь, например Videos, а затем сохранять видео в этой папке. Сохраните его путь в БД. Только ваше приложение может получить доступ к этой папке. Ни одно другое приложение или пользователь устройства не может получить доступ к этой папке. Таким образом, никто не может редактировать или удалять ваши файлы, кроме вашего приложения.

Более того, если пользователь сбросит мобильное устройство, эти данные будут удалены, а также ваша база данных и, возможно, ваше приложение в некоторых случаях. Поэтому не нужно беспокоиться о том, что ваши файлы будут удалены, но в базе данных все еще есть их путь. Если файл удален, то БД тоже удаляется, но только когда приложение Uninstall, device reset или SD card erase.

Код для загрузки видео, снятого через мое приложение на сервере sql? Мы должны преобразовать его в массив байтов и загрузить то же самое на сервер с помощью Volley или каким должен быть подход?

Getsetgo 15.02.2019 12:49

Вы можете легко найти код, как преобразовать видео в массив байтов в Интернете. И всякий раз, когда вы хотите загрузить видео на сервер, конвертируйте его непосредственно перед отправкой.

Abdur Rahman 15.02.2019 13:25

I want to store a video in sqlite database. P.S. I do not want to store the path but the actual video contents.

Если видео не очень короткие и не занимают мало места (скажем, до 200 КБ каждое, возможно, 1/10 секунды, но это зависит от формата, в котором оно сохранено), вы, вероятно, столкнетесь с проблемами и исключениями / сбоями.

  • Использование телефона около 2 секунд черного цвета заняло 2,2 МБ, 2 секунды фактической записи видео заняли 7 МБ.

Хотя SQLite имеет возможность хранить относительно большие BLOB в соответствии с: -

  • Maximum length of a string or BLOB

    The maximum number of bytes in a string or BLOB in SQLite is defined by the preprocessor macro SQLITE_MAX_LENGTH. The default value of this macro is 1 billion (1 thousand million or 1,000,000,000). You can raise or lower this value at compile-time using a command-line option like this:

    -DSQLITE_MAX_LENGTH=123456789 The current implementation will only support a string or BLOB length up to 231-1 or 2147483647. And some built-in functions such as hex() might fail well before that point. In security-sensitive applications it is best not to try to increase the maximum string and blob length. In fact, you might do well to lower the maximum string and blob length to something more in the range of a few million if that is possible.

    During part of SQLite's INSERT and SELECT processing, the complete content of each row in the database is encoded as a single BLOB. So the SQLITE_MAX_LENGTH parameter also determines the maximum number of bytes in a row.

    The maximum string or BLOB length can be lowered at run-time using the sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) interface. Limits In SQLite

КурсорОкно Android SDK имеет ограничение в 2 МБ, и это касается всех столбцов строк (строк) if buffers. Таким образом, даже если вы можете успешно сохранить видео, вы не сможете получить эти видео.

Рекомендуемый способ - это то, что вам не нужно, то есть сохранение пути к видео.

If i store the video in my internal/external storage and store the path instead then how will i be able to access the same from some other device.

У вас будет такая же проблема с базой данных, поскольку он обычно хранится в защищенных данных приложений. Это если база данных не является уже существующей базой данных (то есть заполненной данными), и в этом случае база данных распространяется с приложением через APK.

Если последнее — уже существующая база данных, распространяемая через APK, то видео также можно распространять как часть APK и, следовательно, так же защищено и доступно, как и база данных.

Если вы намерены распространять видео между устройствами, которые не являются частью APK, то SQlite, вероятно, не является правильным решением, поскольку это встроенная база данных и не имеет встроенных функций клиент/сервер.

Besides what if my device gets formatted then I will lose all the data.

В таком сценарии база данных будет так же уязвима, как и любые другие данные, так как это вся база данных, файл, такой же, как видео, текстовый документ и т. д., для которых требуется подходящее приложение для просмотра/изменения содержимого. Однако, если база данных уже существует, то простая переустановка приложения восстановит базу данных и другие файлы из APK.

Рабочий пример

При этом используется метод Suggested/Recommended, предполагающий, что видео будут распространяться вместе с APK.

После создания нового проекта 4 видео были загружены и скопированы в папку res/raw (после создания папки raw) в соответствии с: -

Помощник по базе данных (подкласс SQLiteOpenHelper) был создан для таблицы из 2 столбцов с - Столбец _я бы (примечание с именем _я бы для использования с SimpleCursorAdapter). - video_path для хранения пути/имени видео (не полный путь, но достаточный, чтобы можно было определить путь из сохраненных данных) - Обратите внимание, что код UNIQUE предотвращает добавление дубликатов.

С помощью некоторого базового метода, позволяющего добавлять и удалять строки и извлекать все строки (через Cursor для использования с SimpleCursorAdapter).

DBHelper.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);
    }
}

Довольно прямолинейный MainActivity.java (см. комментарии)

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

Результаты

При первом запуске (ничего не играет): -

После долгого нажатия на видео размером 1 МБ (удаление записи в БД): -

После нажатия видео в списке: -

Другие вопросы по теме