SQLiteDatabase Opening DB in AsyncTask (Android) - java

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.

Related

How to Fix Jsoup nullpointerexception in android studio 2019 [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I am creating an app in which i want to scrape google data with the help of jsoup and show it to text view in android studio.
But after doing some coding with the help of jsoup i am getting following error:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.yasht.cricketapp, PID: 11929
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:325)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.jsoup.nodes.Element.text()' on a null object reference
at com.example.yasht.cricketapp.Bottomnav.score_scrape.doInBackground(score_scrape.java:30)
at com.example.yasht.cricketapp.Bottomnav.score_scrape.doInBackground(score_scrape.java:13)
at android.os.AsyncTask$2.call(AsyncTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
at java.lang.Thread.run(Thread.java:761) 
this is my jsoup code with async task :
public class score_scrape extends AsyncTask<Void,Void,Void> {
String words;
TextView score;
public score_scrape( TextView score){
this.score =score;
}
#Override
protected Void doInBackground(Void... voids) {
try {
Document doc = Jsoup.connect("https://www.google.com/search?q=india+vs+australia+3rd+odi+live+score").get();
Element element = doc.select("div[imspo_mh_cricket__score-major]").first();
words = element.text();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
score.setText(words);
}
}
I am using async task method which is declared i my main activity.
Comment for any further information.
In your case you don't want to use select You can simply change below line.
Change line from
Element element = doc.select("div[imspo_mh_cricket__score-major]").first();
To
Element element = doc.getElementsByClass("imspo_mh_cricket__score-major").first();
Output:
230

False SQLite error? code 14

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.

Receiving data causes "too many files open"

In my client I receive via ZeroMQ a lot of input, which needs to be constantly updated. My server is written in python, but that should not matter. So this is what I do in my MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/********************************NETWORK********************************/
new NetworkCall().execute("");
}
private class NetworkCall extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
while (true) {
try {
ZMQ.Context context = ZMQ.context(1);
// Connect to server
ZMQ.Socket requester = context.socket(ZMQ.REQ);
String address = "tcp://xxx.xx.xx.xx";
int port = 5000;
requester.connect(address + ":" + port);
// Initialize poll set
ZMQ.Poller poller = new ZMQ.Poller(1);
poller.register(requester, ZMQ.Poller.POLLIN);
requester.send("COORDINATES");
//while (true) {
String data;
poller.poll();
data = requester.recvStr();
System.out.println(data);
if (data == null) {
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} requester.close();
} catch (IllegalStateException ise) {
ise.printStackTrace();
}
}
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
}
After executing this code on my device, I'll get like 5-9 input data strings, which I receive from the server, but then the following exception appears:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
Process: com.example.viktoria.gazefocus, PID: 31339
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:353)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: com.example.viktoria.gazefocus.zmq.ZError$IOException: java.io.IOException: Too many open files
at com.example.viktoria.gazefocus.zmq.Signaler.makeFdPair(Signaler.java:94)
at com.example.viktoria.gazefocus.zmq.Signaler.<init>(Signaler.java:50)
at com.example.viktoria.gazefocus.zmq.Mailbox.<init>(Mailbox.java:51)
at com.example.viktoria.gazefocus.zmq.Ctx.<init>(Ctx.java:128)
at com.example.viktoria.gazefocus.zmq.ZMQ.zmq_ctx_new(ZMQ.java:244)
at com.example.viktoria.gazefocus.zmq.ZMQ.zmqInit(ZMQ.java:277)
at org.zeromq.ZMQ$Context.<init>(ZMQ.java:269)
at org.zeromq.ZMQ.context(ZMQ.java:254)
at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:73)
at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:67)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
at java.lang.Thread.run(Thread.java:764) 
Caused by: java.io.IOException: Too many open files
at sun.nio.ch.IOUtil.makePipe(Native Method)
at sun.nio.ch.PipeImpl.<init>(PipeImpl.java:42)
at sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)
at java.nio.channels.Pipe.open(Pipe.java:155)
at com.example.viktoria.gazefocus.zmq.Signaler.makeFdPair(Signaler.java:91)
at com.example.viktoria.gazefocus.zmq.Signaler.<init>(Signaler.java:50) 
at com.example.viktoria.gazefocus.zmq.Mailbox.<init>(Mailbox.java:51) 
at com.example.viktoria.gazefocus.zmq.Ctx.<init>(Ctx.java:128) 
at com.example.viktoria.gazefocus.zmq.ZMQ.zmq_ctx_new(ZMQ.java:244) 
at com.example.viktoria.gazefocus.zmq.ZMQ.zmqInit(ZMQ.java:277) 
at org.zeromq.ZMQ$Context.<init>(ZMQ.java:269) 
at org.zeromq.ZMQ.context(ZMQ.java:254) 
at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:73) 
at com.example.viktoria.gazefocus.MainActivity$NetworkCall.doInBackground(MainActivity.java:67) 
at android.os.AsyncTask$2.call(AsyncTask.java:333) 
at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
at java.lang.Thread.run(Thread.java:764) 
Apparently too many files are open. After research (I'm using Ubuntu 16.04) I changed the ulimit with ulimit -n 10000. Still this exception will happen. Sometimes I get more input data, sometimes less. Also if I set something like Executor executor = Executors.newFixedThreadPool(5); into the onCreate() method, nothing will change.
How to overcome this issue?
Thanks for reading!
You have a leak because you're not closing / ending / freeing something. I think that the context has to be terminated: context.term() after you close the requester...
Well, in distributed-system design, the infrastructure for signalling / messaging setup costs are not negligible. Some use-cases are more foregiving, some less.
Getting always a new Context() instance per each method-call and throwing it right away soon after by a clean-up call to it's .term()*-method is for sure better than having a hung-app or a frozen device, yet it is far from a fair design, respecting the process latencies and an "ecology"-of-resources.
Better first setup a semi-persistent infrastructure of resources ( each Context()-instance is typically a very expensive toy to instantiate ( API 4.2+ as of 2018-Q1 ), not so sharp for the Socket()-instances, but similar to the Poller() and all it's internal-AccessPoint(s) registration-hooks, yet the principle may extend on 'em too ).
Early re-factoring of the code will help not to extend the case with using expensive resources as a "consumable disposable".
The section:
while (true) {
try {
ZMQ.Context context = ZMQ.context(1);
// Connect to server
ZMQ.Socket requester = context.socket( ZMQ.REQ );
String address = "tcp://xxx.xx.xx.xx";
int port = 5000;
requester.connect( address + ":" + port );
...
}
...
}
is exactly a resources-devastating anti-pattern, altogether with repetitive latencies and even risks of remote-hangups and remote-rejections and similar issues.

Query working on local backend but not on deployed backend

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.

nullpointerexception error. trying to connect to the bitcoin server from my phone

I am fairly new to android, java, and mainly jsonrpc...
I have been stuck on this error for some time and i dont know if it is how i have coded it that is causing the issue or if i am trying to connect to the wrong server...
If you could help, it would be GREATLY appreciated.
here is the error code and the important code:
09-08 12:36:12.141: W/System.err(30361): Network exception: failed to connect to /10.10.11.75 (port 18332): connect failed: ECONNREFUSED (Connection refused)
09-08 12:36:12.151: W/dalvikvm(30361): threadid=11: thread exiting with uncaught exception (group=0x417df2a0)
09-08 12:36:12.151: E/AndroidRuntime(30361): FATAL EXCEPTION: AsyncTask #1
09-08 12:36:12.151: E/AndroidRuntime(30361): java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NullPointerException
at com.bitcoinapp.MainActivity.connect(MainActivity.java:219
at com.bitcoinapp.MainActivity.access$0(MainActivity.java:157)
at com.bitcoinapp.MainActivity$BitcoinConnect.doInBackground(MainActivity.java:143)
at com.bitcoinapp.MainActivity$BitcoinConnect.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-08 12:36:12.151: E/AndroidRuntime(30361): ... 5 more
this is the android code that i am using at the moment... all of which is run once the user presses the button on the application. I am working off my SAMSUNG S3 MINI and not an emulator.
I have had to omit some of the content, so showing line numbers wont help, but i have added in the ones that i think are important...
class Connection implements OnClickListener {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
new BitcoinConnect().execute();
}
}
private class BitcoinConnect extends AsyncTask<String, Integer, Object[]> {
#Override
protected Object[] doInBackground(String... params) {
// TODO Auto-generated method stub
connect();
return null;
}
}
public class BasicAuthenticator implements ConnectionConfigurator {
public void configure(HttpURLConnection connection) {
// add custom HTTP header
connection.addRequestProperty("myusername", "mypassword");
}
}
private void connect() { //(line 157)
//This is the code for the JSONRPC2-CLIENT iteraction
// The JSON-RPC 2.0 server URL
URL serverURL = null;
try {
serverURL = new URL("http://10.10.11.75:18332");
} catch (MalformedURLException e) {
// handle exception...
e.printStackTrace();
}
// Create new JSON-RPC 2.0 client session
JSONRPC2Session mySession = new JSONRPC2Session(serverURL);
mySession.setConnectionConfigurator(new BasicAuthenticator());
//This is for the bitcoin BASE interaction.
//for the Bitcoin Payment Request
String method = "getinfo";
Map<String,Object> params = new HashMap<String,Object>();
String id = "Request001";
JSONRPC2Request payment = new JSONRPC2Request(method, params, id);
String jsonString = payment.toString();
JSONRPC2Response response = null;
Log.i("Failed0", "Failed0");
try {
response = mySession.send(payment);
Log.i("response", String.valueOf(response));
mTextView.setText((CharSequence) response);
} catch (JSONRPC2SessionException e) {
System.err.println(e.getMessage());
// handle exception...
Log.i("response", String.valueOf(response));
}
// Print response result / error
if (response.indicatesSuccess()) { //(line 219)
System.out.println(response.getResult());
} else {
System.out.println(response.getError().getMessage());
}
}
I am using the JSONRPC2.0 libraries for the base code and the client code. I am trying to connect to the bitcoin testnet server. The IP there is one of many that i have tried...
I know that testnet is on port 18332 and the mainnet is 8332...
ive tried a localhost IP and that hasnt worked either.
I dont know if there is suppose to be other code that i must use in order for my phone to connect to the bitcoin server...
Please help me, thanks in advance
Lets apply some logical thinking.
According to the stack trace, the NullPointerException was thrown here:
if (response.indicatesSuccess()) {
That means response was null. (No other alternative!)
That means that the send call in
response = mySession.send(payment);
EITHER returned assigned null to response, OR it through a JSONRPC2SessionException that you caught.
I suspect it was the latter, and that the message "Network exception: failed to connect to /10.10.11.75 (port 18332): ..." was logged in the process. However, the evidence is not convincing. (There aren't any "I/..." lines in the logcat output ...)
In summary, what you have done is catch the exception that told you that the send has failed, and then proceed to try to process the non-existent response!
The underlying problem is that you app cannot connect to 10.10.11.75 on port 18332. I assume that you realize that 10.10.11.75 is a private IP address, and hence that you will only be able to connect to it if the server is on your local network.

Categories