2

我在 android 应用程序中使用外部数据库,它在所有模拟器和三星真实设备上运行良好。但是当我在 Acer 智能手机上查看时,我的应用程序会崩溃,并出现以下异常:

android.database.sqlite.SQLiteException: no such table:

这对我来说很奇怪。我在文件资源管理器中的数据文件夹下检查了我的数据库和所有表所在的位置。

我不明白为什么会这样。

请指导我。提前致谢

sql helper类的代码如下:

public class MyDatabaseHelper extends SQLiteOpenHelper {

    // System path of application database.
    private static String DB_PATH = MyApplication.getAppContext()
            .getFilesDir().getParentFile().getPath()
            + "/databases/";
    private static String DB_NAME = "myDB";
    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 MyDatabaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    /**
     * Creates a empty database on the system and rewrites it with own database.
     * 
     */
    public void createDataBase() throws IOException {

        checkDataBase();
        // Creates empty database default system path
        this.getReadableDatabase();
        try {
            copyDataBase();
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }

    /**
     * Checks if the database already exist to avoid re-copying the file each
     * time whenever the application opened.
     * 
     * @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) {
            e.printStackTrace();
        }

        if (checkDB != null) {
            checkDB.close();
        }
        return checkDB != null ? true : false;
    }

    /**
     * Copies database from local assets-folder to the just created empty
     * database in the system folder and from where it can be accessed and
     * handled using byte stream transferring.
     * 
     */
    private void copyDataBase() throws IOException {

        // Open local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME + ".db");

        // Path of 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 input file to the output file
        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 SQLiteDatabase openDataBase() throws SQLException {

        // Opens the database
        String myPath = DB_PATH + DB_NAME;
        return SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READONLY);
    }

    @Override
    public synchronized void close() {
        if (myDataBase != null)
            myDataBase.close();
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
        // TODO Auto-generated method stub
    }
}
4

3 回答 3

4

最后我解决了我的问题。

我只是将可读数据库放入数据库并在再次打开后将其关闭。我的完整代码如下:

 public class MyDatabaseHelper extends SQLiteOpenHelper {

    // System path of application database.
    private static String DB_PATH = MyApplication.getAppContext()
            .getFilesDir().getParentFile().getPath()
            + "/databases/";
    private static String DB_NAME = "myDB";
    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 MyDatabaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    /**
     * Creates a empty database on the system and rewrites it with own database.
     * 
     */
    public void createDataBase() throws IOException {

        checkDataBase();
        SQLiteDatabase db_Read = null;

        // Creates empty database default system path
        db_Read = this.getReadableDatabase();
        db_Read.close();
        try {
            copyDataBase();
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }

    /**
     * Checks if the database already exist to avoid re-copying the file each
     * time whenever the application opened.
     * 
     * @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) {
            e.printStackTrace();
        }

        if (checkDB != null) {
            checkDB.close();
        }
        return checkDB != null ? true : false;
    }

    /**
     * Copies database from local assets-folder to the just created empty
     * database in the system folder and from where it can be accessed and
     * handled using byte stream transferring.
     * 
     */
    private void copyDataBase() throws IOException {

        // Open local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME + ".db");

        // Path of 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 input file to the output file
        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 SQLiteDatabase openDataBase() throws SQLException {

        // Opens the database
        String myPath = DB_PATH + DB_NAME;
        return SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READONLY);
    }

    @Override
    public synchronized void close() {
        if (myDataBase != null)
            myDataBase.close();
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
        // TODO Auto-generated method stub
    }
}

我在这里找到了答案:

于 2013-03-20T09:35:24.683 回答
0

可能您已经硬编码了数据库的路径。对于不同的设备,可能会有所不同。用于Envirenment.getExternalStorageDirectory()创建数据库的路径。

于 2013-03-18T10:52:51.000 回答
0

尝试使用这个私有静态字符串 DB_PATH = "/data/data/your package name/databases/";

于 2013-03-20T09:38:57.193 回答