Normally to make changes in my Database I followed the following steps:
Edited Database in SQLite
Delete Database in my assets folder
Copy paste Database in assets folder again
Delete the App from my phone through settings
Rebuild/install the app
This worked for me beforehand many times. No I have the issue that somehow my project does not access this database anymore.
I figured that out by deleting the database from my asset folder and reinstalling the app. The App still works, therefore it does not access the database from my asset folder that I used beforehand, to the best of my knowledge.
I am using the following path to access it:
DB_Path = mContext.getDatabasePath(DB_Name).
Log.e("DB_path", DB_Path);
Which yields
.com.example.chris.projectartifact E/DB_path:/data/user/0/com.example.chris.projectartifact/databases/myDB.db.
Regarding the Comment:
I am using the following method to copy my Database.
This is from a tutorial and it worked fine for a very long time.
From my understanding though FileOutputStream(DB_Path)
copies it to named path.
public void copyDataBase(){
try {
InputStream myInput = mContext.getAssets().open(DB_Name);
OutputStream myOutput = new FileOutputStream(DB_Path);
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 (IOException e){
Log.e("Error:","in CopyDatabase, where are in catch..");
e.printStackTrace();
}
}
The Questions:
Where do I find my database in my structure?
How am I able to update it?
New Question: How do i delete my copied database and renew it from my asset folder?
If your db is in your assets folder, its not on the file system at all- its in your assets- its part of the APK file (and thus read only). If you need it to be read write, you need to copy it to the filesystem first, and then you can put it where you want (although in the database path is traditional it isn't enforced).
Related
I have made an android app. I am using database in it. I have installed the .apk file on my phone and it works fine. But it does not show me any data I entered in database while I was on emulator. I need to use database tables filled previously. My database does not create on run time. How can I get the database on my phone to see app running perfectly fine with the database?
You can save your database file under assets or res/raw directory, on the app's first startup, copy that database file to /data/data/com.company.yourapp/databases/, and open your database like usual.
The difference between saving files under assets and res/raw directories is that files under res/raw are compressed, while files under assets are not. And files under res/raw cannot exceed 1 MB before Android 2.3. So I'd suggest that you compress your database file yourself and save it to assets and in your code decompress the file using GZIPInputStream.
If you need your database out side the application for testing then i think you should export it into your sdcard.
public static void exportfile(String applicationPackageName,String databaseName,String pathOfFolder) throws FileNotFoundException, IOException
{
InputStream myInput;
myInput = new FileInputStream("/data/data/"+applicationPackageName+"/databases/"+databaseName);
File directory = new File("/sdcard"+pathOfFolder);
if (!directory.exists())
{
directory.mkdirs();
}
OutputStream myOutput = new FileOutputStream(directory.getPath()+"/"+databaseName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0)
{
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
applicationPackageName :- application package name
databaseName :- database file name
pathOfFolder :- path of folder where to export the file in sdcard
don't forget to add <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> in your manifest file.
And download any SQLite Manager to open that file.
Thanks.. hope it helps you.
I am developing my android application using Netbeans and java. When I am using the emulator I can access the File explorer and insert an SQLite database in to device internal memory by accessing the following path, data/data/com.example.helloandroid/database
But I can not access this location to push the SQLite File in to the phone's internal storage (location) when I am using the real device.
Can someone please help me how to add the file in to phones internal storage. Thanks
I think the device doesn't have root permission, that's why you can't access it. If you want to do in your app with programmatically then it is possible. If anybody knows better then this please share it.
EDIT: ok, first of all,
1. copy your Database.db file in your projects assets folder.
2. now using code copy database file from /asset to device's internal storage
(data/data/<package name>/database folder).
For copy file use below code,
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/<your_app_package_name>/databases/<database_file_name>";
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());
}
I have been creating a pay version of my first app.
I would like to copy the existing database to the new payed app.
How is this possible?
EDIT
In the free app I am using a SQLiteOpenHelper. They can use the same database but would like to use the SQLiteOpenHelper again and can't figure out how to get this to use the other database as the apps have different package names (If they use the same dosn't the free database get deleted when the app gets deleted?).
Please comment if you would like additional info (and perhaps what info you need:))
You have a couple of options, you won't get a package with a different name to directly interact with another packages database.
So you could code a Content Provider into the free app, then allow the paid version to collect data from the content provider, then on first run pass all the data across. This is somewhat cumbersome in my opinion - but would mean the user doesn't need an SDcard, you also stay in control of the data, IE if the user has already used the paid version you can ADD the data onto the database rather than replacing the new one with the old free one...
You could save the database to the SDcard from within the free version, and then collect it with the paid version. Depending how much you want to code, you could set up a Broadcast Receiver in the free app, and then sendBroadcast() from the paid version, that way when the free app receives a broadcast it copes its database to the SDcard, then the paid app collects it. The other way would be for the user to click a save button in the free version, backup to the SDcard, then the user clicks a button in the paid version and it receives it - this can be as simple as copying the file and replacing the app's database, or you could import it to the paid app as a different database, process it adding what you need to the main database then discard it.
As a very loose and simple pointer, you can copy the database to the SDcard with something like this, it is very stripped down from a working bit of code, so should be considered untested to a degree - you will need to add a few catch blocks in places to get it working along with the read write permissions for the SDcard in the manifest:
// Get hold of the db:
InputStream myInput = new FileInputStream("/data/data/com.package.name/databases/database-name");
// Set the output folder on the SDcard
File directory = new File("/sdcard/someFolderName");
// Create the folder if it doesn't exist:
if (!directory.exists())
{
directory.mkdirs();
}
// Set the output file stream up:
OutputStream myOutput = new FileOutputStream(directory.getPath()+ "/database-name.backup");
// Transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0)
{
myOutput.write(buffer, 0, length);
}
// Close and clear the streams
myOutput.flush();
myOutput.close();
myInput.close();
Retreival is very similar:
// Set location for the db:
OutputStream myOutput = new FileOutputStream("/data/data/com.package.name/databases/database-name");
// Set the folder on the SDcard
File directory = new File("/sdcard/someFolderName");
// Set the input file stream up:
InputStream myInput = new FileInputStream(directory.getPath()+ "/database-name.backup");
// Transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0)
{
myOutput.write(buffer, 0, length);
}
// Close and clear the streams
myOutput.flush();
myOutput.close();
myInput.close();
However I would suggest doing some checks first and questioning the user a little:
Check if a file already exists on the SDcard, if so do they want to overwrite it.
Check they want to overwrite the current database with the backup one
You will also need to do some checks like, is the SDcard mounted ect.
Like I say the code above is really just to give you a little hint as to how you could possibly use the SDcard to move the database.
One of my applications downloads a database from a server.
When I install the application onto my phone, it downloads the file correctly and loads the information, no exceptions thrown or anything.
However, when I upload the apk into the Android Market Place and download it onto the phone, the application downloads the database and then crashes, saying that the sqlite handler was not able to open up the database.
Here's the progression of code:
In the SQLiteOpenHelper:
this.FULL_DB_PATH = new String(this.getWritableDatabase().getPath());
this.getWritableDatabase();
// Code for retrieving the database off of the server:
private void copyDataBase(){
InputStream myInput=null;
OutputStream myOutput=null;
try{
// opening connections
URL url = new URL("server_url_here");
URLConnection ucon=url.openConnection();
myInput = ucon.getInputStream();
myOutput = new FileOutputStream(this.FULL_DB_PATH);
// write to the db here
byte[] buffer = new byte[1024*1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
catch(Exception e)
{
try{
myOutput.flush();
myOutput.close();
myInput.close();
}
catch(Exception es){}
}
}
I don't know why my colleague is saving the db with a mp3 extension but...it works when we're installing the apk ad-hoc.
For:
myOutput = new FileOutputStream(this.FULL_DB_PATH);
I've also tried:
myOutput = this.getApplicationContext().openFileOutput(this.FULL_DB_PATH, Context.MODE_WORLD_READABLE);
But that doesn't work either.
Any help is greatly appreciated!! I've been tearing my hair out for a couple of hours over this and I just want it to end haha.
What you are doing is copying the file into the /data folder in the android file system. On a normal phone with normal permissions this is not allowed for security reasons. You can do this on the emulator and rooted phones because you have been granted permission to write to /data (normally only read).
To get around this you will need to manually add the information to the database using db.insert(String, String, ContentValues) and db.update(String, ContentValues, String, String[])
It would be nice to be able to do what you are trying but for security reasons it's a very good thing you can't.
The Emulator gives you special access that real phones don't. In other words, I suspect you are directly copying the file into the databases directory on the phone? If so, you can't do that on a non-rooted phone. Hopefully someone will chime in and prove me wrong because this is a problem for me too. I'd like to easily download a db file and install it. What I end up having to do as a work-around is create a new database and load the schema and data through queries.
EDIT:
I would like to share a trick with you. It's simple really. Instead of using just db.insert/db.update/ by themselves, scope them into transactions. In fact, I would scope the whole DB Build as a transaction, or at least just individual tables. I've experienced a 10-50x increase in speed of transactions when they're scoped and then committed all at once.
The other two answers are incorrect, I do believe. I have a backup system in my app where backups are copied to the sd-card, and then copied back to the /data/-folder when the backup is restored. While I have no idea why your code wont work, here is my code to copy the database from the sd-card:
final InputStream in = new FileInputStream(from);
final OutputStream out = new FileOutputStream(to);
final byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
Just to closer investigare the error, try to download to the sd-card instead and then use my code to copy it to the data-folder. The "to" object in my code I get like this:
public static final String DATABASE_PATH = "/data/data/"+SomeClass.class.getPackage().getName()+"/databases/"+ DATABASE_NAME;
final File to = new File(Constant.DATABASE_PATH);
I guess many people already read this article:
Using your own SQLite database in Android applications: http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/comment-page-2/#comment-12368
However it's keep bringing IOException at
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
I’am trying to use a large DB file. It’s as big as >8MB
I built it using sqlite3 in Mac OS X, inserted UTF-8 encoded strings (for I am using Korean),
added android_meta table with ko_KR as locale, as instructed above.
However, When I debug, it keeps showing IOException at
length=myInput.read(buffer)
I suspect it’s caused by trying to read a big file. If not, I have no clue why.
I tested the same code using much smaller text file, and it worked fine.
Can anyone help me out on this? I’ve searched many places, but no place gave me the clear answer, or good solution.
Good meaning efficient or easy.
I will try use BufferedInput(Output)Stream, but if the simpler one cannot work, I don’t think this will work either.
Can anyone explain the fundamental limits in file input/output in Android, and the right way around it, possibly?
I will really appreciate anyone’s considerate answer. Thank you.
WITH MORE DETAIL:
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
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();
}
Can anyone help me out on this?
Use a smaller file. Or a set of smaller files that you stitch together into a large file as you are unpacking them. Or download the database on the first run of your application.
I've been there. I believe the RAW resource type is free of maximum size constraints (whereas Assets, or more specifically, the stream connected to an asset, is limited in size).
Once you get past that hurdle you should be fine - I've had databases on my phone well over 100MB.
Don't know if it would help you, but if other approaches fail you could try using NIO. For example, here's an implementation of copying inputstream to fileoutput. Alternatively, you could try zipping your file and see if the Android unzipping tools can unzip directly to your db folder.