现在好了。我的部分问题是我被cordova上的文件系统/cordova-plugin-file API的异步特性所困扰。我必须进行一些代码重构才能使文件列表正确显示,但是一旦我这样做了,文件就会正确显示,无论它们在设备上的什么位置。
这是适用的代码。请注意,您需要将 cordova-plugin-file 添加到您的 Cordova/PhoneGap 项目中,并且它在浏览器中不起作用。我实际上在另一个 if/then 块内有这个块——如果它在浏览器中运行,则显示 html5 <input type=file>,如果它在移动设备中,则显示此块:
var localURLs = [
cordova.file.dataDirectory,
cordova.file.documentsDirectory,
cordova.file.externalApplicationStorageDirectory,
cordova.file.externalCacheDirectory,
cordova.file.externalRootDirectory,
cordova.file.externalDataDirectory,
cordova.file.sharedDirectory,
cordova.file.syncedDataDirectory
];
var index = 0;
var i;
var statusStr = "";
var addFileEntry = function (entry) {
var dirReader = entry.createReader();
dirReader.readEntries(
function (entries) {
var fileStr = "";
var i;
for (i = 0; i < entries.length; i++) {
if (entries[i].isDirectory === true) {
// Recursive -- call back into this subdirectory
addFileEntry(entries[i]);
} else {
fileStr += (entries[i].fullPath + "<br>"); // << replace with something useful
index++;
}
}
// add this directory's contents to the status
statusStr += fileStr;
// display the file list in #results
if (statusStr.length > 0) {
$("#results").html(statusStr);
}
},
function (error) {
console.log("readEntries error: " + error.code);
statusStr += "<p>readEntries error: " + error.code + "</p>";
}
);
};
var addError = function (error) {
console.log("getDirectory error: " + error.code);
statusStr += "<p>getDirectory error: " + error.code + ", " + error.message + "</p>";
};
for (i = 0; i < localURLs.length; i++) {
if (localURLs[i] === null || localURLs[i].length === 0) {
continue; // skip blank / non-existent paths for this platform
}
window.resolveLocalFileSystemURL(localURLs[i], addFileEntry, addError);
}
编辑(2018 年 2 月):即使您可以在 Android 文件传输中看到文件,您也可能不会以编程方式获得任何结果,即使您在 Cordova 应用程序中设置了构建时间权限。这是由于 runtime 添加到 Android 的权限检查(我相信 > 6.0)。有几个插件可以帮助解决这个问题;在某些时候,我猜文件插件也会为它添加自动请求。以下是我在 Cordova cli-7.0.1 所做的工作:
在您的 config.xml 中,设置所需的应用权限。您将需要 READ_EXTERNAL_STORAGE (如果您要这样做,也需要编写)。我还添加了下面引用的两个插件:
<plugin name="cordova-plugin-device" source="npm" spec="1.1.6" />
<plugin name="cordova.plugins.diagnostic" spec="^3.7.1" />
<config-file platform="android" parent="/manifest" mode="replace">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
然后,最好在应用启动代码中的某个位置(即设备就绪事件的处理程序)检查运行时权限并在需要时添加它们:
if (device.platform === "Android") {
// request read access to the external storage if we don't have it
cordova.plugins.diagnostic.getExternalStorageAuthorizationStatus(function (status) {
if (status === cordova.plugins.diagnostic.permissionStatus.GRANTED) {
console.log("External storage use is authorized");
} else {
cordova.plugins.diagnostic.requestExternalStorageAuthorization(function (result) {
console.log("Authorization request for external storage use was " + (result === cordova.plugins.diagnostic.permissionStatus.GRANTED ? "granted" : "denied"));
}, function (error) {
console.error(error);
});
}
}, function (error) {
console.error("The following error occurred: " + error);
});
}
编辑(2021 年 8 月):Android 10.x 及更高版本引入了范围存储的概念,该概念在 Android 11 中得到了进一步完善(请参阅https://developer.android.com/about/versions/11/privacy/storage)。其中大部分是为了加强设备的安全性。这对您的应用意味着,如果您是一名优秀的 Android 公民,则对永久文件的读取/写入应仅限于以下两个沙盒目录:
- cordova.file.externalDataDirectory(如果您有 SD 卡)
- cordova.file.data 目录
除非您有充分的理由查看整个文件系统(并且可以让 Google Play 商店团队相信这一点),如果您尝试这样做,您的应用很可能会被拒绝调用所有文件访问。来自链接的文章:
Note: If you publish your app to Google Play, carefully read the notice. If you target Android 11 and declare All files access, it can affect your ability to publish and update your app on Google Play.