SQLite
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> SQLite

Cách lưu trữ nội dung video trong cơ sở dữ liệu SQLite (không phải đường dẫn video)

Tôi muốn lưu trữ một video trong cơ sở dữ liệu sqlite. P.S. Tôi không muốn lưu trữ đường dẫn mà là lưu trữ nội dung video thực tế.

Trừ khi video rất ngắn và chiếm ít dung lượng (giả sử mỗi video lên đến 200 nghìn, có lẽ là 1/10 giây nhưng sẽ phụ thuộc vào định dạng video được lưu) thì bạn có thể gặp phải sự cố và ngoại lệ / sự cố.

  • Sử dụng điện thoại màu đen khoảng 2 giây chiếm 2,2Mb, thực tế quay video 2 giây chiếm 7Mb.

Mặc dù SQLite có khả năng lưu trữ BLOB tương đối lớn theo:-

  • Độ dài tối đa của một chuỗi hoặc BLOB

    Số byte tối đa trong một chuỗi hoặc BLOB trong SQLite được xác định bằng macro bộ xử lý trước SQLITE_MAX_LENGTH. Giá trị mặc định của thismacro là 1 tỷ (1 nghìn triệu hoặc 1.000.000.000). Bạn có thể tăng hoặc giảm giá trị này tại thời điểm biên dịch bằng cách sử dụng tùy chọn dòng lệnh như sau:

    -DSQLITE_MAX_LENGTH =123456789 Việc triển khai hiện tại sẽ chỉ hỗ trợ một chuỗi hoặc BLOB độ dài tối đa 231-1 hoặc 2147483647. Và một số hàm tích hợp như hex () có thể bị lỗi trước thời điểm đó. Các ứng dụng nhạy cảm với bảo mật, tốt nhất là không nên cố gắng tăng độ dài chuỗi và đốm màu tối đa của chúng. Trên thực tế, bạn có thể làm tốt việc hạ thấp độ dài chuỗi và đốm màu tối đa xuống một thứ gì đó cao hơn trong khoảng afew triệu nếu điều đó có thể.

    Trong quá trình xử lý CHÈN và CHỌN của SQLite, nội dung hoàn chỉnh của mỗi hàng trong cơ sở dữ liệu được mã hóa thành một BLOB duy nhất. Tham số Sothe SQLITE_MAX_LENGTH cũng xác định số byte tối đa trong một hàng.

    Chuỗi hoặc độ dài BLOB tối đa có thể được giảm xuống tại thời điểm chạy bằng giao diện thesqlite3_limit (db, SQLITE_LIMIT_LENGTH, size).

CursorWindow của Android SDK có giới hạn là 2Mb và đó là đối với tất cả các cột của (các) hàng nếu bộ đệm. Như vậy, ngay cả khi bạn có thể lưu trữ các Video thành công, bạn vẫn không thể truy xuất các Video đó.

Cách được đề xuất là điều bạn không muốn, đó là lưu trữ đường dẫn đến Video.

Nếu tôi lưu trữ video trong bộ nhớ trong / bên ngoài của mình và lưu trữ đường dẫn thay vào đó thì làm cách nào để tôi có thể truy cập video đó từ một thiết bị khác.

Bạn sẽ gặp vấn đề tương tự với cơ sở dữ liệu vì nó thường được lưu trữ trong dữ liệu Ứng dụng được bảo vệ. Đó là trừ khi cơ sở dữ liệu là cơ sở dữ liệu có từ trước (tức là được điền dữ liệu), trong trường hợp đó, cơ sở dữ liệu được phân phối với Ứng dụng thông qua APK.

Nếu sau này, cơ sở dữ liệu tồn tại từ trước được phân phối qua APK, thì video cũng có thể được phân phối như một phần của APK và do đó được bảo vệ như và có thể hiển thị như cơ sở dữ liệu.

Nếu ý định của bạn là phân phối video giữa các thiết bị không phải là một phần của APK thì SQlite có lẽ không phải là giải pháp chính xác vì đây là một cơ sở dữ liệu được nhúng và không có chức năng máy khách / máy chủ được tích hợp sẵn.

Ngoài ra, nếu thiết bị của tôi bị định dạng thì tôi sẽ mất tất cả dữ liệu.

Trong trường hợp như vậy, cơ sở dữ liệu sẽ dễ bị tấn công như bất kỳ dữ liệu nào khác , vì đó là tất cả cơ sở dữ liệu, một tệp, giống như video, tài liệu word, v.v. tất cả đều cần một ứng dụng phù hợp để xem / thay đổi nội dung. Tuy nhiên, nếu cơ sở dữ liệu là cơ sở dữ liệu đã có từ trước, thì chỉ cần cài đặt lại Ứng dụng sẽ khôi phục cơ sở dữ liệu và các tệp khác từ APK.

Ví dụ làm việc

Điều này sử dụng phương pháp Đề xuất / Được đề xuất giả sử video được phân phối bằng APK.

  • Ghi chú Video Phản cảm về Video Mẫu

Sau khi tạo dự án mới, 4 video đã được tải xuống và sao chép vào thư mục res / raw (sau khi tạo thư mục raw) như sau:-

Trình trợ giúp cơ sở dữ liệu (lớp con của SQLiteOpenHelper) đã được tạo cho bảng 2 cột với- _id cột ( ghi chú có tên _id để sử dụng với SimpleCursorAdapter ) .- video_path để lưu trữ đường dẫn / tên của video (không phải là đường dẫn đầy đủ nhưng đủ để có thể xác định đường dẫn từ dữ liệu được lưu trữ) - Lưu ý rằng UNIQUE đã được mã hóa để ngăn các bản sao được thêm vào.

Với một số phương pháp cơ bản để cho phép thêm và xóa các hàng và trích xuất tất cả các hàng (thông qua Con trỏ để sử dụng với 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);
    }
}

Một MainActivity.java khá đơn giản (xem phần bình luận)

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

Kết quả

Khi mới bắt đầu (không có gì phát):-

Sau một lúc nhấp vào video 1Mb (xóa mục nhập DB):-

Sau khi nhấp vào Video trong Danh sách:-



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chèn hoặc cập nhật SQLite cho Android

  2. SQLite - Thả một bảng

  3. selectArgs trong SQLiteQueryBuilder không hoạt động với các giá trị số nguyên trong cột

  4. Tự động tạo khóa tổng hợp trong SQLite

  5. SQLITE không thể nâng cấp cơ sở dữ liệu chỉ đọc từ phiên bản 1 lên 2