在没有外部存储权限的情况下将 SQLite 数据库传输到另一台设备的工作方式(更新 Android 11)

Working way to transfer SQLite database to another device without external storage permissions (updates Android 11)

有了新的共享存储和新的 Android API 30 个要求,我找不到在新设备或其他设备上恢复数据库的方法。 直到此时,我才使用 File API 创建了数据库的副本。任何时候用户都可以将此文件放到任何云中,从云中下载到另一台设备上并在其上恢复数据库。当然,我用的是WRITE_EXTERNAL_STORAGE.

现在,Google 拒绝了该应用程序,并说我们应该使用 MediaStore API,它可以在没有任何权限的情况下解决该问题。我试过了,它只适用于同一台设备。直到创建了数据库文件,才没有复制 to/from 云或移动 to/from 另一个文件夹。在那种情况下 cursor.getCount == 0:

String[] projections = new String[]{MediaStore.Downloads._ID};
String selection = MediaStore.Downloads.DISPLAY_NAME + "=?";
String[] selectionArgs = new String[]{"database.db"};
String sortOrder = MediaStore.Downloads.DISPLAY_NAME + " ASC";
Cursor cursor = getApplicationContext().getContentResolver().query(MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL), projections, selection, selectionArgs, sortOrder);
Uri uri = null;
if (cursor != null) {
    int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID);
    cursor.moveToNext();
    long id = cursor.getLong(idColumn);
    uri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, id);
    try {
        ContentResolver contentResolver = getApplicationContext().getContentResolver();
        ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "rw");
        FileInputStream fileInputStream = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
        File dbFile = new File(Environment.getDataDirectory(), "/data/com.example.app/databases/database.db");
        FileOutputStream fileOutputStream = new FileOutputStream(dbFile);
        byte[] buf = new byte[1024];
        int len;
        while ((len = fileInputStream.read(buf)) > 0) {
            fileOutputStream.write(buf, 0, len);
        }
        fileOutputStream.close();
        fileInputStream.close();
        parcelFileDescriptor.close();
        restartApp();
    } catch (IOException e) {
        e.printStackTrace();
    }
    cursor.close();
}

代码或 MediaStore 有问题 API 不提供对已创建文件的任何操作?

E/DBError: exception
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0

我也试过 Google Drive API 直接从应用程序复制云上的数据库文件并下载它。但这也行不通,因为新设备不知道用于下载文件的文件 ID。

对此有什么想法吗?

想通了。 在没有任何存储权限的情况下,您的应用程序可以访问使用 MediaStore API 创建的文件。 但是如果:

  • 文件是 moved/copied 在设备存储中
  • 文件已上传到云端,然后从云端下载
  • 应用已重新安装

我在版本 28(仿真)、29(设备​​)、30(仿真)上对其进行了测试。

所以在我的情况下无论如何我需要:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>

不知道为什么但是在 Android 上读取自己的文件 Q 还不够 READ_EXTERNAL_STORAGE

我很幸运,Google 批准了应用程序。希望你也是。