SQLite
 sql >> Datenbank >  >> RDS >> SQLite

So speichern Sie Videoinhalte in der SQLite-Datenbank (nicht im Videopfad)

Ich möchte ein Video in einer SQLite-Datenbank speichern. P.S. Ich möchte nicht den Pfad speichern, sondern den eigentlichen Videoinhalt.

Wenn die Videos nicht sehr kurz sind und wenig Platz beanspruchen (z. B. bis zu 200 KB pro Stück, vielleicht 1/10 Sekunde, aber das hängt vom Format ab, in dem sie gespeichert sind), treten wahrscheinlich Probleme und Ausnahmen/Abstürze auf.

  • Bei Verwendung eines Telefons nahmen etwa 2 Sekunden Schwarz 2,2 MB in Anspruch, 2 Sekunden der eigentlichen Aufnahme eines Videos belegten 7 MB.

Obwohl SQLite die Fähigkeit hat, relativ große BLOBs zu speichern, wie pro :-

  • Maximale Länge eines Strings oder BLOBs

    Die maximale Anzahl von Bytes in einem String oder BLOB in SQLite wird durch das Präprozessormakro SQLITE_MAX_LENGTH definiert. Der Standardwert dieses Makros ist 1 Milliarde (1 Milliarde oder 1.000.000.000). Sie können diesen Wert zur Kompilierzeit mit einer Befehlszeilenoption wie dieser erhöhen oder verringern:

    -DSQLITE_MAX_LENGTH=123456789 Die aktuelle Implementierung unterstützt nur eine Zeichenfolgen- oder BLOB-Länge bis zu 231-1 oder 2147483647. Und einige eingebaute Funktionen wie hex() könnten lange vor diesem Punkt fehlschlagen. Bei unsicheren Anwendungen ist es am besten, nicht zu versuchen, die maximale String- und Blob-Länge zu erhöhen. Tatsächlich könnten Sie gut daran tun, die maximale String- und Blob-Länge auf etwas mehr im Bereich von ein paar Millionen zu verringern, wenn dies möglich ist.

    Während eines Teils der INSERT- und SELECT-Verarbeitung von SQLite wird der vollständige Inhalt jeder Zeile in der Datenbank als einzelnes BLOB codiert. Der Parameter SQLITE_MAX_LENGTH bestimmt also auch die maximale Anzahl von Bytes in einer Zeile.

    Die maximale Zeichenfolgen- oder BLOB-Länge kann zur Laufzeit mithilfe der Schnittstelle sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) verringert werden. Beschränkungen in SQLite

Das CursorWindow des Android SDK hat eine Begrenzung von 2 MB und das gilt für alle Spalten der Zeile(n), wenn Puffer vorhanden sind. Daher können Sie diese Videos möglicherweise nicht abrufen, selbst wenn Sie Videos erfolgreich speichern können.

Der empfohlene Weg ist, was Sie nicht wollen, nämlich den Pfad zum Video zu speichern.

Wenn ich das Video in meinem internen/externen Speicher speichere und stattdessen den Pfad speichere, wie kann ich dann von einem anderen Gerät darauf zugreifen.

Sie hätten das gleiche Problem mit der Datenbank da es normalerweise in den geschützten Anwendungsdaten gespeichert ist. Es sei denn, die Datenbank ist eine bereits vorhandene Datenbank (d. h. mit Daten gefüllt). In diesem Fall wird die Datenbank mit der App über das APK verteilt.

Wenn letzteres eine bereits vorhandene Datenbank ist, die über die APK verteilt wird, dann können die Videos auch als Teil der APK verteilt werden und sind daher genauso geschützt wie und verfügbar wie die Datenbank.

Wenn Sie beabsichtigen, Videos zwischen Geräten zu verteilen, die nicht Teil des APK sind, ist SQLite wahrscheinlich nicht die richtige Lösung, da es sich um eine eingebettete Datenbank handelt und keine Client/Server-Funktionalität integriert ist.

Außerdem verliere ich alle Daten, wenn mein Gerät formatiert wird.

In einem solchen Szenario wäre die Datenbank genauso anfällig wie alle anderen Daten , denn das ist alles, was die Datenbank ist, eine Datei, genau wie ein Video, ein Word-Dokument usw., die alle eine geeignete Anwendung benötigen, um den Inhalt anzuzeigen / zu ändern. Wenn es sich bei der Datenbank jedoch um eine bereits vorhandene Datenbank handelt, würde eine einfache Neuinstallation der App die Datenbank und andere Dateien aus dem APK wiederherstellen.

Arbeitsbeispiel

Dies verwendet die empfohlene/empfohlene Methode, vorausgesetzt, die Videos sollen mit dem APK verteilt werden.

  • Hinweisvideos Mit freundlicher Genehmigung von Beispielvideos

Nach dem Erstellen eines neuen Projekts wurden 4 Videos heruntergeladen und in den res/raw-Ordner kopiert (nach dem Erstellen des Raw-Ordners) gemäß :-

Der Database Helper (Unterklasse von SQLiteOpenHelper) wurde für eine 2-Spalten-Tabelle mit einer _id erstellt Spalte (Notiz namens _id zur Verwendung mit SimpleCursorAdapter ).- video_path zum Speichern des Pfads/Namens des Videos (nicht der vollständige Pfad, aber ausreichend, um den Pfad anhand der gespeicherten Daten bestimmen zu können)- Hinweis:UNIQUE wurde codiert, um das Hinzufügen von Duplikaten zu verhindern.

Mit einer grundlegenden Methode, um das Hinzufügen und Löschen von Zeilen und das Extrahieren aller Zeilen zu ermöglichen (über einen Cursor zur Verwendung mit dem 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);
    }
}

Eine ziemlich unkomplizierte MainActivity.java (siehe Kommentare)

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

Ergebnisse

Beim ersten Start (nichts spielt):-

Nach langem Klicken auf das 1-MB-Video (Löschen des DB-Eintrags) :-

Nachdem Sie auf ein Video in der Liste geklickt haben:-