将数据库从内部存储复制到我的应用程序的数据目录

Copy database from internal storage to data directory of my application

我想将一个数据库文件从内部存储目录复制到我的应用程序的数据文件夹中。

这是我的代码:

public static void copyDatabase(Context applicationContext){
    try {
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();
        if (data.canWrite()) {
            String dbPath = "/data/data/" + "my.package.here" + "/databases/dbname";
            String actualDBPath = "dbname.sqlite";
            File finalDB = new File(dbPath);
            File actualDB = new File(sd, actualDBPath);
            if (actualDB.exists()) {
                FileChannel src = new FileInputStream(actualDB).getChannel();
                FileChannel dst = new FileOutputStream(finalDB).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
            }
        }
        Toast.makeText(applicationContext, "Save completed !!.", Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

虽然我调用了 copydatabase 函数,但当编译器到达 data.canWrite() 时,它 returns 为假。我该如何解决?

Ship an application with a database

public class PlanDetailsSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = "SQLiteOpenHelper";

private final Context context;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "my_custom_db";

private boolean createDb = false, upgradeDb = false;

public PlanDetailsSQLiteOpenHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    this.context = context;
}

/**
 * Copy packaged database from assets folder to the database created in the
 * application package context.
 * 
 * @param db
 *            The target database in the application package context.
 */
private void copyDatabaseFromAssets(SQLiteDatabase db) {
    Log.i(TAG, "copyDatabase");
    InputStream myInput = null;
    OutputStream myOutput = null;
    try {
        // Open db packaged as asset as the input stream
        myInput = context.getAssets().open("path/to/shipped/db/file");

        // Open the db in the application package context:
        myOutput = new FileOutputStream(db.getPath());

        // Transfer db file contents:
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }
        myOutput.flush();

        // Set the version of the copied database to the current
        // version:
        SQLiteDatabase copiedDb = context.openOrCreateDatabase(
            DATABASE_NAME, 0, null);
        copiedDb.execSQL("PRAGMA user_version = " + DATABASE_VERSION);
        copiedDb.close();

    } catch (IOException e) {
        e.printStackTrace();
        throw new Error(TAG + " Error copying database");
    } finally {
        // Close the streams
        try {
            if (myOutput != null) {
                myOutput.close();
            }
            if (myInput != null) {
                myInput.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new Error(TAG + " Error closing streams");
        }
    }
}

@Override
public void onCreate(SQLiteDatabase db) {
    Log.i(TAG, "onCreate db");
    createDb = true;
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    Log.i(TAG, "onUpgrade db");
    upgradeDb = true;
}

@Override
public void onOpen(SQLiteDatabase db) {
    Log.i(TAG, "onOpen db");
    if (createDb) {// The db in the application package
        // context is being created.
        // So copy the contents from the db
        // file packaged in the assets
        // folder:
        createDb = false;
        copyDatabaseFromAssets(db);

    }
    if (upgradeDb) {// The db in the application package
        // context is being upgraded from a lower to a higher version.
        upgradeDb = false;
        // Your db upgrade logic here:
    }
}
}