मैं sqlite डेटाबेस में एक वीडियो स्टोर करना चाहता हूं। पी.एस. मैं पथ को नहीं बल्कि वास्तविक वीडियो सामग्री को संग्रहीत करना चाहता हूं।
जब तक वीडियो बहुत छोटे न हों और कम जगह लेते हों (जैसे कि 200k तक, शायद एक सेकंड का 1/10वां, लेकिन यह उस प्रारूप पर निर्भर करेगा जिसमें यह सहेजा गया है) तब आपको समस्याओं और अपवादों/क्रैश का सामना करना पड़ सकता है।
- फ़ोन का उपयोग करने में लगभग 2 सेकंड का काला समय 2.2Mb, वास्तव में एक वीडियो रिकॉर्ड करने में 2 सेकंड में 7Mb लगता है।
हालांकि SQLite में सापेक्ष बड़े BLOB के अनुसार स्टोर करने की क्षमता है :-
एक स्ट्रिंग या BLOB की अधिकतम लंबाई
SQLite में एक स्ट्रिंग या BLOB में बाइट्स की अधिकतम संख्या प्रीप्रोसेसर मैक्रो SQLITE_MAX_LENGTH द्वारा परिभाषित की जाती है। इस मैक्रो का डिफ़ॉल्ट मान 1 बिलियन (1 हजार मिलियन या 1,000,000,000) है। आप इस तरह के कमांड-लाइन विकल्प का उपयोग करके संकलन-समय पर इस मान को बढ़ा या घटा सकते हैं:
-DSQLITE_MAX_LENGTH=123456789 वर्तमान कार्यान्वयन केवल 231-1 या 2147483647 तक की स्ट्रिंग या BLOB लंबाई का समर्थन करेगा। और कुछ अंतर्निहित फ़ंक्शन जैसे hex() उस बिंदु से पहले अच्छी तरह से विफल हो सकते हैं। असुरक्षा के प्रति संवेदनशील अनुप्रयोग अधिकतम स्ट्रिंग और ब्लॉब लंबाई को बढ़ाने का प्रयास नहीं करना सबसे अच्छा है। वास्तव में, यदि संभव हो तो आप अधिकतम स्ट्रिंग और ब्लॉब लंबाई को कुछ मिलियन की सीमा में कुछ और कम करने के लिए अच्छा कर सकते हैं।
SQLite के INSERT और SELECT प्रसंस्करण के दौरान, डेटाबेस में प्रत्येक पंक्ति की पूर्ण सामग्री को एकल BLOB के रूप में एन्कोड किया जाता है। सोथ SQLITE_MAX_LENGTH पैरामीटर एक पंक्ति में बाइट की अधिकतम संख्या भी निर्धारित करता है।
अधिकतम स्ट्रिंग या BLOB लंबाई को thesqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) इंटरफ़ेस का उपयोग करके रन-टाइम पर कम किया जा सकता है। SQLite में सीमाएं
Android SDK का कर्सरविंडो 2Mb की सीमा है और यह बफ़र्स के सभी स्तंभों के लिए है। इसलिए यदि आप वीडियो को सफलतापूर्वक संग्रहीत कर सकते हैं, तो भी आप उन वीडियो को पुनः प्राप्त करने में सक्षम नहीं हो सकते हैं।
अनुशंसित तरीका वह है जो आप नहीं चाहते हैं, वह है वीडियो का पथ संगृहीत करना।
<ब्लॉकक्वॉट>अगर मैं वीडियो को अपने आंतरिक/बाहरी स्टोरेज में स्टोर करता हूं और इसके बजाय पथ को स्टोर करता हूं तो मैं इसे किसी अन्य डिवाइस से कैसे एक्सेस कर पाऊंगा।
डेटाबेस के साथ आपकी भी यही समस्या होगी क्योंकि यह आमतौर पर एप्लिकेशन डेटा के भीतर संग्रहीत होता है जो संरक्षित होता है। यह तब तक है जब तक कि डेटाबेस पहले से मौजूद डेटाबेस (यानी डेटा से भरा हुआ) न हो, उस स्थिति में डेटाबेस को एपीके के माध्यम से ऐप के साथ वितरित किया जाता है।
यदि बाद वाला, एपीके के माध्यम से वितरित एक पूर्व-मौजूदा डेटाबेस है, तो वीडियो को एपीके के हिस्से के रूप में भी वितरित किया जा सकता है और इसलिए डेटाबेस के रूप में संरक्षित और एक्सपोज़ेबल के रूप में।
यदि आपका इरादा उन उपकरणों के बीच वीडियो वितरित करना है जो एपीके का हिस्सा नहीं हैं तो एसक्यूलाइट शायद सही समाधान नहीं है क्योंकि यह एक एम्बेडेड डेटाबेस है और इसमें कोई क्लाइंट/सर्वर कार्यक्षमता नहीं है।
<ब्लॉकक्वॉट>इसके अलावा अगर मेरा डिवाइस फॉर्मेट हो जाता है तो मैं सारा डेटा खो दूंगा।
ऐसे परिदृश्य में, डेटाबेस किसी भी अन्य डेटा की तरह असुरक्षित होगा , जैसा कि सभी डेटाबेस है, एक फ़ाइल, एक वीडियो की तरह, एक शब्द दस्तावेज़ आदि जिसे सामग्री को देखने/बदलने के लिए सभी को उपयुक्त एप्लिकेशन की आवश्यकता होती है। हालाँकि, यदि डेटाबेस पहले से मौजूद डेटाबेस है, तो बस ऐप को फिर से इंस्टॉल करने से डेटाबेस और अन्य फ़ाइलों को एपीके से पुनर्स्थापित कर दिया जाएगा।
कार्य उदाहरण
यह मानते हुए कि वीडियो को APK के साथ वितरित किया जाना है, यह सुझाई गई/अनुशंसित विधि का उपयोग करता है।
- नोट वीडियो नमूना वीडियो . के सौजन्य से
नया प्रोजेक्ट बनाने के बाद 4 वीडियो डाउनलोड किए गए और उन्हें रेस/रॉ फोल्डर (रॉ फोल्डर बनाने के बाद) में कॉपी किया गया::-
डेटाबेस हेल्पर (SQLiteOpenHelper का उपवर्ग) एक 2 कॉलम टेबल के लिए बनाया गया था- _id कॉलम (नोट नाम _id SimpleCursorAdapter के साथ प्रयोग के लिए ).- वीडियो के पथ/नाम को संग्रहीत करने के लिए video_path (पूर्ण पथ नहीं बल्कि संग्रहीत डेटा से पथ निर्धारित करने में सक्षम होने के लिए पर्याप्त है)- नोट डुप्लिकेट को जोड़े जाने से रोकने के लिए UNIQUE को कोडित किया गया है।
पंक्तियों को जोड़ने और हटाने की अनुमति देने के लिए और सभी पंक्तियों को निकालने के लिए कुछ बुनियादी विधि के साथ (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 प्रविष्टि को हटाते हुए) :-
सूची में एक वीडियो क्लिक करने के बाद:-