SQLiteException - 仅在某些设备上发生

时间:2011-08-25 20:11:45

标签: android sqlite exception

我最近向市场发布了一款应用。从开发人员控制台看,似乎有1-2%的用户遇到此问题。 1-2%很小但人们更倾向于在某些内容不起作用时发表评论,而不是在可能会对下载产生负面影响的情况下发表评论。

不幸的是,开发者控制台仅将平台列为“其他”,但我的应用程序可供SDK 1.6+的用户使用。我也无法重新创建此问题,并且没有用户直接与我联系,因此我无法获得有关其失败的设备的更多信息。

这是堆栈

android.database.sqlite.SQLiteException: no such table: QUESTIONS: , while compiling: SELECT * FROM QUESTIONS WHERE DIFFICULTY=2 ORDER BY RANDOM() LIMIT 20
at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method)
at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:91)
at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:64)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:80)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:46)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1434)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1404)
at com.app.myapp.db.DBHelper.getQuestionSet(DBHelper.java:140)
at com.app.myapp.SplashActivity.getQuestionSetFromDb(SplashActivity.java:109)
at com.app.myapp.SplashActivity.onClick(SplashActivity.java:58)
at android.view.View.performClick(View.java:2421)
at android.view.View$PerformClick.run(View.java:8867)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)

getQuestionSetFromDb(SplashActivity.java:109)引用

List<Question> questions = myDbHelper.getQuestionSet(diff, numQuestions);

指的是

public List<Question> getQuestionSet(int difficulty, int numQ){
    List<Question> questionSet = new ArrayList<Question>();
    Cursor c = myDataBase.rawQuery("SELECT * FROM QUESTIONS WHERE DIFFICULTY=" + difficulty +
            " ORDER BY RANDOM() LIMIT " + numQ, null);
    while (c.moveToNext()){
        //Log.d("QUESTION", "Question Found in DB: " + c.getString(1));
        Question q = new Question();
        q.setQuestion(c.getString(1));
        q.setAnswer(c.getString(2));
        q.setOption1(c.getString(3));
        q.setOption2(c.getString(4));
        q.setOption3(c.getString(5));
        q.setRating(difficulty);
        questionSet.add(q);
    }
    return questionSet;
}

}

有没有人知道可能的原因?奇怪的是,这只是在少量安装的情况下发生,并且无法确定他们使用的SDK级别/设备使其变得更加困难。

感谢任何帮助

编辑:由于响应,我包括如何创建数据库。

首先,我的活动有这个(这与导致崩溃的方法相同)

    private List<Question> getQuestionSetFromDb() throws Error {
    int diff = getDifficultySettings();
    int numQuestions = getNumQuestions();
    DBHelper myDbHelper = new DBHelper(this);
    try {
        myDbHelper.createDataBase();
    } catch (IOException ioe) {
        throw new Error("Unable to create database");
    }
    try {
        myDbHelper.openDataBase();
    }catch(SQLException sqle){
        throw sqle;
    }
    List<Question> questions = myDbHelper.getQuestionSet(diff, numQuestions);
    myDbHelper.close();
    return questions;
}

myDBhelper.createdatabase()调用

public void createDataBase() throws IOException{

    boolean dbExist = checkDataBase();
    if(!dbExist)
    {
        //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");
        }
    }
}

checkDatabase()

    private boolean checkDataBase(){
    SQLiteDatabase checkDB = null;
    try{
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
    }catch(SQLiteException e){
        //database does't exist yet.
    }
    if(checkDB != null){
        checkDB.close();
    }

    return checkDB != null ? true : false;
}

copyDatabase()

    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();

}

变量

    private static String DB_PATH = "/data/data/com.app.myapp/databases/";
private static String DB_NAME = "questionsDb";
private SQLiteDatabase myDataBase; 
private final Context myContext;

Apoligies,我真的应该包括这个

2 个答案:

答案 0 :(得分:0)

错误报告缺少“QUESTIONS”数据库。 DB_NAME是“questionsDb”。

对于一个字符串附加+的int难度也让我感到困惑(此线程中早先已经有另一位用户报告过)。

答案 1 :(得分:0)

我只是觉得你创建数据库的方式导致了问题。没有什么问题;正如你所说,它适用于98%的设备。

在我看来,你可能最好延长SQLiteOpenHelper。如果数据库不存在,则负责创建数据库并且您不必手动执行任何检查。