2012-04-11 3 views
1

EDIT: приложение сбой на мобильных телефонах с Android версии 2.3.5«SQLiteException: не удалось открыть файл базы данных» после первой загрузки файла .apk на рынок (Android 2.3.5)

I загрузил свое первое приложение на Google Play вчера, сегодня я получил сообщение об ошибке с происходит некорректно:

android.database.sqlite.SQLiteException: unable to open database file 
at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1956) 
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:918) 
at com.hazcheck.dgl.data.ExternalDBOpenHelper.openDataBase(ExternalDBOpenHelper.java:96) 
at com.hazcheck.dgl.SearchActivity.afterTextChanged(SearchActivity.java:284) 
at android.widget.TextView.sendAfterTextChanged(TextView.java:6566) 
at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:6989) 
at android.text.SpannableStringBuilder.sendTextHasChanged(SpannableStringBuilder.java:897) 
at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:353) 
at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:269) 
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:432) 
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:409) 
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:28) 
at android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.java:679) 
at android.view.inputmethod.BaseInputConnection.commitText(BaseInputConnection.java:185) 
at com.android.internal.widget.EditableInputConnection.commitText(EditableInputConnection.java:120) 
at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:332) 
at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:86) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:143) 
at android.app.ActivityThread.main(ActivityThread.java:4268) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:507) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
at dalvik.system.NativeStart.main(Native Method) 

EDIT: Вот мой класс SQLiteOpenHelper, я мог бы сделать что-то неправильно, пожалуйста, проверьте это:

package com.hazcheck.dgl.data; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.BufferedInputStream; 
import java.io.ByteArrayOutputStream; 
//import java.util.zip.ZipInputStream; 

import com.hazcheck.dgl.R; 

import android.content.Context; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 
//import android.content.res.Resources; 

public class ExternalDBOpenHelper extends SQLiteOpenHelper{ 

    //public static int DB_PATH_ID; 
    public static String DB_NAME; 
    public static String DB_PATH; 
    public static int DB_VERSION; 
    public SQLiteDatabase database; 
    public final Context context; 

    //private Resources resources; 

    public SQLiteDatabase getDb() { 
     return database; 
    } 
     public ExternalDBOpenHelper(Context context) { 
     super(context, DB_NAME = context.getString(R.string.app_data_name), null, DB_VERSION = Integer.parseInt((context.getString(R.string.app_database_version)))); 
     this.context = context; 
     String packageName = context.getPackageName(); 
     //resources = context.getResources(); 
     //DB_PATH_ID = R.raw.imdg35; 
     DB_PATH = String.format("//data//data//%s//databases//", packageName); 

     openDataBase(); //createDataBase(); 
    } 


    public void createDataBase() { 
     boolean dbExist = checkDataBase(); 
     if (!dbExist) { 
      this.getReadableDatabase(); 
      try { 
       copyDataBase(); 
      } catch (IOException e) { 
       Log.e(this.getClass().toString(), "Copying error"); 
       throw new Error("Error copying database!"); 
      } 
     } else { 
      Log.i(this.getClass().toString(), "Database already exists"); 
     } 
    } 

    private boolean checkDataBase() { 
     String path = DB_PATH + DB_NAME; 
     File dbFile = new File(path); 
     return dbFile.exists(); 
    } 

    private void copyDataBase() throws IOException { 
     InputStream externalDbStream = context.getAssets().open(DB_NAME); 

     String outFileName = DB_PATH + DB_NAME; 

     OutputStream localDbStream = new FileOutputStream(outFileName); 

    byte[] buffer = new byte[1024]; 
    int bytesRead; 
    while ((bytesRead = externalDbStream.read(buffer)) > 0) { 
     localDbStream.write(buffer, 0, bytesRead); 
    } 

    localDbStream.close(); 
    externalDbStream.close(); 
/* String outFileName = DB_PATH + DB_NAME; 
    InputStream is = resources.openRawResource(DB_PATH_ID); 
    OutputStream myOutput = new FileOutputStream(outFileName); 
    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is)); 
    try { 
     while (zis.getNextEntry() != null) { 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      byte[] buffer = new byte[1024]; 
      int count; 
      while ((count = zis.read(buffer)) != -1) { 
       baos.write(buffer, 0, count); 
       //Log.d("", buffer.toString()); 
      } 
      baos.writeTo(myOutput); 
     } 
    } 
    finally{ 
     zis.close(); 
     myOutput.flush(); 
     myOutput.close(); 
     is.close(); 
    }*/ 
} 

public SQLiteDatabase openDataBase() throws SQLException { 
    String path = DB_PATH + DB_NAME; 
    if (database == null) { 
     createDataBase(); 
     database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE); 
    } 
    return database; 
} 
@Override 
public synchronized void close() { 
    if (database != null) { 
     database.close(); 
    } 
    super.close(); 
} 
@Override 
public void onCreate(SQLiteDatabase db) {} 
@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} 
} 
+0

RU копирование на SD-карту? Если SD-карта отсутствует, значит, что вы делаете? Ru, создавая папку (mkdir) внутри SDCard? –

+0

вы уверены, что база данных будет скопирована до начала поиска? – njzk2

+0

Я тестировал приложение на разных устройствах и разных версиях Android, прежде чем загружать их на рынок, он всегда работал нормально. Если у кого-то есть Android-мобиль, вы также можете попробовать его, в Google Play ищите слово «DGL» и установите приложение с красным символом H diamond. –

ответ

0

Я обнаружил, что проблема в самой базе данных, она была создана со старой версией Sqlite. Теперь я использовал Sqlite 3.7.11 и воссоздал базу данных, и теперь она работает отлично.

0

1) Какая база данных вы имеете в виду в этой строке: com.hazcheck.dgl.SearchActivity.afterTextChanged(SearchActivity.java:284)? Имеется ли соответствующая база данных? Вы создавали или создавали базу данных в методе OnCreate()? Если нет, есть ваша ошибка. Вероятно, вы протестировали приложение на своем устройстве, где вы создали его только в первый раз; где приложение затем повторно использует базу данных, даже если вы замените пакет приложений.

2) Об «1 сообщение об ошибке, в то время как 0 устанавливает», Это случилось с моим приложением. Вероятно, процесс обновления количества установок является периодическим, а обновление журнала ошибок мгновенно.

+0

afterTextChanged вызывает метод Поиск, который фактически создает экземпляр базы данных, если он еще не создан, а затем открыть базу данных, ExternalDBOpenHelper dbOpenHelper = new ExternalDBOpenHelper (getBaseContext()); Я не создаю экземпляр в onCreate(). –

+0

IMHO, было бы лучше создать экземпляр базы данных в заглушке onCreate(), чтобы избежать дальнейших проблем. создание частной переменной db поля может оказаться плодотворным. – SamSPICA

+0

Я применил то, что вы мне сказали, и отправил на тестирование, надеюсь, что все будет хорошо. Другое дело, что нынешний на рынке не работал на одном HTC WildFire, но работал над другим аналогичным устройством HTC WildFire, странным. Я отредактировал свой вопрос и добавил еще одну функцию, которую я использую для чтения базы данных. –

0
> String outFileName = DB_PATH + DB_NAME; 

Это может быть проблема, если приложение установлено на SD-карте или в памяти телефона.

Класс DatabaseContext и его decendants (как Activity) есть метод

File getDatabasePath(String name) 

, который должен дать вам правильный каталог.

+0

Что моя функция copyDataBase делает, создайте новый файл, используя DB_PATH + DB_NAME, если файл еще не существует, что происходит при первом запуске. Затем распакуйте сжатую базу данных, находящуюся в необработанной папке, и переместите ее содержимое во вновь созданный файл. Путь к базе данных - DB_PATH = String.format ("// data // data //% s // databases //", packageName); –

+0

спасибо за помощь. Я пробовал ваше решение, но оно не сработало. Любые другие предложения? –

0

В моем случае, когда я открываю базу данных с databaseInstance этим методом

private static boolean openDB(String dbPathWithName) { 
     boolean status = true; 
     try { 
      if (databaseInstance == null || !databaseInstance.isOpen()){ 
       databaseInstance = SQLiteDatabase.openDatabase(dbPathWithName, null, SQLiteDatabase.OPEN_READWRITE + SQLiteDatabase.CREATE_IF_NECESSARY); 

      } 
     } catch (Exception ex){ 
      status = false; 
      NGAndroidUtil.logErr("DataHelper", ex.getMessage(), ex); 
     } 
     return status; 
    } 

В этом он бросить исключение «Не удается открыть базу данных» .... В этом я не даю путь базы данных в правильном формате, поэтому он бросает исключение «не может открыть базу данных ... Убедитесь, что путь к базе данных в правильном формате, который вы хотите открыть.

Смежные вопросы