我目前正在运行一个应用程序。该应用程序并未在商店发布,而是作为 apk 分发供用户下载。 我们决定在 Google Play 商店上发布更新后的应用程序。在发布时,我们正在尝试实现一个功能,将保存在 SD 卡上的数据从旧应用程序转移到新应用程序,但我不知道该怎么做,所以我提出了一个问题。
我试图实现的功能如下。
我们已确认在 Android7 及更高版本上可以使用存储访问框架的 DocumentsContract.moveDocument() 移动文件。但是,上述方法无法在我的Android 5设备上使用,因此我采用了不同的方式实现。但是,我被告知权限被拒绝,无法迁移数据。
下面是我实现的部分代码。
正在执行处理的方法
void forTEST() {
File fileDir = getExternalFilesDir(null);
File[] fileDirs = getExternalFilesDirs(null);
File appAExternalFileDir = null;
for (File dir : fileDirs) {
if ( dir != null && !fileDir.equals(dir) && Environment.isExternalStorageRemovable(dir)) {
appAExternalFileDir = dir;
}
}
if (appAExternalFileDir == null) return;
String appAExternalFileDirPath = appAExternalFileDir.getAbsolutePath();
Log.d("testlog", "externalFileDirPath:" + appAExternalFileDir.getAbsolutePath()); // externalFileDirPath:/storage/MicroSD/Android/data/com.example.testAppA/files
Log.d("testlog", appAExternalFileDir.canRead() ? "true" : "false"); // true
Log.d("testlog", appAExternalFileDir.canWrite() ? "true" : "false"); // true
String appBExternalFileDirPath =
String appBExternalFileDirPath = appAExternalFileDirPath.replace("com.example.testAppA", "testAppB");
File appBExternalFileDir = new File(appBExternalFileDirPath);
Log.d("testlog", "externalFileDirPath:" + appBExternalFileDir.getAbsolutePath());// externalFileDirPath:/storage/MicroSD/Android/data/com.example.testAppB/files
Log.d("testlog", appBExternalFileDir.canRead() ? "true" : "false"); // true
Log.d("testlog", appBExternalFileDir.canWrite() ? "true" : "false"); // true
File[] appAFiles = appAExternalFileDir.listFiles();
for(int i=0; i<appAFiles.length; i++) {
String fileName = appAFiles[i].getName();
File destFile = new File(appBExternalFileDir, appAFiles[i].getName());
moveFileToDest(appAFiles[i], destFile);
// I tried renameTo() but only found true/false, so I created moveFileToDest() and executed it.
// renameTo() returned false.
// if (appAFiles[i].renameTo(destFile)) {
// Log.d("testLog", "success to renameTo()");
// } else {
// Log.d("testlog", "failure to renameTo()");
// }
}
}
void moveFileToDest(File sourceFile, File destinationFile) {
try {
// When I performed the move process described below without creating a new file first, a FileNotFoundException occurred, so I added createNewFile().
if (destinationFile.createNewFile()) { // throw java.io.IOException: open failed: EACCES (Permission denied)
Log.d("testlog", "create success!!");
} else {
Log.d("testlog", "create failed");
}
FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(destinationFile);
FileChannel sourceChannel = fis.getChannel();
FileChannel destinationChannel = fos.getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel);
sourceChannel.close();
fis.close();
destinationChannel.close();
fos.close();
sourceFile.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
AndroidManifest.xml(摘录)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
appAExternalFileDir 和 appBExternalFileDir 的 canRead() 和 canWrite() 都是 true。 但是当我尝试在 appBExternalFileDir 中创建文件时,我收到 IOException 并显示权限被拒绝。
我该怎么办。 如果你能告诉我,我很高兴。 (如果有遗漏的信息,请告诉我,以便我补充)
由于 Android 4 KitKat 可移动微型 SD 卡是只读的,除了其上的应用程序特定目录之外,您应该让新应用程序将文件从旧位置复制到新位置。
在 Android 5 上,应用程序可以读取卡上 Android 目录中的所有文件。但他们只能写入自己的特定文件目录。