I try to create a DB on an SD card, when I call getReadableDatabase () I get
Failed to open database '/storage/sdcard1/xAPP/inventory.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database.
If I put the database to the SD card manually, the following errors appear:
Failed to open database '/storage/sdcard1/xAPP/inventory.db'.
android.database.sqlite.SQLiteException: not an error (code 0): Could not open the database in read/write mode.
Why? There is no such problem on Internal storage and external storage. Can the problem be in the format of the SD card file system (FAT32)?
P.S. I emphasize that this is not about the external storage, but about the removable storage (SD card)! If I use Environment.getExternalStorageDirectory() all works good!
UPD1 Create Database:
private InventoryDBHelper(Context context) {
super(context, Settings.getInstance().getSDCardDir()
+ File.separator + "xAPP"
+ File.separator + DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// date text yyyy-MM-dd HH:mm:ss
String sql = String
.format("CREATE TABLE %s (_key INTEGER PRIMARY KEY, ProductId TEXT, ProductName TEXT, Price DOUBLE, Cost DOUBLE, DateModified TEXT);",
TABLE_INVENTORY);
db.execSQL(sql);
sql = String
.format("CREATE TABLE %s (ProductId INTEGER, ProductQuantity INTEGER);",
TABLE_QUANTITY);
db.execSQL(sql);
}
UPD2: I have to re-open the problem, because this works only in debugging mode, and even not always!
UPD3 Works if I get a directory like:
File[] dbDirs = ContextCompat.getExternalFilesDirs(context, null);
if (dbDirs[1] != null) {
return dbDirs[1].getAbsolutePath();
} else {
return dbDirs[0].getAbsolutePath();
}
First just try to create that directory on the sdcard. You will see that you wont succeed.
Micro SD cards are read only for modern Android versions.
Except for one app specific directory on it.
Well if you are lucky.
Try to put the database as
/storage/sdcard1/Android/data/<packagename>/files/xAPP/inventory.db
Related
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 want to edit an existing .db file in SD card directly. According to this, using the following code, it is possible to copy that database to /data/data/PACKAGE_NAME/databases/ and then edit it, but I want to edit it in the SD card itself.
public void openDataBase() throws SQLException{
String myPath = DB_PATH + DB_NAME;
myDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READWRITE);
Is it possible?
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
With this, you can read/write to your app's internal storage... be that a DB file or not.
OR.... you CAN open/read the data from the internal DB, and then systematically copy it over into a new DB on the external storage.
This is tedious, but it gives you the opportunity to 'scrub' your DB of any 'private' info that you might not want to share.
and "tedious" isn't "quite" true, you just need to create each table again, then read each table and insert that data into the new DB.
thanks to friends ... this is the answer :
first u should define the database file like this :
SQLiteDatabase myDB;
then, for example for inserting :
myDB = SQLiteDatabase.openDatabase("/sdcard/mydb.db", null, SQLiteDatabase.OPEN_READWRITE);
ContentValues cv1 = new ContentValues();
cv1.put("Field1", "new Field");
cv1.put("Field2", "other Field");
myDB.insert("TABLE_NAME", null, cv1);
or for update use this :
myDB.update("TABLE_NAME", cv1, "_id=" + 1, null);
I have an android application that is supposed to read and expand a DataBase that is already created on SQLite...it works fine on emulator by putting database in data/data/(packagename)/database folder on the file explorer of emulator.
Now problem is occuring with the real device. Obviously it doesnt have the DataBase to open.I tried to put DataBase in assets folder but I am not getting to open it with the openhelper. how to access my database file form assets folder.will you please give me the right solution because i am new in Android and java .
this is my dbheperclass .
public class FoodDbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "pkfood_calories.DB";
private static final int DATABASE_VERSION = 1;
private static final String CREATE_QUERY =
"CREATE TABLE "+ Food.NewDishInfo.TABLE_NAME+"("
+ Food.NewDishInfo.DISH_NAME+" TEXT NOT NULL,"
+ Food.NewDishInfo.DISH_QUANTITY+" TEXT NOT NULL,"
+ Food.NewDishInfo.DISH_CALORIE+" INTEGER,"
+ Food.NewDishInfo.DISH_FAT+" TEXT NOT NULL,"
+ Food.NewDishInfo.DISH_PROTEIN+" TEXT NOT NULL,"
+ Food.NewDishInfo.DISH_SUGAR+" TEXT NOT NULL,"
+ Food.NewDishInfo.DISH_VITAMINS+" TEXT NOT NULL);";
public FoodDbHelper(Context context)
{
super(context,DATABASE_NAME,null,DATABASE_VERSION);
Log.e("DATABASE OPERATION","Database created / opened...");
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_QUERY);
Log.e("DATABASE OPERATION","Table created...");
}
public void addInformations(String name ,String quantity, Integer calorie, String fat ,
String protein,String sugar,String vitamins, SQLiteDatabase db){
ContentValues contentValues = new ContentValues();
contentValues.put(Food.NewDishInfo.DISH_NAME,name);
contentValues.put(Food.NewDishInfo.DISH_QUANTITY,quantity);
contentValues.put(Food.NewDishInfo.DISH_CALORIE,calorie);
contentValues.put(Food.NewDishInfo.DISH_FAT,fat);
contentValues.put(Food.NewDishInfo.DISH_PROTEIN,protein);
contentValues.put(Food.NewDishInfo.DISH_SUGAR,sugar);
contentValues.put(Food.NewDishInfo.DISH_VITAMINS,vitamins);
db.insert(Food.NewDishInfo.TABLE_NAME, null, contentValues);
Log.e("DATABASE OPERATION","one row inserted...");
}
public Cursor getInformations(SQLiteDatabase db){
Cursor cursor;
String[] projections = {Food.NewDishInfo.DISH_NAME,Food.NewDishInfo.DISH_QUANTITY,
Food.NewDishInfo.DISH_CALORIE,Food.NewDishInfo.DISH_FAT,Food.NewDishInfo.DISH_PROTEIN,
Food.NewDishInfo.DISH_SUGAR, Food.NewDishInfo.DISH_VITAMINS};
cursor= db.query(Food.NewDishInfo.TABLE_NAME,projections,null,null,null,null,"DISH_NAME ASC");
return cursor;
}
please help me to short out from this problem..
First thing is your logic of reading from asset folder is correct.
But writing to assets folder may not be a better logic.
The asset folder is part of the APK
To read a file from asset folder
context.getAssets().open("pkfood_calories.DB")
Assuming that you placed that file in assets folder
You can get the internal memory location using
context.getFilesDir()
Refer creating file in internal memory Android create folders in Internal Memory
You cannot write anything to an APK. So, your db is in assert folder which can only be used for reading purpose.
You need to migrate that db file in external or internal memory(according to requirement) before doing some writing part on it.
Im trying to do a simple example using my own SQLite database, android and greenDAO generator to generate classes for my android app.
My database file is defined this way:
1) Create a database called "OneTableDB" (without extension, SQLite 3) with the following structure:
Entity: Professor
professorID: primarykey
name: text
age: int
Entity: android_metadata
locale: text
Then i populated android_metadata with the value 'en_US', and the entity with few rows.
2) placed on my Android app structure inside: proj_root/databases/
Full path to database file: proj_root/databases/OneTableDB
3)i have a method to check whether database exists or not (in my case, it has to exist, since i placed inside databases folder)
private boolean databaseExists() {
SQLiteDatabase sqliteDatabase = null;
try {
String databasePath = DB_PATH + DB_NAME;
File f = new File(DB_PATH + DB_NAME);
f.exists();
sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
e.printStackTrace();
}
if (sqliteDatabase != null) {
sqliteDatabase.close();
}
return sqliteDatabase != null ? true : false;
}
//DB_PATH = /data/data/com.myapp.android_dao_tests/databases/
//DB_NAME = OneTableDB
debugging on f.exists(), it returns false value and then breaks on
sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
SQLiteDatabase.OPEN_READONLY);
During the debugging i used adb shell to check if the path was right, and in fact i can navigate to /data/data/com.myapp.android_dao_tests/ and there is no databases folder!
Any idea how can i solve this problem?
Thanks in advance?
The DB "template" is saved in the assets/ folder, in order for it to be bundled in the apk. The code then copies the DB from assets/ to databases/ to make it accessible as a regular SQLite DB.
After further investigation, it seems like Android refuses to acknowledge the new DB as its own. Apparently, the built-in DB mechanism wasn't meant to be used this way.
The correct way to approach it is by keeping the data in textual format in assets/ so that if the app starts and finds there's no DB, it will create the schema itself, and populate it with the data in the text files from the assets/ folder.
Am creating a new database using helper, but as per the document on create should be called once the data base is created, but its not called properly. could any plz help me to resolve this asap. Plz see the code below.
1) Is there any way to create database instead of using helper if so plz advise me !
2) What are the callbacks will be called in the database creation and also in kill of a database ?
OpenHelper(Context context)
{
super(context, "examplee.db", null, 1 );
SQLiteDatabase sqlite = null;
Log.w(TAG, "Openhelp database, ");
sqlite = context.openOrCreateDatabase("examplee.db", Context.MODE_PRIVATE, null );
Log.e ( TAG,"SQ lite database object "+sqlite );
}
public void onOpen(SQLiteDatabase db)
{
Log.e ( TAG,"On open called ");
}
#Override
public void onCreate(SQLiteDatabase db)
{
Log.w(TAG, " On create ");
//db.execSQL(sql);
//db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY, name TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w(TAG, "Upgrading database, this will drop tables and recreate.");
//db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
//onCreate(db);
}
}
Thanks in advance,
Here's a very detailed description on how to delete a database file from your emulator (debugging on an actual android phone is very similar).
Run your emulator. If you're having problems with that, then you can ignore the rest of this help message!
Pull up a command-line interface, according to your operating system.
Execute the command: 'adb shell' (omit the quotes, of course). This will take you into the Android Debug Bridge; your prompt will change to something like a simple pound sign. Regardless of your original operating system, you are now in a simplified unix OS.
You are now in your emulator. Type the command 'ls -l' to verify that you're in the root directory (you'll see something that looks very much like a unix root directory system).
Change directories to where your database file is stored. Suppose that the program that your ran is in the package com.sillynames.myprogram5, and the database file is called 'myblackbook.db'. You will find the file at the directory:
/data/data/com.sillynames.myprogram5/databases/myblackbook.db
Once you're at that directory, simply delete the database via 'rm myblackbook.db'.
Hope this helps!
-scott
The SQLiteOpenHelper javadoc says that onCreate is "Called when the database is created for the first time. This is where the creation of tables and the initial population of the tables should happen.". It is not called everytime the application comes up. In your case Probably the db is already created.
To verify if the db exists login to the shell with adb and go to /data/data/<your application package name>/databases and see if the employees.db file exists there.
In the onCreate method typically you will create your tables and load any initial data. This is executed when the app is launched for the first time after installation.
Is there any way to create database instead of using helper if so plz advise me !
Yes you can create your databse manually on your system using the the tool SQLite Manager or other and bundle that sqlite db file in your assets folder of your project. And when your application run then you need to copy that database file to the path /data/data/your_app_package_name/databases/
Refer this : Using your own SQLite database in Android applications
What are the callbacks will be called in the database creation and also in kill of a database ?
When your database is created fist time the onCreate() method is called. And there is no way to kill/drop a database instead you can delete that db file.
Make sure you await to get the database reference. Check if you have the database reference that was my issue. Had declared Database _db on top of class but in my functions it was null
final Database db = await initDb();
print("insert to db $db");
initDB
Future<Database> initDb() async {
print("called db init");
try {
final dbFolder = await getDatabasesPath();
if (!await Directory(dbFolder).exists()) {
print("db path does not exist");
await Directory(dbFolder).create(recursive: true).then((value) {
print("db directory $value");
});
}
final dbPath = join(dbFolder, _kBdFileName);
print("db path $dbPath");
// open db
_db = await openDatabase(
dbPath,
version: 1,
onCreate: (db, version) async {
print("Call on create");
await _initDBtables(db).then((value) {
print("on created ");
});
},
);
print("Db initialized $_db");
// success init db
return _db;
} on DatabaseException catch (e) {
print(e);
return _db;
}
}