I'm developing an application. I need to use at least 400 audio files which can be played for some respective texts. My question is which is the best and optimized way to do this?
One solution is putting all the audio files in the resources folder and referring from there. This will never be a feasible solution as the application size will increase. Is there any way to convert the audio file into some format and dump into the SQLite database and retrieve them flexibly? If so, what options do I have?
Storing the files as BLOB in a SQLite db will not save you any space vs storing them as files. If these files are not meant to be associated to any dynamic data, I would just put them in assets folders, that way they'll be compiled into the APK and might be a tad faster to retrieve that if they were in a db.
try the following code... it stored for me.....
#Override
public void onClick(View arg0) {
SQLiteDatabase myDb;
String MySQL;
byte[] byteImage1 = null;
byte[] byteImage2 = null;
MySQL="create table emp1(_id INTEGER primary key autoincrement, sample TEXT not null, picture BLOB);";
myDb = openOrCreateDatabase("Blob List", Context.MODE_PRIVATE, null);
myDb.execSQL(MySQL);
String s=myDb.getPath();
textView.append("\r\n" + s+"\r\n");
myDb.execSQL("delete from emp1");
ContentValues newValues = new ContentValues();
newValues.put("sample", "HI Hello");
try
{
FileInputStream instream = new FileInputStream("/sdcard/AudioRecorder/AudioRecorder.wav");
BufferedInputStream bif = new BufferedInputStream(instream);
byteImage1 = new byte[bif.available()];
bif.read(byteImage1);
textView.append("\r\n" + byteImage1.length+"\r\n");
newValues.put("picture", byteImage1);
long ret = myDb.insert("emp1", null, newValues);
if(ret<0) textView.append("\r\n!!! Error add blob filed!!!\r\n");
} catch (IOException e)
{
textView.append("\r\n!!! Error: " + e+"!!!\r\n");
}
Cursor cur = myDb.query("emp1",null, null, null, null, null, null);
cur.moveToFirst();
while (cur.isAfterLast() == false)
{
textView.append("\r\n" + cur.getString(1)+"\r\n");
cur.moveToNext();
}
///////Read data from blob field////////////////////
cur.moveToFirst();
byteImage2=cur.getBlob(cur.getColumnIndex("picture"));
bmImage.setImageBitmap(BitmapFactory.decodeByteArray(byteImage2, 0, byteImage2.length));
textView.append("\r\n" + byteImage2.length+"\r\n");
cur.close();
myDb.close();
}
});
Anybody correct me if I'm wrong, but SQLite has an restriction of total row size < 1024kb. If all of your audio files are small enough, you could store them as BLOBs.
The main reason for storing sound files on database might be product line approach. You can develop many many similar applications by just modifying your database and not touching your code.
I do not comment on application size because there are comments about it and I do not look at it.
Yes. You can store your small sized sound files in sqlite database as blob fields. It works well. First store your data in database then retrieve it and put it in a temp file. That way you can store your sound files in database.
Check this:
soundDataFile = File.createTempFile( "sound", "sound" );
FileOutputStream fos = new FileOutputStream( soundDataFile );
fos.write( soundData );
fos.close();
mediaPlayer.reset();
mediaPlayer.setDataSource( soundDataFile.getAbsolutePath() );
mediaPlayer.prepare();
mediaPlayer.start();
What is the motivation behind storing the files in the sql lite db? I dont see much benefit to that over storing the file path in the db, and the actual file on the file system...
Related
It was working very well. But when i put image broked. Before doesn´t exist "foto". But I need save a property type BLOB. But I dont´t know why is broking.
Bitmap bitmap = imageViewProeto.getDrawingCache();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
if(bitmap != null){
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
}
//byte[] data = baos.toByteArray();
byte[] data = stream.toByteArray();
bitmap.recycle();
boolean isOk = validarCampos();
if(!isOk){
String query = "INSERT INTO projetos (nome, descricao, url, foto, voluntario_id ) " +
"VALUES ('"+ nomeDigitado +"','"+descricaoDigitada+ "','"+urlDigitada+"', "+ data +" , " + testeId + ")";
bancoDados.execSQL(query);
A blob needs to be inserted as a string of hex numbers enclosed in single quotes and prefixed by x e.g.
"INSERT INTO projetos (nome, descricao, url, foto, voluntario_id ) " +
"VALUES ('"+ nomeDigitado +"','"+descricaoDigitada+ "','"+urlDigitada+"', x'000102030405060708090a0b0c' , " + testeId + ")";
x'000102030405060708090a0b0c' is just an example of the format using some arbritary value that would very likely not be an image.
As such you'd need to convert the byte[] to the respective value. However, if you use the SQLiteDatabase insert convenience method rather then execSQL then the conversion is performed by the method and thus the value can be passed as a byte[].
e.g. you could use :-
ContentValues() cv = new ContentValues();
cv.put(nome,nomeDigitado);
cv.put(nomeDigitado,descricaoDigitada);
cv.put(foto,data);
cv.put(voluntario_id,testeId);
cv.put(url,urlDigitada); //<<<<< note out of order but the correct SQL will be built
long rowid = bancoDados.insert("projetos",null,cv);
In addition to conveniently handling byte[]'s the insert method also has the fowlling advantages :-
it returns the rowid of the inserted row or -1 if the row was not inserted.
it also offers protection against SQL Injection.
it builds the underlying SQL (for insertion via VALUES)
HOWEVER, if the byte[] is around 2MB or greater then you will not be able to retrieve the BLOB as there is a 2MB size limit for a Cursor Window (a buffer into which complete rows are placed). There may also be issues with smaller byte[] as the process for retrieving the data can be relatively slow.
It is recommended to rather save the path to the respective image which is stored as a file. However, saving images (byte[]) as BLOBs that are around about 100KB can be more efficient.
I need to open a database from my phone's memory (/storage/emulated/0) and I've got "SQLiteCantOpenDatabaseException" the database to open (created by DB browser from linux) have the tables "android_metadata" and them respective fields (locale...es_US).
I need open and read data from the external db (the app need to download the db from website and read data and put in textview into the app activities )
The app has permission to read and write external memory
code below (only the code of button to get the database reference)
case R.id.button4:
{
int ID,IDn,IDa;
String cabeceras[] ={"nombre","apellido",_ID},lectura=new String(),err="";
ArrayList<String> arregloDatos = new ArrayList<>();
try {
SQLiteDatabase db = SQLiteDatabase.openDatabase(Environment.getExternalStorageDirectory().getPath() +"/"+"pruebaDB.db", null, SQLiteDatabase.OPEN_READWRITE);
Cursor cursor = db.query("persona", cabeceras, null, null, null, null, null);
ID = cursor.getColumnIndex(_ID);
IDn = cursor.getColumnIndex("nombre");
IDa = cursor.getColumnIndex("apellido");
while (cursor.moveToNext()) {
lectura = cursor.getString(ID) + " " + cursor.getString(IDn) + " " + cursor.getString(IDa);
arregloDatos.add(lectura);
}
Intent i = new Intent(this, Main2Activity.class);
i.putStringArrayListExtra("cadena", arregloDatos);
startActivity(i);
}catch (Exception g)
{
Toast msg =Toast.makeText(this,g.getClass().toString(),Toast.LENGTH_SHORT);
msg.show();
}
break;
}
Edit: i find the problem, the problem is the cursor, becose i comment it and the app not show any exception.
now...my problem is "how to read data from SQliteDatabase object"
I don't think you are able to write SQLDatabases to external. If it is all string or int data, you could write the Database to internal, then write a function that will iterate through the table and concatenate the data and write it to external as a .txt.
Yep, just read the documentation on the .openDatabase method. I think the first param is looking for the path portion of the content URI, not an ext memory file path.
https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#openDatabase(java.lang.String,%20android.database.sqlite.SQLiteDatabase.CursorFactory,%20int,%20android.database.DatabaseErrorHandler)
I am doing a project on Contacts For this , I need to Import/Store Pictures in SQlite DataBase.From what I have read , I have to convert the picture into a different format (maybe wrong in this assumption) and then store it in the data Base . Can you please tell me how can I do it or can I use a different method to do it?Both would be helpful for me , so that I can learn a bit more.
Thank You,
Depending on where you want to get the picture from, whether from the internet or from the sdcard. However, I'm assuming that you can get it and convert it into a bitmap.
Bitmap bm = (get it from anywhere);
ByteArrayOutputStream blob = new ByteArrayOutputStream();
//the below line is used if you like to scale it down to store it into the database
bm = Bitmap.createScaledBitmap(bm, width, height, false);
//then put it into a byte array to store it in the database
bm.compress(CompressFormat.JPEG, 100, blob);
// method call to database
dbClass.addPicture(blob.toByteArray());
Table definition in the database:
SQLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS Pictures (id integer primary key autoincrement, pic blob not null ");
addPicture method in the database class is as the following
public void addPicture(byte[] picture){
db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("pic", picture);
db.insert("Pictures ", null, cv);
}
I hope that helps
I've developed a Backup application. Now, it could takes backup for contacts, settings and browser I would take these backups by that host like
Backup bu = new Backup(this);
bu.runBackup(Contacts.People.CONTENT_URI);
bu.runBackup(Settings.System.CONTENT_URI);
bu.runBackup(Browser.SEARCHES_URI);
I've use gethost method in Backup class like
int count=0;
String file = uri.getHost() +"-"+ System.currentTimeMillis();
Cursor cursor = cr.query(uri, null, null, null, null);
count = cursorToCSV(cursor, file);
cursor.close();
String msg = String.format("Backed up %d records to %s file", count, file);
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
return count;
I would like to take backup for media files images, videos, musics Is it possible to do that? How can i do like this? Anyone knows mean tell me otherwise what's the alternate way?
I've done this by my own Coding...
bu.runBackup(Images.Media.CONTENT_URI);
bu.runBackup(Video.Media.CONTENT_URI);
bu.runBackup(Audio.Media.CONTENT_URI);
I have an SQLite DB with a sample table, which is stored in the assets/ folder.
This DB contains a single table, one of the columns is BLOB containing a BMP image. I may read/write this image flawlessly using JDBC on the host machine.
Then the data is accessed from the emulator using the following code:
final Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, null);
if (cursor.moveToFirst()) {
byte[] icon = cursor.getBlob(cursor.getColumnIndex(SearchEngines.ICON));
// ...
But the attempt to decode retreived image fails:
final Bitmap icon = BitmapFactory.decodeByteArray(icon , 0, icon.length);
I get null result and the following in the log:
DEBUG/skia(374): --- decoder->decode returned false
After this, I dumped the blob array into the file and compared with the original image. And it was a complete surprise, because the only uncovered difference was that all the 0x00 bytes were replaced with 0x25 0x30 sequences in the retreived blob:
0x00 -> 0x25 0x30 // %0
Besides that, all the data was intact. What the heck?
Update 1. After pulling the DB from the emulator (adb pull) the data it contains is corrupted (same %0 symbols). So, the problem is either in DB itself or implementation/usage of query/getBlob or other DB access code.
Update 2. *Seems that it's wrong* As far as I understand, SQLite supports 2 ways of storing large objects: TEXT and BLOB. TEXT columns don't contain 0x00 bytes, and in BLOBs 0x00 is translated into %0 (what a coincidence!). So, it seems that what I get is internal representation, not the actual data.
Update 3. Code for adding to DB is the following:
private void save(Connection conn, String id, String fileName) throws SQLException, IOException {
final String sql = "UPDATE " + TABLE_NAME + " SET " + BLOB_COLUMN_NAME + " = ? WHERE " + ID_COLUMN_NAME + " = ?";
System.out.println("Executing: " + sql);
final PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(2, Integer.valueOf(id));
File fBlob = new File(fileName);
FileInputStream is = new FileInputStream(fBlob);
byte[] bytes = new byte[(int) fBlob.length()];
int rc = is.read(bytes);
assert (rc == bytes.length);
System.out.println("Total size: " + rc);
pstmt.setBytes(1, bytes);
pstmt.execute();
}