SQLite
 sql >> Base de données >  >> RDS >> SQLite

Comment stocker le contenu vidéo dans la base de données SQLite (pas le chemin de la vidéo)

Je veux stocker une vidéo dans la base de données sqlite. PS Je ne veux pas stocker le chemin mais le contenu vidéo réel.

À moins que les vidéos ne soient très courtes et n'occupent que peu d'espace (disons jusqu'à 200 000 ko chacune, peut-être 1/10e de seconde, mais cela dépend du format dans lequel elles sont enregistrées), vous rencontrerez probablement des problèmes et des exceptions/plantages.

  • L'utilisation d'un téléphone pendant environ 2 secondes de noir prenait 2,2 Mo, et 2 secondes d'enregistrement d'une vidéo occupaient 7 Mo.

Bien que SQLite ait la capacité de stocker des BLOB relativement volumineux selon :-

  • Longueur maximale d'une chaîne ou d'un BLOB

    Le nombre maximal d'octets dans une chaîne ou un BLOB dans SQLite est défini par la macro du préprocesseur SQLITE_MAX_LENGTH. La valeur par défaut de cette macro est de 1 milliard (1 milliard ou 1 000 000 000). Vous pouvez augmenter ou diminuer cette valeur au moment de la compilation à l'aide d'une option de ligne de commande comme celle-ci :

    -DSQLITE_MAX_LENGTH=123456789 L'implémentation actuelle ne prend en charge qu'une longueur de chaîne ou de BLOB jusqu'à 231-1 ou 2147483647. Et certaines fonctions intégrées telles que hex() peuvent échouer bien avant ce point. Pour les applications sensibles à l'insécurité, il est préférable de ne pas essayer d'augmenter la longueur maximale de chaîne et de blob. En fait, vous feriez mieux de réduire la longueur maximale de la chaîne et de la goutte à quelque chose de plus dans la plage de quelques millions si cela est possible.

    Pendant une partie du traitement INSERT et SELECT de SQLite, le contenu complet de chaque ligne de la base de données est encodé sous la forme d'un seul BLOB. Ainsi, le paramètre SQLITE_MAX_LENGTH détermine également le nombre maximum d'octets dans une ligne.

    La longueur maximale de la chaîne ou du BLOB peut être réduite au moment de l'exécution à l'aide de l'interface sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size).Limits In SQLite

CursorWindow du SDK Android a une limitation de 2 Mo et c'est pour toutes les colonnes de la ou des lignes si les tampons. En tant que tel, même si vous pouvez stocker des vidéos avec succès, vous ne pourrez peut-être pas récupérer ces vidéos.

La méthode recommandée est ce que vous ne voulez pas, c'est-à-dire stocker le chemin d'accès à la vidéo.

Si je stocke la vidéo dans mon stockage interne/externe et que je stocke le chemin à la place, comment pourrai-je y accéder à partir d'un autre appareil.

Vous auriez le même problème avec la base de données car il est généralement stocké dans les données d'applications qui sont protégées. Sauf si la base de données est une base de données préexistante (c'est-à-dire remplie de données), auquel cas la base de données est distribuée avec l'application via l'APK.

Si ce dernier, une base de données préexistante distribuée via l'APK, alors les vidéos peuvent également être distribuées dans le cadre de l'APK et donc aussi protégées et aussi exposables que la base de données.

Si votre intention est de distribuer des vidéos entre des appareils qui ne font pas partie de l'APK, alors SQlite n'est probablement pas la bonne solution car il s'agit d'une base de données intégrée et n'a pas de fonctionnalité client/serveur intégrée.

De plus, si mon appareil est formaté, je perdrai toutes les données.

Dans un tel scénario, la base de données serait aussi vulnérable que n'importe quelle autre donnée , car c'est tout ce que la base de données est, un fichier, tout comme une vidéo, un document Word, etc., qui ont tous besoin d'une application appropriée pour afficher/modifier le contenu. Cependant, si la base de données est une base de données préexistante, il suffit de réinstaller l'application pour restaurer la base de données et d'autres fichiers à partir de l'APK.

Exemple de travail

Cela utilise la méthode suggérée/recommandée en supposant que les vidéos doivent être distribuées avec l'APK.

  • Remarquez les vidéos avec l'aimable autorisation de Exemples de vidéos

Après avoir créé un nouveau projet, 4 vidéos ont été téléchargées et copiées dans le dossier res/raw (après avoir créé le dossier raw) selon :-

L'assistant de base de données (sous-classe de SQLiteOpenHelper) a été créé pour une table à 2 colonnes avec un _id colonne (note nommée _id à utiliser avec SimpleCursorAdapter ).- video_path pour stocker le chemin/nom de la vidéo (pas le chemin complet mais suffisant pour pouvoir déterminer le chemin à partir des données stockées)- Remarque UNIQUE a été codé pour empêcher l'ajout de doublons.

Avec une méthode de base pour permettre l'ajout et la suppression de lignes et l'extraction de toutes les lignes (via un curseur à utiliser avec le 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);
    }
}

Un MainActivity.java assez simple (voir commentaires)

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

Résultats

Au premier démarrage (rien ne joue) :-

Après avoir longuement cliqué sur la vidéo de 1 Mo (en supprimant l'entrée DB) :-

Après avoir cliqué sur une vidéo dans la liste :-