SQLiteDiskIOException: disk I / O error (code 3850)

I get the above error on some devices (very rare, 2 times so far):

android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 3850) at android.database.sqlite.SQLiteConnection.nativeExecuteForString(Native Method) at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:679) at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:361) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:236) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:200) 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 ***.a(***.java:115) 

In my code the following line:

 // here the exception occurs SQLiteDatabase db = SQLiteDatabase.openDatabase(pathApp, null, SQLiteDatabase.OPEN_READONLY); // ... db.close(); 

History

What am I doing:

  • application has root privileges
  • it copies the database from another application to its own directory
  • he is trying to open this database and read some data
  • it will close the file again

It's all. It works on thousands of devices. My application probably only accesses the database in place, I am completely sure of it

Question

Does anyone know what might cause this problem?

Perhaps interesting facts

  • 2 devices - OnePlus2
  • One guy told me that the problem arose after upgrading to Oxygen 2.1
+5
source share
3 answers

Here's a working solution (it has already been tested in production for 2 months or so), and it works on OnePlus2 and Android 6:

Then in your application, try reading an external database, for example the following:

  • Find out which binary is working. I tried several methods (for example, when calling /proc/cpuinfo ), but could not find a reliable solution, so I do this through a trial version and an error, for example:
    • First, I copy the binary from my resources folder to the files application folder
    • Then I try to dump the desired database through <path_to_SQLite3_bnary> <path_to_database> \.dump '<tablename>'\n and read the result
    • I check the result if it contains error: I know that the binary does not work if it starts with INSERT INTO I know that it works
    • I repeat this with my binaries until I find a working binary
  • Then I just read the result. The result will contain an error or look like csv. I either handle the error or convert each row to a valid csv via row.replace("INSERT INTO \"" + tablename + "\" VALUES(", "").replace(");", "") content in csv format. I use opencsv CSVReader for data analysis, then ...

What is it, it works (not yet known) on all devices without problems

Code - copied from my sources, a little suitable for your needs

 public static List<String> readCSVData(String pathDatabase, String tableName) throws InterruptedException, TimeoutException, RootDeniedException, IOException { List<String> res = null; List<String> csvData = null; final String[] architectures = new String[]{ "armv7", "armv7-pie", "armv6", "armv6-nofpu" }; for (int i = 0; i < architectures.length; i++) { res = readDatabase(architectures[i], pathDatabase, tableName, rootMethod); if (res.toString().contains("[error:")) { Ld(RootNetworkUtil.class, "Trial and Error - ERROR: " + architectures[i]); } else { int maxLength = (res.toString().length() < 100) ? res.toString().length() : 100; Ld(RootNetworkUtil.class, "Trial and Error - RESULT: " + res.toString().substring(0, maxLength)); Ld(RootNetworkUtil.class, "Architecture found via trial and error: " + architectures[i]); csvData = res; break; } } return csvData; } private static List<String> readDatabase(String architecture, String pathDB, String tablename) throws InterruptedException, TimeoutException, RootDeniedException, IOException { String sqlite = "sqlite3." + architecture; String pathSQLite3 = getSQLitePath(architecture, tablename); // OWN class, just copy the file from the assets to the sqlite3 path!!! AssetUtil.copyAsset(sqlite, pathSQLite3); String[] cmd = new String[]{ "su\n", //"chown root.root " + pathSQLite3 + "\n", "chmod 777 " + pathSQLite3 + "\n", pathSQLite3 + " " + pathDB + " \".dump '" + tablename + "'\"\n" }; List<String> res = new ArrayList<>(); List<String> temp = RootUtils.execute(cmd); for (int i = 0; i < temp.size(); i++) { // Fehlerzeilen behalten!!! if (temp.get(i).contains("error:")) res.add(temp.get(i)); else if (temp.get(i).startsWith("INSERT INTO \"" + tablename + "\"")) res.add(temp.get(i).replace("INSERT INTO \"" + tablename + "\" VALUES(", "").replace(");", "")); } return res; } public static String getSQLitePath(String architecture, String addon) { String sqlite = "sqlite3." + architecture; String pathSQLite3 = "/data/data/" + MainApp.get().getPackageName() + "/files/" + sqlite + addon; return pathSQLite3; } 
0
source

I recently encountered a similar problem when my application works fine on all Android devices except OnePlus Two running on OxygenOS 2.1.

Having studied the problem, it seems that this particular combination is very sensitive and fails in any database lock. In my case, my application copied the new database to the device the first time it was started, then checking the version of the database to see if an update was needed. On the check, it crashed on these devices. I understood in my code. I open a separate database instance instead of using an open database when checking the version. After changing the code in order not to open a separate instance of the database, the application stopped crashing on OnePlus.

My advice: do not open multiple database instances in your application or close the database first before reopening it (perhaps your copy method did not close the database or did not use another instance of the same database).

+1
source

Just met this in development. This worked when the phone ran out of batteries and turned off. Presumably, you just need to capture the database lock when this happens.

+1
source

Source: https://habr.com/ru/post/1232194/


All Articles