Is there a way to copy sqlite database from external storage to assets at run time and then use it ? or is there a way to copy the ready sqlite from external storage to below path at run time and then read it in app? context.getDatabasepath. I have problem with the copying process, please help me because I got this error :
can't open file
My question may look like a duplicate but I couldn't find the answer.
public void copyDataBase() throws IOException
{
try
{
String inputDB = Environment.getExternalStorageDirectory().getPath() + "/test.sqlite" ;
File input = new File(inputDB);
InputStream myInput = new FileInputStream(input);
String outputFileName = databasePath + DATABASE_NAME ;
OutputStream myoutput = new FileOutputStream(outputFileName) ;
byte[] buffer = new byte[1024];
int length;
while((length = myInput.read(buffer))>0)
{
myoutput.write(buffer,0,length);
}
myoutput.flush();
myoutput.close();
myInput.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
I think the file should be opened first then we give it to the input stream because error was like : can't open the file. Please help me.
Related
I am using GreenDAO as ORM and using a pre-populated database which is encrypted by SQLite Cipher. Encryption is the feature of GreenDAO. So when a user launches the application I am using below code to copy the database from asset to phone memory.
ContextWrapper cw =new ContextWrapper(context);
if (android.os.Build.VERSION.SDK_INT >= 17) {
DB_PATH = cw.getApplicationInfo().dataDir + "/databases/";
} else {
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}
byte[] buffer = new byte[1024];
OutputStream myOutput = null;
int length;
InputStream myInput = null;
try
{
myInput = mContext.getAssets().open(DB_NAME);
myOutput =new FileOutputStream(DB_PATH+ DB_NAME);
while((length = myInput.read(buffer)) > 0)
{
myOutput.write(buffer, 0, length);
}
myOutput.close();
myOutput.flush();
myInput.close();
But on some device, it is showing following error
"Exception java.io.FileNotFoundException: /data/user/0/com.example.appname/databases/my-db.db: open failed: ENOENT (No such file or directory) "
and according to firebase crash report the below line is responsible for the error.
myOutput =new FileOutputStream(DB_PATH+ DB_NAME);
How can I solve this and can ensure that the database will work in all device. However I am using below code to check database exist or not
File file = new File(DB_PATH+ DB_NAME);
if(file.exists()) {
}
The directory
/data/user/0/com.example.appname/databases
does not exist yet.
Before you try to write a file in it check if the directory exists and if not create it.
if(file.getParentFile().exists())
if(!file.getParentFile().mkdirs())
return false.
public void copyDbToInternalFolder() throws IOException {
String DB_PATH = Environment.getDataDirectory().getPath()+getPackageName()+"/Databases/"; // Don't worry I know this line doesn't work, however, nothing was working
String DB_NAME = "Client_Responses.db";
InputStream myInput = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS,"Client_Responses.db"); //needs to get database file from Downloads folder
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
I have written several related apps that create sqlite database files in the devices Downloads folder. I need to stick to this method in order to support all the way back to first generation tablets. API 8 in essence.
Now, the manager needs to import found files from the Downloads folder and import them to its own database folder.
The above code doesn't work, null pointer exceptions and incorrect filename/pathname create errors and the app will force quit, and I have tried what seems like everything. My thinking is now bottlenecked.
I have been struggling with this and would welcome input.
Note: I will most likely duplicate the code in different class files, each copying a differing database name.
private void copyDbToInternalFolder() throws IOException {
String ToDB_PATH = "/data/data/"+this.getPackageName()+"/databases/";
String sourcePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Client_Responses.db";
File source = new File(sourcePath);
String destinationPath = ToDB_PATH + "/" + DB_NAME;
File destination = new File(destinationPath);
try
{
FileUtils.copyFile(source, destination);
}
catch (IOException e)
{
e.printStackTrace();
}
}
This seems to work on Android4.2.2 tablet but not on the emulator. I cannot work out whether the issue is the emulator and how it handles the path creation, or if its API8 that cannot understand them. If anyone has any suggestions I would be grateful. So the issue is only partially answered.
This question already has answers here:
How do I view the SQLite database on an Android device? [duplicate]
(19 answers)
Closed 7 years ago.
How can I get the database of my application running on my phone.
I use Android Studio and my database is in assets>MyDataBase.db
Is there a way to update this file ?
I have my own sqlite database, I insert data then I want to get the file back with the new data.
I don't use the emulator and my database was created by SQLite Browser.
[EDIT]
People said it was a duplicate of this question.
But I want to do the same in code line not in command.
If you want to edit file in assets folder of your app in Runtime - this is not possible. you should copy this DB to internal/external storage and edit it after that.
Yes you can edit in in many ways. One of them is using libraries such as this. Give it a look and try it in your app.
You cannot write data's to asset/Raw folder, since it is packed(.apk), the assets folder is read-only at runtime.
You need to choose a different storage location, here is a method to backup you db to your sdcard (external storage) dbName=MyDataBase.db in your case:
public static void backupDBonSDcard(Context context, String dbName){
String DB_PATH = context.getDatabasePath(dbName).getPath();
Log.d("DB_PATH:" + DB_PATH);
if(checkDataBase(DB_PATH)){
InputStream myInput;
try {
Log.e("[backupDBonSDcard] saving file to SDCARD");
myInput = new FileInputStream(DB_PATH);
// Path to the just created empty db
String outFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + java.io.File.separator + dbName;
//Open the empty db as the output stream
OutputStream myOutput;
try {
myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
} catch (FileNotFoundException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//Close the streams
if(myOutput!=null){
myOutput.flush();
myOutput.close();
}
if(myInput!=null)
myInput.close();
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}else{
Log.d("DB "+dbName+" not found");
}
}
public static boolean checkDataBase(String fileName) {
java.io.File dbFile = new java.io.File(fileName);
return dbFile.exists();
}
Don't forget to add the following permission in your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I want to send the database file of my app via email. This makes my it easier to help in a error case. For that I need to retrieve the installation folder of my app. How can I achieve this so that i can send my db which is place here APP-FOLDER\databases\mydb.db
Thanks
Hope, you are asking about the strategy or where to start to do so.
There are several approaches you can follow,
1) Save your db file to the sdcard then it will be available to you for your mailing function. You can achieve this by using SQLiteDatabase.openOrCreateDatabase(String, SQLiteDatabase.CursorFactory) and simply pass "/sdcard/yrdatabase.db" as the first parameter .
2) If you aren't saving it to the sdcard, then simply move your db file to the sdcard. You can achieve this by using following code. (i.e. bind the below function to your button or anyhow call it from your app)
public void copyDBToSDCard() {
try {
InputStream myInput = new FileInputStream("/data/data/com.yrproject/databases/"+DATABASE_NAME);
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/"+DATABASE_NAME);
if (!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
Log.i("TAG","File creation failed for " + file);
}
}
OutputStream myOutput = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/"+DATABASE_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
Log.i("TAG","copied");
} catch (Exception e) {
Log.i("TAG","exception="+e);
}
}
Once you are done with the accessing db file, you can use mail functions to use it further.
I think that this is rather easy question. I am too young in android stuff already. I want to prepare application which will be using database. In every example I've shown, there is an empty database where application is firstly started and after that there are some inserts. I want to have app with rather big db so I want to have filled db when app is started. How can I prepare db and attach it to program?
put your filled database in Package's Asset directory,
at application runtime just copy that database to application's internal storage like
data/data/<package name>/database directory.
then use it.
EDIT: this for copy database from asset directory to database directory,
private void copyDataBase() throws IOException {
try {
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open("your Database file name");
// Path to the just created empty db
String outFileName = "/data/data/<package name>/databases/";
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
} catch (Exception e) {
Log.e("error", e.toString());
}
}