Как хранить видео контент в базе данных SQLite (не путь к видео) - PullRequest
0 голосов
/ 15 февраля 2019

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

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Я хочу хранить видео в базе данных sqlite.PS Я не хочу сохранять путь, но фактическое содержание видео.

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

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

Хотя SQLite имеет возможность хранить относительно большие большие двоичные объекты в соответствии с: -

  • Максимальная длина строки или большого двоичного объекта

    Максимальное количество байтов в строке или большом двоичном объекте в SQLite определяется макросом препроцессора SQLITE_MAX_LENGTH.Значение этого макроса по умолчанию составляет 1 миллиард (1 тысяча миллионов или 1 000 000 000).Вы можете увеличить или уменьшить это значение во время компиляции, используя параметр командной строки, например, такой:

    -DSQLITE_MAX_LENGTH = 123456789 Текущая реализация будет поддерживать только строку или длину BLOB до 231-1 или 2147483647. Инекоторые встроенные функции, такие как hex (), могут выйти из строя задолго до этого.В приложениях, чувствительных к безопасности, лучше не пытаться увеличить максимальную длину строки и двоичного объекта.Фактически, вы можете преуменьшить максимальную длину строки и большого двоичного объекта до нескольких миллионов, если это возможно.

    Во время обработки SQLite INSERT и SELECT полное содержимое каждогоСтрока в базе данных закодирована как один BLOB.Поэтому параметр SQLITE_MAX_LENGTH также определяет максимальное количество байтов в строке.

    Максимальная длина строки или BLOB-объекта может быть уменьшена во время выполнения с помощью интерфейса sqlite3_limit (db, SQLITE_LIMIT_LENGTH, size). Пределы в SQLite

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

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

Если я сохраню видео во внутреннем / внешнем хранилище и вместо него сохраню путь, то как я смогу получить к нему доступ с другого устройства.

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

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

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

Кроме того, что, если мое устройство будет отформатировано, я потеряю все данные.

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

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

Используется предложенный / рекомендуемый метод, при условии, что видео должны распространяться вместе с APK.

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

enter image description here

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

С некоторымибазовый метод, позволяющий добавлять и удалять строки и извлекать все строки (с помощью курсора для использования с 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());
            }
    }
}

Результаты

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

enter image description here

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

enter image description here

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

enter image description here

0 голосов
/ 15 февраля 2019

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

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

Context.getFilesDir()

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...