I have encountered a weird problem. I was querying a database table for a list of words and was able to get the list. But I am not being able to update that table. The weird thing is, the logcat is showing Code 14 error. I uninstalled the app, re-ran it so the db is freshly copied, But nothing has changed.
Here's the dbHandler code:
public VocabDatabase(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
}
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
//do nothing - database already exist
} else {
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getWritableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
*
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase() {
this.getReadableDatabase();
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
e.printStackTrace();
}
if (checkDB != null) {
checkDB.close();
}
return (checkDB != null) ? true : false;
}
private boolean checkDataBaseAlt(){
File chkdb = new File(DB_PATH);
return chkdb.exists();
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
*/
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 = 0;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
#Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
try {
copyDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
//add your public methods for insert, get, delete and update data in database.
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
}
public long insert(String table, String nullColumnHack, ContentValues contentValues) {
SQLiteDatabase db = this.getWritableDatabase();
return db.insert(table, nullColumnHack, contentValues);
}
public Cursor rawQuery(String string, String[] selectionArguments) {
SQLiteDatabase db = this.getWritableDatabase();
return db.rawQuery(string, selectionArguments);
}
public long update(String table, ContentValues contentValues, String whereClause, String[] whereArgs) {
SQLiteDatabase db = this.getWritableDatabase();
return db.update(table, contentValues, whereClause, whereArgs);
}
}
And here's the service code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
vdb = new VocabDatabase(this);
Toast.makeText(this, "Service started", Toast.LENGTH_SHORT).show();
createDB();
queryDB();
return super.onStartCommand(intent, flags, startId);
}
private void createDB() {
vdb.getWritableDatabase();
try {
vdb.createDataBase();
vdb.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
public void queryDB() {
String vet = "";
ArrayList<String> lister = new ArrayList<>();
Cursor cr = vdb.query(TABLE_NAME, null, null, null, null, null, null);
if (cr.moveToFirst()) {
do {
lister.add(cr.getString(0));
} while (cr.moveToNext());
}
cr.close();
String vet="";
for (String v : lister) {
vet += v + "\t";
}
}
The String-vet is displayed in the toast, and I can see all the words in the first column of the table. But I'm not able to update the rows.
private void updateInDatabase(String up, String pot) {
ContentValues conval = new ContentValues();
conval.put(pot, "1");
try {
long res = vdb.update(TABLE_NAME, conval, "Word=?", new String[]{up});
} catch (Exception e) {
}
}
I've given the storage permissions to it and double checked the same.
Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.hack.corrector">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".scrapeservice"/>
</application>
Error Log:
05-17 13:39:04.614 28088-28088/com.example.hack.corrector E/SQLiteLog: (14) cannot open file at line 31282 of [5a3022e081]
05-17 13:39:04.615 28088-28088/com.example.hack.corrector E/SQLiteLog: (14) os_unix.c:31282: (21) open(/data/user/0/com.example.hack.corrector/databases/) -
05-17 13:39:04.616 28088-28088/com.example.hack.corrector E/SQLiteDatabase: Failed to open database '/data/user/0/com.example.hack.corrector/databases/'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:207)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:191)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at com.example.hakc.corrector.VocabDatabase.checkDataBase(VocabDatabase.java:81)
at com.example.hakc.corrector.VocabDatabase.createDataBase(VocabDatabase.java:48)
at com.example.hakc.corrector.scrapeservice.createDB(scrapeservice.java:48)
at com.example.hakc.corrector.scrapeservice.onStartCommand(scrapeservice.java:39)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3049)
at android.app.ActivityThread.access$2300(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1479)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5571)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
05-17 1
This issue if you are running your app on API level 23 or greater, because of the new real-time permissions model introduced in this. In these versions users grant permissions to apps while the app is running
For getting permissions at runtime, you will have to request the user. You can do that in following way:
Request Permission
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, REQUEST_CODE); //REQUEST_CODE can be any Integer value
And check your Permission Result
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Permission granted.
//Now you can try your database creating and writing stuff.
}
else{
//Permission denied.
}
break;
}
}
If this does not solve your problem then go to this link. Number of solutions are here for the same problem.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
Like the exception tells :
Failed to open database '/data/user/0/com.example.hack.corrector/databases/'.
You are trying to open the SQLite DB with the variable DB_PATH set like
this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
You don't set the name of the file, only set the directory path. databases/ is a directory.
Set a file name to your path :
this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/my_db";
EDIT:
you have two DB name variable... you are using DB_NAME to open the connection with the helper (in the super constructor) then in the check method you used DB_PATH.
So you are able to get a connection from the helper
this.getWritableDatabase(); //Using the DB at `DB_NAME`
But will failed to get a connection with
String myPath = DB_PATH;
SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
Because you used DB_PATH here not DB_NAME. You are using 2 different DB path.
I believe you will find that the cannot open database error is not actually a failure, but an indication of the issue. That is the open error is encountered by the checkdataBase method because it cannot open the database as the message says. This, as it is trapped, does not result in a failure.
Rather what happens is that checkDatabase method returns false, because it cannot open the database, and so the database is copied from the assets every time the App is run. Thus undoing any changes from a previous run.
It is simple to diagnose/debug this using two lines of code.
by adding Log.d("DBEXISTCHK", "Method checkdataBase returned" + String.valueOf(dbExist));
as per :-
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
Log.d("DBEXISTCHK", "Method checkdataBase returned" + String.valueOf(dbExist)); //<<<<<<<<<< ADDED
if (dbExist) {
//do nothing - database already exist
} else {
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getWritableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
and
by adding Log.d("DBCOPY","Database is being copied from the Assets.");
as per :-
private void copyDataBase() throws IOException {
Log.d("DBCOPY","Database is being copied from the Assets."); //<<<<<<<<<< ADDED
//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 = 0;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
The resultant log would then be along similar to (note the last two lines):-
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
(14) os_unix.c:30174: (21) open(/data/data/bcdbfa.basiccopydbfromassets/databases/) -
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets E/SQLiteDatabase: Failed to open database '/data/data/bcdbfa.basiccopydbfromassets/databases/'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at bcdbfa.basiccopydbfromassets.VocabDatabase.checkDataBase(VocabDatabase.java:85)
at bcdbfa.basiccopydbfromassets.VocabDatabase.createDataBase(VocabDatabase.java:45)
at bcdbfa.basiccopydbfromassets.MainActivity.onCreate(MainActivity.java:18)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets W/System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets W/System.err: at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at bcdbfa.basiccopydbfromassets.VocabDatabase.checkDataBase(VocabDatabase.java:85)
at bcdbfa.basiccopydbfromassets.VocabDatabase.createDataBase(VocabDatabase.java:45)
at bcdbfa.basiccopydbfromassets.MainActivity.onCreate(MainActivity.java:18)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets D/DBEXISTCHK: Method checkdataBase returnedfalse
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets D/DBCOPY: Database is being copied from the Assets.
The Fix
The fix is even simpler, it is simply a matter of changing :-
String myPath = DB_PATH;
to
String myPath = DB_PATH + DB_NAME;
in the checkDatabase method.
In which case the result in the log (if the logging is left in) will be :-
05-17 10:30:49.809 1265-1265/? D/DBEXISTCHK: Method checkdataBase returnedtrue
Additional
Re the comment
only empty database with the same name is being created.
This is because you are calling getWritableDatabase in the createDB method before calling the createDatabase method. That is, getWritableDatabase will, if there is no database, create an empty database (bar the sqlite_master table and for android the android_metadata table), and then invoke the onCreate method. So that explains why when the full path is correct that the copy of the database is circumvented and that the database empty database exists as a result.
And then the comment
But when I changed 'myPath' back to myPath = DB_Path; the entire
database got copied but the problem still persists.
When the path is incorrect the, as previously explained, the checkDatabase method will always return false and thus the copyDatabase method is invoked, this then works as the paths used are correct.
So
private void createDB() {
vdb.getWritableDatabase(); //<<<<<<<<<< The villainous line
try {
vdb.createDataBase();
vdb.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
should be
private void createDB() {
try {
vdb.createDataBase();
vdb.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
Obviously with all paths being the full path that include the name of the database.
I've figured out where the problem lies. It was in the service from which the query is done. In createDB() method, I've used vdb.getWritableDatabase(). When I commented it out, the query worked smoothly. Entire database copied, and queries are being handled perfectly. I need to check the 'update' though.. I sincerely thank you guys for hearing me and taking your time to help me solve this problem. It's thanks to your answers, I've learnt a lot about how databases are communicated with properly.
Related
i'm having problem understanding what is the error with opening the database since my program works fine but it displays this error.can anyone help me in understanding this.
this is how i check the database exists in the main
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase("Event.db", null, SQLiteDatabase.OPEN_READONLY);
checkDB.close();
}
catch (SQLiteException e) {
eventDB = new DatabaseEvent(this);
}
return checkDB != null;
}
i'm getting this error i don't know how to fix?
E/SQLiteDatabase: Failed to open database 'MyACtion.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
In the onCreate method of DatabaseEvent class change the SQL from:
db.execSQL("CREATE TABLE... ;");
to
db.execSQL("CREATE TABLE... "); // NO SEMI-COLON
also, in your checkDataBase method, you're not opening the same database you are creating in DatabaseEvent. Instead call:
DatabaseEvent db = new DatabaseEvent(context);
db.getReadableDatabase();
One of my methods in my custom SQLiteOpenHelper class throws an "attempt to re-open already closed object" error whenever I try to invoke it after closing the database. I close my databases in onPause on my MainActivity, and then I make sure to check if they are open before invoking a method on the database.
This is the code for the database method, it is within an AsyncTask.
public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) {
Log.d("insert LocationsDB", "Data inserted");
final SQLiteDatabase db = this.getWritableDatabase();
new AsyncTask<ArrayList<SavedWifiHotspot>, Void, Void>() {
#Override
protected Void doInBackground(ArrayList<SavedWifiHotspot>... hotspots) {
Log.d("insert LocationsDB", "Hotspot inserted");
ContentValues hotspotValues = new ContentValues();
for(SavedWifiHotspot hotspot : hotspots[0]) {
hotspotValues.put("Ssid", hotspot.getSsid());
hotspotValues.put("Password", hotspot.getPassword());
hotspotValues.put("LocationName", hotspot.getHotspotLoc());
hotspotValues.put("Lat", hotspot.getLatitude());
hotspotValues.put("Lng", hotspot.getLongitude());
db.insert(HOTSPOT_TABLE_NAME, null, hotspotValues);
}
return null;
}
}.execute(hotspots);
new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() {
#Override
protected Void doInBackground(ArrayList<MarkerOptions>... markers) {
ContentValues markerValues = new ContentValues();
for(MarkerOptions marker: markers[0]) {
markerValues.put("LocationName", marker.getTitle());
markerValues.put("Lat", marker.getPosition().latitude);
markerValues.put("Lng", marker.getPosition().longitude);
db.insert(LOCATION_TABLE_NAME, null, markerValues);
}
return null;
}
}.execute(markers);
}
This is the code used to call the method:
public void updateLocDB() {
if(!db.isOpen()) {
db = locDB.getReadableDatabase();
}
if(!wifiHotspots.isEmpty() && !markers.isEmpty()) {
locDB.clearData();
locDB.insertData(wifiHotspots, markers);
}
}
Logcat output:
FATAL EXCEPTION: AsyncTask #1
Process: com1032.cw2.fm00232.fm00232_assignment2, PID: 368
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalStateException: attempt to re-open an
already-closed object: SQLiteDatabase:/data/data/com1032.cw2.fm00232.fm00232_assignment2/databases/locationsDB
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1659)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:89)
at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:75)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
I've been searching for a few hours, and can't find anything that helps me fix this problem. Any help would be appreciated.
clearData code:
public void clearData() {
Log.d("clear LocationsDB", "Tables cleared");
db = this.getReadableDatabase();
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
String dropHSTable = "DROP TABLE IF EXISTS "
+ HOTSPOT_TABLE_NAME + ";";
String dropLocTable = "DROP TABLE IF EXISTS "
+ LOCATION_TABLE_NAME + ";";
db.execSQL(dropHSTable);
db.execSQL(dropLocTable);
createTables(db);
return null;
}
}.execute();
}
As per my understanding you are executing two asynchronous task at same time. And creating/opening a SQLite DB connection in both tasks. Which creates the problem.
As, it is not possible to create two connections of SQLite DB. Because SQLite is ThreadSafe, only one thread can perform read/write operation at a single time.
You can not perform read and write operations concurrently on SQLite until you do not use WAL(Write Ahead Logging). Follow this for more info Concurrency in SQLite database
If the locDB.clearData(); is also asynchronous it can cause that error by having the connection open to the same SQLite database with the locDB.insertDatalocDB.insertData.
class EndpointsAsyncTask extends AsyncTask<Void, Void, List<Quote>> {
private static QuoteEndpoint myApiService = null;
private Context context;
EndpointsAsyncTask(Context context) {
this.context = context;
}
#Override
protected List<Quote> doInBackground(Void... params) {
if(myApiService == null) { // Only do this once
/*QuoteEndpoint.Builder builder = new QuoteEndpoint.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});*/
// end options for devappserver
QuoteEndpoint.Builder builder = new QuoteEndpoint.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl("https://momcares-987.appspot.com/_ah/api/");
myApiService = builder.build();
}
try {
return myApiService.listQuote().execute().getItems();
} catch (IOException e) {
return Collections.EMPTY_LIST;
}
}
#Override
protected void onPostExecute(List<Quote> result) {
for (Quote q : result) {
Toast.makeText(context, q.getWho() + " : " + q.getWhom(), Toast.LENGTH_LONG).show();
}
}
}
The above class has been included in my MainActivity.java file.
http://rominirani.com/2014/08/26/gradle-tutorial-part-9-cloud-endpoints-persistence-android-studio/
I have been following this tutorial. I manually inserted quotes (Quote is the bean I am using) in the API Explorer and I successfully get the list of quotes in my emulator when I run the local server and test. However, when I deploy the same backend and run the application, I get a NullPointerException in the onPostExecuteMethod. Please help. Thanks!
Error Log:
06-26 11:50:19.889 26342-26342/com.sickstudios.sickapplication W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x430d4140)
06-26 11:50:19.909 26342-26342/com.sickstudios.sickapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.sickstudios.sickapplication, PID: 26342
java.lang.NullPointerException
at com.sickstudios.sickapplication.EndpointsAsyncTask.onPostExecute(MainActivity.java:64)
at com.sickstudios.sickapplication.EndpointsAsyncTask.onPostExecute(MainActivity.java:25)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:817)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:633)
at dalvik.system.NativeStart.main(Native Method)
06-26 11:50:23.639 26342-26342/com.sickstudios.sickapplication I/Process﹕ Sending signal. PID: 26342 SIG: 9
Try this:
http://www.momcares-987.appspot.com/_ah/api/
Sometimes https calls raise the connectivity issue.
I am trying to open a database to test if the database exists. I wrote the code in a try and catch statement to catch the SQLiteCantOpenDatabaseException if the database doesn't exist.
However, even if I catch the SQLiteCantOpenDatabaseException, the error log is printed in the Logcat. Is that normal ? I haven't invoked the method printStackTrace on the exception. Is there a way to remove the exception log ?
Fortunately, the app still runs normaly even after the try and catch statement.
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
myContext = this;
try
{
database = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null,
SQLiteDatabase.OPEN_READWRITE);
database.close();
Log.v("Database Log", "Database exists !!");
}
catch(SQLiteCantOpenDatabaseException e)
{
// The database doesn't exist; Lets create it
Log.v("Database Log", "Database doesn't exists !!");
}
Logcat
17:30:43.587: E/SQLiteLog(2054): (14) cannot open file at line 30191 of [00bb9c9ce4]
17:30:43.587: E/SQLiteLog(2054): (14) os_unix.c:30191: (2) open(/data/data/com.appsplus.hearthstonecollection/databases/hearthstonedata) -
17:30:43.667: E/SQLiteDatabase(2054): Failed to open database '/data/data/com.appsplus.hearthstonecollection/databases/hearthstonedata'.
17:30:43.667: E/SQLiteDatabase(2054): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
I am required to check whether a preexisting data base is present in my application, and for that I have written the following code:
public boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try {
String myPath = "/data/data/com.mycomp.sampleapp/databases/myDB.db";
checkDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READWRITE);
}
catch (Exception e) { }
return checkDB != null ? true : false;
}
The above code working as expected. Now my problem is that it is printing below exception statements in my Logcat. I just want to do nothing and don't want to print exception in my Logcat.
E/SQLiteDatabase(27655): Failed to open database '/data/data/com.mycomp.sampleapp/databases/myDB.db'.
E/SQLiteDatabase(27655): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:338)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:232)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:512)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:885)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:855)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
E/SQLiteDatabase(27655): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:671)
E/SQLiteDatabase(27655): at com.mycomp.sampleapp.DataBaseHelper.checkDataBase(DataBaseHelper.java:63)
E/SQLiteDatabase(27655): at com.mycomp.sampleapp.GetData.doInBackground(GetData.java:55)
E/SQLiteDatabase(27655): at com.mycomp.sampleapp.GetData.doInBackground(GetData.java:1)
E/SQLiteDatabase(27655): at android.os.AsyncTask$2.call(AsyncTask.java:288)
E/SQLiteDatabase(27655): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
E/SQLiteDatabase(27655): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
E/SQLiteDatabase(27655): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/SQLiteDatabase(27655): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/SQLiteDatabase(27655): at java.lang.Thread.run(Thread.java:841)
I have written my code in try/catch block, but still it's printing the exception in my log files.
The exception is generating from the below statement of my code:
checkDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READWRITE);
Please let me know how can I prevent printing exception in log files.
You can check whether file exists:
File dbFile = mContext.getDatabasePath(myPath);
boolean exists = dbFile.exists();
For your example:
private static final String DB_PATH = "myDB.db";
public boolean checkDataBase() {
File dbFile = mContext.getDatabasePath(DB_PATH);
return dbFile.exists();
}