Saya ingin menyimpan video di database sqlite. P.S. Saya tidak ingin menyimpan jalurnya tetapi konten video yang sebenarnya.
Kecuali jika video sangat pendek dan memakan sedikit ruang (katakanlah masing-masing hingga 200rb, mungkin 1/10 detik tetapi akan bergantung pada format penyimpanannya), maka Anda mungkin akan mengalami masalah dan pengecualian/gangguan.
- Menggunakan ponsel sekitar 2 detik hitam menghabiskan 2,2Mb, 2 detik sebenarnya merekam video menghabiskan 7Mb.
Meskipun SQLite memiliki kemampuan untuk menyimpan BLOB yang relatif besar sesuai :-
Panjang maksimum string atau BLOB
Jumlah maksimum byte dalam string atau BLOB di SQLite ditentukan oleh makro praprosesor SQLITE_MAX_LENGTH. Nilai default makro ini adalah 1 miliar (1 ribu juta atau 1.000.000.000). Anda dapat menaikkan atau menurunkan nilai ini pada waktu kompilasi menggunakan opsi baris perintah seperti ini:
-DSQLITE_MAX_LENGTH=123456789 Implementasi saat ini hanya akan mendukung string atau panjang BLOB hingga 231-1 atau 2147483647. Dan beberapa fungsi bawaan seperti hex() mungkin gagal sebelum titik itu. Aplikasi yang peka terhadap ketidakamanan, sebaiknya jangan mencoba menambah panjang string dan gumpalan maksimum. Sebenarnya, Anda mungkin melakukannya dengan baik untuk menurunkan panjang string dan gumpalan maksimum menjadi sesuatu yang lebih dalam kisaran beberapa juta jika memungkinkan.
Selama bagian dari pemrosesan INSERT dan SELECT SQLite, konten lengkap dari setiap baris dalam database dikodekan sebagai BLOB tunggal. Jadi parameter SQLITE_MAX_LENGTH juga menentukan jumlah byte maksimum dalam satu baris.
Panjang string atau BLOB maksimum dapat diturunkan saat run-time menggunakan antarmuka sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size). Batas Dalam SQLite
CursorWindow Android SDK memiliki batasan 2Mb dan itu untuk semua kolom dari baris jika buffer. Dengan demikian, meskipun Anda berhasil menyimpan Video, Anda mungkin tidak dapat mengambil Video tersebut.
Cara yang disarankan adalah yang tidak Anda inginkan, yaitu menyimpan jalur ke Video.
Jika saya menyimpan video di penyimpanan internal/eksternal saya dan menyimpan jalurnya, lalu bagaimana saya dapat mengaksesnya dari perangkat lain.
Anda akan memiliki masalah yang sama dengan database karena biasanya disimpan dalam data Aplikasi yang dilindungi. Itu kecuali database adalah database yang sudah ada sebelumnya (yaitu diisi dengan data), dalam hal ini database didistribusikan dengan Aplikasi melalui APK.
Jika yang terakhir, database yang sudah ada sebelumnya didistribusikan melalui APK, maka video juga dapat didistribusikan sebagai bagian dari APK dan karenanya dilindungi dan dapat diekspos seperti database.
Jika tujuan Anda adalah untuk mendistribusikan video antar perangkat yang bukan bagian dari APK, maka SQlite mungkin bukan solusi yang tepat karena merupakan basis data tertanam dan tidak memiliki fungsionalitas klien/server bawaan.
Selain itu bagaimana jika perangkat saya diformat maka saya akan kehilangan semua data.
Dalam skenario seperti itu, basis data akan sama rentannya dengan data lainnya , karena hanya itu basis datanya, file, seperti video, dokumen kata, dll. yang semuanya memerlukan aplikasi yang sesuai untuk melihat/mengubah konten. Namun, jika database adalah database yang sudah ada sebelumnya, maka cukup menginstal ulang Aplikasi akan memulihkan database dan file lain dari APK.
Contoh Kerja
Ini menggunakan metode Disarankan/Direkomendasikan dengan asumsi video didistribusikan dengan APK.
- Catatan Video Atas izin Contoh Video
Setelah membuat proyek baru, 4 video diunduh dan disalin ke folder res/raw (setelah membuat folder mentah) sesuai :-
Database Helper (subclass dari SQLiteOpenHelper) dibuat untuk tabel 2 kolom dengan- _id kolom (catatan bernama _id untuk digunakan dengan SimpleCursorAdapter ).- video_path untuk menyimpan jalur/nama video (bukan jalur lengkap tetapi cukup untuk dapat menentukan jalur dari data yang disimpan)- Catatan UNIK telah dikodekan untuk menghentikan penambahan duplikat.
Dengan beberapa metode dasar untuk memungkinkan baris ditambahkan dan dihapus dan untuk semua baris diekstraksi (melalui Kursor untuk digunakan dengan 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 yang cukup lurus ke depan (lihat komentar)
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());
}
}
}
Hasil
Saat pertama kali dimulai (tidak ada yang diputar):-
Setelah lama mengklik video 1Mb (menghapus entri DB):-
Setelah mengklik Video di Daftar :-