SQLite
 sql >> база данни >  >> RDS >> SQLite

Как да съхранявате видео съдържание в базата данни на SQLite (не пътя на видеото)

Искам да съхраня видео в sqlite база данни. P.S. Не искам да съхранявам пътя, а действителното видео съдържание.

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

  • Използването на телефон около 2 секунди черно заеха 2,2Mb, 2 секунди действително записване на видеоклип заеха 7Mb.

Въпреки че SQLite има способността да съхранява относително големи BLOB според :-

  • Максимална дължина на низ или BLOB

    Максималният брой байтове в низ или BLOB в SQLite се дефинира от макроса на препроцесора SQLITE_MAX_LENGTH. Стойността по подразбиране на този макрос е 1 милиард (1 хиляда милион или 1 000 000 000). Можете да увеличите или намалите тази стойност по време на компилиране, като използвате опция от командния ред, като тази:

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

    По време на част от обработката INSERT и SELECT на SQLite, пълното съдържание на всеки ред в базата данни се кодира като един BLOB. Така параметърът SQLITE_MAX_LENGTH също така определя максималния брой байтове в ред.

    Максималната дължина на низ или BLOB може да бъде намалена по време на изпълнение с помощта на интерфейса sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size). Ограничения в SQLite

CursorWindow на Android SDK има ограничение от 2Mb и това е за всички колони на ред(ове) if буфери. По този начин, дори ако можете да съхранявате видеоклипове успешно, може да не сте в състояние да извлечете тези видеоклипове.

Препоръчителният начин е това, което не искате, тоест да съхраните пътя към видеоклипа.

Ако съхраня видеото във вътрешното/външно хранилище и вместо това запазя пътя, тогава как ще мога да осъществя достъп до същото от друго устройство.

Ще имате същия проблем с базата данни тъй като обикновено се съхранява в данните на приложенията, които са защитени. Това е, освен ако базата данни не е вече съществуваща база данни (т.е. попълнена с данни), в който случай базата данни се разпространява с приложението чрез APK.

Ако последното е вече съществуваща база данни, разпространявана чрез APK, тогава видеоклиповете също могат да се разпространяват като част от APK и следователно толкова защитени, колкото и достъпни като базата данни.

Ако намерението ви е да разпространявате видеоклипове между устройства, които не са част от APK, тогава SQlite вероятно не е правилното решение, тъй като е вградена база данни и няма вградена клиент/сървър функционалност.

Освен това, ако устройството ми бъде форматирано, ще загубя всички данни.

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

Работен пример

Това използва метода Suggested/Recommended, като се приема, че видеоклиповете трябва да се разпространяват с APK.

  • Забележка на видеоклипове с любезното съдействие на Примерни видеоклипове

След създаването на нов проект 4 видеоклипа бяха изтеглени и копирани в папката res/raw (след създаването на raw папката) съгласно :-

Помощникът за база данни (подклас на SQLiteOpenHelper) е създаден за таблица с 2 колони с _id колона (бележка с име _id за използване с SimpleCursorAdapter ).- video_path за съхраняване на пътя/името на видеоклипа (не пълният път, но достатъчен, за да може да се определи пътя от съхранените данни)- Забележка УНИКАЛНО е кодирано, за да спре добавянето на дубликати.

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

Резултати

При първото стартиране (нищо не се възпроизвежда) :-

След дълго щракване върху 1Mb видео (изтриване на записа в DB) :-

След като щракнете върху видеоклип в списъка :-



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Получаване на NoClassDefFoundError, докато се опитвате да използвате Proguard и SQLcipher в Android

  2. Как да форматирате дата и час в SQLite

  3. Грешка в Android SQLite:номерът на променливата трябва да е между ?1 и ?999

  4. SQLite NOT NULL ограничение

  5. SQLite Поръчайте по