Intereting Posts
Вызывать пользовательскую активность как startActivityForResult Библиотека проверки лицензии Android и несколько учетных записей Google Ссылка на ссылку сброса Firebase не работает Canvas – масштабирование, изменение и масштабирование на Android Превышение предела метода 65k Dex, но инструменты для подсчета меток dex говорят, что намного меньше Переопределение атрибутов стиля ссылок Использование Android RecognizerIntent с Bluetooth-гарнитурой Как сделать пару через bluetooth для печати zebra mz320? Android-студия Gradle download загрузить Переопределение физической кнопки меню на Android Pakage для проверки токена входа в Google в режиме Go on GAE Firebase onMessageReceived не вызывается, когда приложение находится в фоновом режиме Как хранить данные из нескольких приложений в одном месте? Как подключиться к нескольким базам данных firebase из приложения Android Java.lang.NullPointerException: попытка вызвать виртуальный метод 'android.view.View android.app.Activity.findViewById (int)' для ссылки на нулевой объект

Ошибка «Ошибка открытия базы данных» при копировании базы данных sqlite из активов В Android 4.2

Мой код отлично работает для Android 2.3, но я не знаю, почему он не работает для Android 4.2

Мой журнал исключения здесь

01-17 09:54:04.411: E/SQLiteLog(24202): (14) cannot open file at line 30176 of [00bb9c9ce4] 01-17 09:54:04.411: E/SQLiteLog(24202): (14) os_unix.c:30176: (2) open(/data/data/com.example.myapp/databases/myapp.db) - Failed to open database '/data/data/com.example.mypapp/databases/myapp.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) 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 com.example.myapp.DataBaseHelper.checkDataBase(DataBaseHelper.java:80) at com.example.myapp.DataBaseHelper.createDataBase(DataBaseHelper.java:47) at com.example.myapp.MainActivity.onCreate(MainActivity.java:61) at android.app.Activity.performCreate(Activity.java:5104) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230) at android.app.ActivityThread.access$600(ActivityThread.java:141) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5039) 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:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method) 

Мой MainActivity.java

 public class MainActivity extends Activity { public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.activity_main); DataBaseHelper myDbHelper; myDbHelper = new DataBaseHelper(this); try { myDbHelper.createDataBase(); } catch (IOException ioe) { throw new Error("Unable to create database"); } try { myDbHelper.openDataBase(); } catch (SQLException sqle) { throw sqle; } finally { myDbHelper.close(); } }} 

Моя база данныхHelper.java

 public class DataBaseHelper extends SQLiteOpenHelper{ //The Android's default system path of your application database. private static String DB_PATH = "/data/data/com.example.myapp/databases/"; private static String DB_NAME = "myapp.db"; private SQLiteDatabase myDataBase; private final Context myContext; /** * Constructor * Takes and keeps a reference of the passed context in order to access to the application assets and resources. * @param context */ public DataBaseHelper(Context context) { super(context, DB_NAME, null, 1); this.myContext = context; } /** * 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.getReadableDatabase(); 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(){ SQLiteDatabase checkDB = null; try{ String myPath = DB_PATH + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); }catch(SQLiteException e){ Log.i("Hellloooo", e.getMessage()); //database does't exist yet. } if(checkDB != null){ checkDB.close(); } return checkDB != null ? true : false; } /** * 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; 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_READONLY); } @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) { } // 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. } 

Solutions Collecting From Web of "Ошибка «Ошибка открытия базы данных» при копировании базы данных sqlite из активов В Android 4.2"

Мне пришлось изменить checkDataBase () на

  private boolean checkDataBase() { File databasePath = mContext.getDatabasePath(DB_NAME); return databasePath.exists(); } 

Я столкнулся с этой проблемой, потому что в 4.2 существует поддержка нескольких пользователей, и если вы тестируете пользователя, не являющегося администратором, вы не можете использовать путь acess /data/data .

В моем случае я использую путь:

 context.getFilesDir().getAbsolutePath().replace("files", "databases") + File.separator 

Надеюсь, это поможет..

Некоторые устройства не могут обрабатывать большие активы. То, что я сделал, – это разделение базы данных на 1 кубик MiB и скопировать их в файл

Я создал сценарий (для Linux), чтобы легко разбить файл

 #!/bin/bash #split database file into chunks not larger than 1 MiB split -b 1048576 databasename db -d -a1 

Куски будут называться db0, db1, db2, …, dbN

 /** * Copies database from assets to a file if not exists. * * @param context Application's Context */ public static void copyDatabase(Context context) { File target = context.getDatabasePath(databasename"); if (target.exists()) { return; } target.getParentFile().mkdirs(); InputStream is = null; OutputStream os = null; try { List<String> filesl = new ArrayList<String>(); String[] files = context.getAssets().list(""); if (files != null) { for (int i = 0; i < files.length; i++) { if (Pattern.matches("^db\\d.db$", files[i])) { filesl.add(files[i]); } } } files = null; Collections.sort(filesl); if (filesl.isEmpty()) { return; } os = new FileOutputStream(target); for (int i = 0; i < filesl.size(); i++) { is = context.getAssets().open(filesl.get(i), AssetManager.ACCESS_BUFFER); byte[] buffer = new byte[5096]; int read; while (true) { read = is.read(buffer, 0, buffer.length); if (read < 0) break; os.write(buffer, 0, read); } is.close(); } } catch (Exception e) { if (target.exists()) { target.delete(); } e.printStackTrace(); } finally { if (is != null) try { is.close(); } catch (Exception e) { } if (os != null) try { os.close(); } catch (Exception e) { } } } 

Обратите внимание, что Collections.sort будет сортировать имена в правильном порядке, если не более 10 файлов в случае db0 … db9 – после db10 вам придется написать свою собственную сортировку или комаратор.