копирование sqlite db на устройство Android не удается

У меня есть база данных sqlite, которую я скопировал в папку «актив». В своей проге я проверяю существует ли уже база, если нет то создаю новую и копирую. Я использовал (более или менее) код из http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/comment-page-2/

    public void createDataBase() throws IOException {
    boolean dbExist = checkDataBase();

    if (dbExist) {
        Log.i(DEBUG_TAG, "createDataBase -> Datenbank existiert");
        // 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();
        Log.i(DEBUG_TAG, "else, db existiert nicht 1");
        try {
            copyDataBase();
            Log.i(DEBUG_TAG, "nach copydatabase");
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }
}

/**
 * Checked ob Database bereits existiert
 * 
 * @return
 */
private boolean checkDataBase() throws SQLiteException {
    SQLiteDatabase checkDB = null;
    Boolean checkTable = false;
    try {
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);
        Log.i(DEBUG_TAG, "checkdatabase1");

    } catch (SQLiteException e) {
        Log.e(DEBUG_TAG, "Fehler checkDataBase: ", e);
    }
    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 = dbContext.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();
    Log.i(DEBUG_TAG, "copydatabase");
}

В эмуляторе работает отлично.

Потом попробовал запустить на своем устройстве (HTC Desire HD). Там я получаю следующее сообщение:

03-26 17:02:05.053: INFO/Database(24458): sqlite returned: error code = 14, msg = cannot open file at line 27206 of [42537b6056]

Это происходит, когда я пытаюсь в первый раз открыть БД. Когда я запускаю программу в эмуляторе, я не получаю это сообщение. Когда я запускаю программу 2-й раз, она находит базу данных, ошибок при открытии нет, но таблицы не существуют.

Я несколько раз отлаживал программу на эмуляторе и устройстве, но решения не нашел.

Может быть, это какая-то проблема с разрешением? (Поскольку я также не могу видеть БД на устройстве с adb --> разрешение запрещено')

Я очень новичок в андроиде, так что, может быть, я просто пропустил что-то глупое....

Спасибо


person user678199    schedule 26.03.2011    source источник


Ответы (2)


  1. Не создавайте пути с помощью конкатенации строк. Используйте соответствующий конструктор File.
  2. Ваш DB_PATH может быть недействительным, но, поскольку вы отказались его показывать, мы не можем сказать наверняка.
  3. Если класс, из которого исходит этот код, является SQLiteOpenHelper, ваш вызов getReadableDatabase() создаст пустую базу данных.
  4. «(Поскольку я также не могу увидеть базу данных на устройстве с adb -> разрешение запрещено» — это ожидаемо, поскольку у вас нет прав на просмотр этого каталога на рабочем устройстве.
person CommonsWare    schedule 26.03.2011
comment
Спасибо за Ваш ответ. Подсказка с конструктором файлов очень полезна. Я нашел решение на anddev.org/networking-database-problems-f29/ Я не знал, что это проблема конкретного устройства, поэтому несколько часов гуглил неправильные ключевые слова. . - person user678199; 27.03.2011
comment
@user678199 user678199: большое спасибо за ссылку... :) это должен быть ответ... не комментарий.. - person Deepzz; 04.01.2013

Я заставляю это работать, создавая свой собственный каталог и помещая файл в каталог.

String path=mContext.getDir("Folder_name", Context.MODE_WORLD_WRITEABLE).getAbsolutePath();

Код для создания папки.

Затем выполните нашу операцию проверки базы данных и копирования базы данных.

enter code here 

 public void createDataBase() throws IOException { 
 String path=mContext.getDir("Folder_Name", Context.MODE_WORLD_WRITEABLE).getAbsolutePath();
 DB_PATH=path;
 boolean mDataBaseExist = checkDataBase(); 
 if(!mDataBaseExist) 
 { 
   try  
    { 
     copyDataBase(); 
    }  
    catch (IOException mIOException)  
    { 
    Log.d("Exception",mIOException.getMessage());
    throw new Error("ErrorCopyingDataBase"); 
    } 
} 
}


private boolean checkDataBase() 
{ 
    Log.d(TAG, "In checkDataBase :::::"); 
    File dbFile = new File( DB_PATH+DATABASE_NAME); 
    Log.d("dbFile", dbFile + "   "+ dbFile.exists()); 
    return dbFile.exists(); 
} 

//Copy the database from assets 
private void copyDataBase() throws IOException 
{ 
    Log.d(TAG, "In copyDataBase :::::"); 
    InputStream mInput = mContext.getAssets().open(DB_NAME);
    String outFileName = DB_PATH  + DATABASE_NAME;

    Log.d(TAG, "In copyDataBase  outFileName:::::"+outFileName);

    OutputStream mOutput = new FileOutputStream(outFileName); 
    byte[] mBuffer = new byte[1024]; 
    int mLength; 
    while ((mLength = mInput.read(mBuffer))>0) 
    { 
        mOutput.write(mBuffer, 0, mLength); 
    } 
    mOutput.flush(); 
    mOutput.close(); 
    mInput.close(); 
} 

//Open the database, so we can query it 
public boolean openDataBase() throws SQLException 
{ 
    //DB_PATH +
    String mPath = DB_PATH+ DATABASE_NAME; 
    Log.v("mPath", mPath); 
    mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY); 
    return mDataBase != null; 
} 

Надеюсь, это поможет новичкам.

Ваше здоровье

person Jabeer    schedule 06.09.2012