【问题标题】:Database not getting copied properly in OnePlus Two数据库未在 OnePlus 2 中正确复制
【发布时间】:2015-09-21 14:01:54
【问题描述】:

我正在创建一个 Android 应用程序,并在其中使用 sqlite 数据库。为此,我在项目的资产文件夹中放置了一个 sqlite 文件,并且在我第一次使用下面的代码执行应用程序时将此文件复制到手机。

 private void copyDataBase() throws IOException {
    new File(DB_PATH).mkdirs();
    InputStream myInput = appContext.getAssets().open(DB_NAME);
    String outFileName = DB_PATH + DB_NAME;
    OutputStream myOutput = new FileOutputStream(outFileName);
    byte[] buffer = new byte[1024];
    int length;

    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    myOutput.flush();
    myOutput.close();
    myInput.close();
}

但我收到此错误。

 09-21 18:03:56.841: E/SQLiteLog(7850): (1) no such table: tbl_player

但该表存在于资产文件中。所以我使用这种方法从手机中获取数据库文件。

public static void exportDB(String databaseName, Context context) {
    try {
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();

        if (sd.canWrite()) {
            String currentDBPath = "//data//" + context.getPackageName()
                    + "//databases//" + databaseName + "";
            String backupDBPath = "sensor_game.db";
            File currentDB = new File(data, currentDBPath);
            File backupDB = new File(sd, backupDBPath);

            if (currentDB.exists()) {
                FileChannel src = new FileInputStream(currentDB)
                        .getChannel();
                FileChannel dst = new FileOutputStream(backupDB)
                        .getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
            }
        }

    } catch (Exception e) {

    }
}

我发现提取的数据库文件中没有表。

注意:此问题仅在 OnePlus Two 中出现,并且在 Nexus 4Htc 820Moto EGalxy S3Galaxy Quottro 中正常工作

【问题讨论】:

  • void exportDB。将该布尔值设为布尔值并添加代码以防 currentDB 不存在。该代码将/不能工作。
  • 有时我发现了同样的问题。
  • 我正在试验我在 OP2 中开发的应用程序的问题,这让我发疯了
  • 你找到解决这个问题的方法了吗?
  • 否:/仍在试图找出问题所在

标签: android sqlite assets oneplustwo


【解决方案1】:

不同设备的数据库路径可能不同。 您需要使用Context.getDatabasePath(String) 来获取数据库路径。

例如

File backupDB = context.getDatabasePath(backupDBPath);

【讨论】:

  • 我猜这是否比sqlite-asset-helper 中的这一行正确:github.com/jgilfelt/android-sqlite-asset-helper/blob/master/… - 对吧?
  • IMO 它仍然比完全硬编码的版本好。至少当应用程序移动到 sdcard 时它会正常运行。无论如何,我认为没有必要尝试假设路径,而系统已经提供了它。
  • 我没有得到你的评论,抱歉;我的意思是:如果必须使用 getDatabasePath() 是对的,那也应该是 sqlite-asset-helper 中的默认值,对吧?
  • IMO,最好使用 Context.getDatabasePath()。但这并不意味着context.getApplicationInfo().dataDir + "/databases" 是错误的。
  • IMO,除非供应商更改 Android 代码并构建自己的代码,否则由 Android 决定将数据库放在哪里而不是设备。
【解决方案2】:

经过长时间的尝试和搜索,我不得不假设 OP2 制造中应该存在错误,因为它在所有其他设备中都可以正常工作。

我改变了使用查询创建数据库的方法,而不是从资产中复制数据库文件。像下面的代码

import java.io.File;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MySQLiteHelper extends SQLiteOpenHelper implements DBConstants {

private static MySQLiteHelper mInstance = null;
private SQLiteDatabase myDataBase;
private static String DB_PATH = "";

public MySQLiteHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    try {
        if (checkDataBase())
            openDataBase();
        else
            myDataBase = this.getReadableDatabase();
    } catch (Exception e) {
    }
}

public static MySQLiteHelper instance(Context context) {

    File outFile = context.getDatabasePath(DATABASE_NAME);
    DB_PATH = outFile.getPath();

    if (mInstance == null) {
        mInstance = new MySQLiteHelper(context);
    }

    return mInstance;
}

private void openDataBase() throws Exception {
    try {
        myDataBase = SQLiteDatabase.openDatabase(DB_PATH, null,
                SQLiteDatabase.OPEN_READWRITE);
    } catch (SQLException e) {
        // TODO: handle exception
    }
}

private boolean checkDataBase() {
    SQLiteDatabase checkDB = null;
    try {
        checkDB = SQLiteDatabase.openDatabase(DB_PATH, null,
                SQLiteDatabase.OPEN_READONLY);

    } catch (SQLiteException e) {
        /** database does't exist yet. */
    } catch (Exception e) {
    }
    if (checkDB != null) {
        checkDB.close();
    }
    return checkDB != null ? true : false;
}

@Override
public void onCreate(SQLiteDatabase db) {

    Log.v("log_tag", "onCreate");
    myDataBase = db;

    // creating a sample table
    String CREATE_DEVICE_TABLE = "CREATE TABLE " + DEVICE + " ("
            + KEY_DEVICEID + " TEXT, " + KEY_OPERATOR + " TEXT, "
            + KEY_DEVICENAME + " TEXT, " + KEY_DEVICETOTALMEMORY
            + " INTEGER, " + KEY_SCREENWIDTH + " INTEGER, "
            + KEY_SCREENHEIGHT + " INTEGER, " + KEY_OPERATINGSYSTEM
            + " TEXT)";

    db.execSQL(CREATE_DEVICE_TABLE);

    // other tables also can be created from here.
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + DEVICE);

    // Create tables again (as per requirement)
    this.onCreate(db);
}

public Cursor rawQuery(String qry) {
    return myDataBase.rawQuery(qry, null);
}

public long insert(String tableName, ContentValues cv) {
    return myDataBase.insert(tableName, null, cv);
}

public void insertWithOnConflict(String tableName, ContentValues cv,
        int flag) {
    myDataBase.insertWithOnConflict(tableName, null, cv, flag);

}

public long update(String tableName, ContentValues cv, String whereClose) {
    return myDataBase.update(tableName, cv, whereClose, null);

}

public int deleteData(String table_name, String whereClause) {
    return (int) myDataBase.delete(table_name, whereClause, null);
}

}

它对我有用

谢谢!

【讨论】:

    【解决方案3】:

    我已经找到了解决方案,我使用了以下函数:

    public void createDb() {
            boolean dbExist = checkDataBase();
    
            if (dbExist) {
                // do nothing - database already exist
            } else {
                // call close() for properly copy database file
                this.getReadableDatabase().close();
                try {
                    copyDataBase();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new Error("Error copying database");
                }
            }
        }
    

    根据this post,我们需要调用close(),您也可以将数据库推送到一加两台设备上。

    【讨论】:

    • 谢谢老兄,你拯救了我的一天!
    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多