After clearing application storage & cache, started getting unknown error (code 14 SQLITE_CANTOPEN): Could not open database. Before clearing storage, everything was working properly, both Emulator and Device.
I tried deleting application from Emulator, wiped Emulator and cleaned project, but still crashing when opening MainActivity. For the sake of problem solving, I've put writing permissions in AndroidManifest but still the same error.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Instead of doing
this.baza_putanja = "/data/data/" + context.getPackageName() + "/" + "databases/";
I did
baza_putanja = context.getDatabasePath(baza_ime).getPath();
What bothers me is if I'm trying to open database using a path that does not include the database name - why was it working before clearing application storage & cache?
BazaPodatakaHelper.java
private String baza_putanja = null;
private static final String baza_ime = "eng_dictionary.db";
private SQLiteDatabase econDictionary;
private final Context mContext;
public BazaPodatakaHelper(Context context) {
super(context, baza_ime, null, 1);
this.mContext = context;
this.baza_putanja = "/data/data/" + context.getPackageName() + "/" + "databases/";
Log.e("Putanja 1", baza_putanja);
}
public void kreirajBazuPodataka() throws IOException {
boolean bazaPodatakaPostoji = provjeriBazuPodataka();
if ( !bazaPodatakaPostoji ) {
this.getReadableDatabase();
try {
kopirajBazuPodataka();
} catch (IOException e) {
throw new Error("Greška prilikom kopiranja baze podataka");
}
}
}
public boolean provjeriBazuPodataka() {
SQLiteDatabase provjera;
try {
String putanja = baza_putanja + baza_ime;
provjera = SQLiteDatabase.openDatabase(putanja, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
throw new Error("Greška prilikom provjeravanja baze podataka");
}
if (provjera != null) {
provjera.close();
}
return provjera != null;
}
Error Log:
2019-07-17 20:39:30.482 7885-7885/com.benjaminkljn.econdictionary E/Putanja 1: /data/data/com.benjaminkljn.econdictionary/assets/ 2019-07-17 20:39:30.485 7885-7885/com.benjaminkljn.econdictionary E/SQLiteLog: (14) cannot open file at line 36683 of [c255889bd9] 2019-07-17 20:39:30.485 7885-7885/com.benjaminkljn.econdictionary E/SQLiteLog: (14) os_unix.c:36683: (2) open(/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db)
- 2019-07-17 20:39:30.491 7885-7885/com.benjaminkljn.econdictionary E/SQLiteDatabase: Failed to open database '/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14 SQLITE_CANTOPEN): Could not open database
The message is saying
/data/data/com.benjaminkljn.econdictionary/assets/eng_dictionary.db
Your code above does not include assets in the path, so your issue is probably based around that.
Typically, and specifically, if using context.getDatabasePath(your_database), the attempt would be to open
/data/data/com.benjaminkljn.econdictionary/databases/eng_dictionary.db
i.e. the databases folder not the assets.
Additionally in your comments you mention :-
>I've deleted and re-imported database
Typically, importing the database, at least for an App, would be copying the database to be imported (included with the app) to the assets folder.
As such it could be that you are trying to open the database from what you think is the assets folder, but you cannot use the included/imported assets folder directly as the assets are managed by AssetsManager.
You could probably use Device Explorer to create the assets folder in /data/data/com.benjaminkljn.econdictionary and then copy the database into that folder and then the open may then work.
If you did that previously then, after deleting/uninstalling the App would, if the database hasn't been manually copied into the assets folder (and thus the assets folder has be created), result in the issue you have encountered.
When an App is installed the /data/data/com.benjaminkljn.econdictionary folder will be created but not the sub folders databases not the sub folder named assets, Clearing the App's storage effectively returns to this point.
However, manually copying the database, will only work for the specific App. It wouldn't work if you published the App, as you would not have access to copy the file manually.
To use a pre-existing database in an App then the recommended way is to :-
Create the App or part of the App
Create the assets folder in main/src/ (same location as where the res/java folders and android.manaifest are located).
Note if using SQLiteAssetHelper then create the databases folder in the assets folder.
Copy the database into the assets
The App should then before attempting to use the database, copy the database from the assets folder, accessing the database using AssetManager, into the location from which the database will be accessed.
Typically this location is /data/data/the_package_name/databases/your_database
The reliable/recommended way of determening the location is to use context.getDatabasePath(your_database).
Note that the databases folder will not exist for a new App and must be created (SQLiteAssethelper will do this).
SQliteAssethelper simplifies this.
I've used application folder
data/data/com.xxx.xxx/databases/Customer.db
to store a database,it works fine and i could open and used it,but i wanted to add multiple folders to this path like
/data/data/com.xxx.xxx/databases/b36f6e58-0971-4f79-aca0-dada4201d886/Customer.db
but when i download the database and put it on the path and when i want to open it, it throws Exception that couldn't open the database.i have also try downloading the db ,check and makeDir the path then move db to the path but it doesn't solve the issue.
is there anything wrong with adding another folder in application folder or am i missing something? Any help would be appreciated.
Try this way:
File newDir = new File(getFilesDir(), "newDir");
if (!newDir.exists()) {
newDir.mkdirs();
}
File inside newDir can be accessed with openFileInput/openFileOutput. For both you need a context
I have an sqlite database (.db), copied it in assets folder and have to copy it to /data/data/package_name/databases. The problem is I don't have databases folder and did not succeed to create it.
String dirPath = "/data/data/com.gatec.douaa/databases/";
Log.d("Directory",dirPath);
File projDir = new File(dirPath);
if (!projDir.exists())
projDir.mkdirs();
Can you please help me to create that folder to store on it the database?
Thank you very much.
In my experieces, the "databases" directory is created the first time you use the database. So, if you want copy the database from "asset" directory, you have to force the database creation in the path "data/data/package_name/databases".
This happens only in the lollipop (android 5), in my experiences.
Then you can use the code below:
File file = new File(context.getDatabasePath("database_name.db").getPath());
if (!file.exists())
{
try
{
file.createNewFile();
}
catch (IOException e)
{
}
}
Is there anyway to rename a database of a published android app? I am working something out to just change the database name and onCreate of that database, check for the old database and copy the contents out, but wondering if thats my only recourse.
You could try renaming the file before opening it the first time. It is located in:
getApplication().getDatabasePath("databasename");
Replace "databasename" with the one you are using.
And when you open it for the first time afterwards, use the new name you have selected.
You can use following java commands
File f = new File(PATH + DB_NAME);
f.renameTo(new File(PATH + NEWName));
Where PATH is the path on the device
File database=getApplicationContext().getDatabasePath("oldDatabase.db");
if (database.exists()) {
File newPath = getApplicationContext().getDatabasePath("newDatabase.db");
database.renameTo(newPath);
}
I've created a sqlite database programmatically with the default way of extending SQLiteOpenHelper and overriding onCreate(). This way the db gets created on the fly when needed.
I'd like to check the contents of the db file on my OS X machine with a sqlite browser.
I know the name of the db file, but I can't find it on the device. I've connected to the device via USB and looked with finder and terminal, but I just can't find the db file.
What is the default location for a sqlite databases on an android device?
You can find your created database, named <your-database-name>
in
//data/data/<Your-Application-Package-Name>/databases/<your-database-name>
Pull it out using File explorer and rename it to have .db3 extension to use it in SQLiteExplorer
Use File explorer of DDMS to navigate to emulator directory.
For this, what I did is
File f=new File("/data/data/your.app.package/databases/your_db.db3");
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
fis=new FileInputStream(f);
fos=new FileOutputStream("/mnt/sdcard/db_dump.db");
while(true)
{
int i=fis.read();
if(i!=-1)
{fos.write(i);}
else
{break;}
}
fos.flush();
Toast.makeText(this, "DB dump OK", Toast.LENGTH_LONG).show();
}
catch(Exception e)
{
e.printStackTrace();
Toast.makeText(this, "DB dump ERROR", Toast.LENGTH_LONG).show();
}
finally
{
try
{
fos.close();
fis.close();
}
catch(IOException ioe)
{}
}
And to do this, your app must have permission to access SD card, add following setting to your manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Not a brilliant way, but works.
The Context contains many path functions: Context.getXXXPath()
One of them is android.content.Context.getDatabasePath(String dbname) that returns the absolute path of a database called dbname.
Context ctx = this; // for Activity, or Service. Otherwise simply get the context.
String dbname = "mydb.db";
Path dbpath = ctx.getDatabasePath(dbname);
The returned path, in this case, would be something like:
/data/data/com.me.myapp/databases/mydb.db
Note that this path is autogenerated if using SQLiteOpenHelper to open the DB.
If you're talking about real device /data/data/<application-package-name> is unaccessible. You must have root rights...
This is and old question, but answering may help others.
Default path where Android saves databases can not be accesed on non-rooted devices. So, the easiest way to access to database file (only for debugging environments) is to modify the constructor of the class:
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
MySQLiteOpenHelper(Context context) {
super(context, "/mnt/sdcard/database_name.db", null, 0);
}
}
Remember to change for production environments with these lines:
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
MySQLiteOpenHelper(Context context) {
super(context, "database_name.db", null, 0);
}
}
/data/data/packagename/databases/
ie
/data/data/com.example.program/databases/
A SQLite database is just a file. You can take that file, move it around, and even copy it to another system (for example, from your phone to your workstation), and it will work fine. Android stores the file in the /data/data/packagename/databases/ directory. You can use the adb command or the File Explorer view in Eclipse (Window > Show View > Other... > Android > File Explorer) to view, move, or delete it.
well this might be late but it will help.
You can access the database without rooting your device through adb
start the adb using cmd and type the following commands
-run-as com.your.package
-shell#android:/data/data/com.your.package $ ls
cache
databases
lib
shared_prefs
Now you can open from here on.
If you name your db as a file without giving a path then most common way to get its folder is like:
final File dbFile = new File(getFilesDir().getParent()+"/databases/"+DBAdapter.DATABASE_NAME);
where DBAdapter.DATABASE_NAME is just a String like "mydatabase.db".Context.getFilesDir() returns path for app's files like: /data/data/<your.app.packagename>/files/ thats why you need to .getParent()+"/databases/", to remove "files" and add "databases" instead.
BTW Eclipse will warn you about hardcoded "data/data/" string but not in this case.
By Default it stores to:
String DATABASE_PATH = "/data/data/" + PACKAGE_NAME + "/databases/" + DATABASE_NAME;
Where:
String DATABASE_NAME = "your_dbname";
String PACKAGE_NAME = "com.example.your_app_name";
And check whether your database is stored to Device Storage. If So, You have to use permission in Manifest.xml :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You can access it using adb shell how-to
Content from above link:
Tutorial : How to access a Android database by using a command line.
When your start dealing with a database in your program, it is really
important and useful to be able to access it directly, outside your
program, to check what the program has just done, and to debug.
And it is important also on Android.
Here is how to do that :
1) Launch the emulator (or connect your real device to your PC ). I
usually launch one of my program from Eclipse for this. 2) Launch a
command prompt in the android tools directory. 3) type adb shell. This
will launch an unix shell on your emulator / connected device. 4) go
to the directory where your database is : cd data/data here you have
the list of all the applications on your device Go in your application
directory ( beware, Unix is case sensitive !! ) cd
com.alocaly.LetterGame and descend in your databases directory : cd
databases Here you can find all your databases. In my case, there is
only one ( now ) : SCORE_DB 5) Launch sqlite on the database you want
to check / change : sqlite3 SCORE_DB From here, you can check what
tables are present : .tables 6) enter any SQL instruction you want :
select * from Score;
This is quite simple, but every time I need it, I don't know where to
find it.
Do not hardcode path like //data/data/<Your-Application-Package-Name>/databases/<your-database-name>. Well it does work in most cases, but this one is not working in devices where device can support multiple users. The path can be like //data/user/10/<Your-Application-Package-Name>/databases/<your-database-name>. Possible solution to this is using context.getDatabasePath(<your-database-name>).
If your application creates a database, this database is by default saved in the directory DATA/data/APP_NAME/databases/FILENAME.
The parts of the above directory are constructed based on the following rules. DATA is the path which the Environment.getDataDirectory() method returns. APP_NAME is your application name. FILENAME is the name you specify in your application code for the database.
You can find your database file :
Context.getDatabasePath(getDatabaseName())
getDatabaseName from class SQLiteOpenHelper
In kotlin you can find it in this way:
val data: File = Environment.getDataDirectory()
val currentDBPath = "//data//$packageName//databases//"
val destDir = File(data, currentDBPath)
You can also check whether your IDE has a utility like Eclipse's DDMS perspective which allows you to browse through the directory and/or copy files to and from the Emulator or a rooted device.
Define your database name like :
private static final String DATABASE_NAME = "/mnt/sdcard/hri_database.db";
And you can see your database in :
storage/sdcard0/yourdatabasename.db
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
MySQLiteOpenHelper(Context context) {
super(context, "/mnt/sdcard/database_name.db", null, 0);
} }
Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead
#Shardul's answer is correct.
Besides that, new Android Studio has a tool called: App Inspection, which you can view database directly.
Here is the version of Android Studio:
Android Studio Arctic Fox | 2020.3.1 Patch 3
Build #AI-203.7717.56.2031.7784292, built on October 1, 2021