首页 > 解决方案 > 从资产复制的数据库在 api 28 上为空(无表)

问题描述

我使用以下代码将数据库文件导出到手机内存。它在 Android 24 上运行良好,但在 API 28 上它只提供一个空文件:

public void exportDatabse() {
    try {
        if (sd.canWrite()) {
            String backupDBPath = "nameBCK.db";
            File currentDB = new File(MainActivity.this.getDatabasePath("dataBaseName.db").getPath());
            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();
                Toast.makeText(this,getString(R.string.stSuccess2),
                        Toast.LENGTH_LONG).show();
            }
        }

        else {
            REQUEST_TYPE=0;
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);}

    } catch (Exception e) {
        Toast.makeText(this,getString(R.string.stFaild),Toast.LENGTH_LONG).show();
    }
}

我还使用 onRequestPermissionsResult 请求写入存储的权限。

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                if (REQUEST_TYPE==0) exportDatabse();
                if (REQUEST_TYPE==1) importDB();
            } else {
                if (REQUEST_TYPE==0) Toast.makeText(this,getString(R.string.stFaild2),Toast.LENGTH_LONG).show();
                if (REQUEST_TYPE==1) Toast.makeText(this,getString(R.string.stFaild3),Toast.LENGTH_LONG).show();
                Log.e("value", "Permission Denied, You cannot use local drive .");
            }
            break;
        default:
            throw new IllegalStateException("Unexpected value: " + requestCode);
    }
}

标签: javaandroid

解决方案


我已经回答了这个问题。此问题仅出现在 Android 28 上。

关联

  public class DataBase extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "database.db";
private static String DATABASE_PATH = "";
private static String LAST_DATABASE_PATH = "";
private SQLiteDatabase mDataBase;
private final Context ctx;

public DataBase2(@Nullable Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    DATABASE_PATH = context.getDatabasePath(DATABASE_NAME).getPath();
    this.ctx = context;

    if (!checkIfDBExists()) {
        createDataBase();
    }

    File dbFile = new File(Environment.getDataDirectory().getPath()+"/data/"+ BuildConfig.APPLICATION_ID +"/databases");
    if (dbFile.isDirectory()) {
        String[] child = dbFile.list();
        assert child != null;
        for (int i = 0; i < child.length; i++) {
            if (!(child[i].equals("database.db") || child[i].equals(DATABASE_NAME))) {
                new File(dbFile, child[i]).delete();
            }
        }
    }
}

public void createDataBase() {
    this.getReadableDatabase();
    this.close();
    try {
        copyDataBase();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    try {
        File DbFile = ctx.getDatabasePath(DATABASE_NAME);
        if (DbFile.exists()) {
            copyDataBase();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private boolean checkIfDBExists() {
    File dbFile = new File(DATABASE_PATH);
    return dbFile.exists();
}



public void openDataBase() {
    close();
    mDataBase = SQLiteDatabase.openDatabase(DATABASE_PATH, null, CREATE_IF_NECESSARY);
}

private void copyDataBase() throws IOException {
    InputStream mInput = ctx.getAssets().open("database.db");
    String outfileName = DATABASE_PATH;
    OutputStream mOutput = new FileOutputStream(outfileName);
    byte[] buffer = new byte[1024];
    int mLength;
    while ((mLength = mInput.read(buffer)) > 0) {
        mOutput.write(buffer, 0, mLength);
    }
    mOutput.flush();
    mInput.close();
    mOutput.close();
}

@Override
public void onCreate(SQLiteDatabase db) {
}


@Override
public synchronized void close() {
    if (mDataBase != null)
        mDataBase.close();

    SQLiteDatabase.releaseMemory();
    super.close();
}
}

推荐阅读