Я хочу хранить видео в базе данных 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](https://i.stack.imgur.com/6gqMn.png)
Помощник по базам данных (подкласс 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](https://i.stack.imgur.com/naJcE.png)
После долгого нажатия на видео размером 1 МБ (удаление записи в БД): -
![enter image description here](https://i.stack.imgur.com/Bb0zV.png)
После нажатия видео в списке: -
![enter image description here](https://i.stack.imgur.com/v4eb6.png)