Android 6 上未返回任何 fileEntry 结果
No fileEntry results returned on Android 6
我的 Cordova 应用程序中似乎存在文件读取权限问题,但我终究无法正确找到它。在 Android 5 和 Android 6 之间,我看到对 fileEntry
的相同调用得到完全不同的结果。 有谁知道是否需要更改才能在 Android > 5 中阅读 files/directories?
血淋淋的细节: 我只用 cordova-plugin-file
(调用 cordova create hello
)将代码复制到 helloWorld 应用程序,并得到相同的结果。我的改动如下:
我在 index.html
的正文中添加了一个元素:
<div id="contents"></div>
我还更改了 index.js
中的 stock receivedEvent 方法,只是为了遍历设备上的各种目录和 return cordova-plugin-file
给我的内容:
receivedEvent: function (id) {
"use strict";
var parentElement = document.getElementById(id),
listeningElement = parentElement.querySelector('.listening'),
receivedElement = parentElement.querySelector('.received'),
localURLs = [
cordova.file.documentsDirectory,
cordova.file.externalRootDirectory,
cordova.file.sharedDirectory,
cordova.file.syncedDataDirectory
],
DirsRemaining = localURLs.length,
i,
contents = "",
addFileEntry = function (entry) {
var dirReader = entry.createReader();
dirReader.readEntries(
function (entries) {
var i;
for (i = 0; i < entries.length; i += 1) {
if (entries[i].isDirectory === true) {
contents += "<h2> Directory: " + entries[i].fullPath + "</h2>";
// Recursive -- call back into this subdirectory
DirsRemaining += 1;
addFileEntry(entries[i]);
} else {
contents += "<p> File: " + entries[i].fullPath + "</p>";
}
}
DirsRemaining -= 1;
if (DirsRemaining <= 0) {
if (contents.length > 0) {
document.getElementById("contents").innerHTML = contents;
} else {
// nothing to select -- inform the user
document.getElementById("contents").innerHTML = "No documents found";
}
}
},
function (error) {
console.log("readEntries error: " + error.code);
contents += "<p>readEntries error: " + error.code + "</p>";
}
);
},
addError = function (error) {
// log the error and continue processing
console.log("getDirectory error: " + error.code);
DirsRemaining -= 1;
};
for (i = 0; i < localURLs.length; i += 1) {
if (localURLs[i] === null || localURLs[i].length === 0) {
DirsRemaining -= 1;
continue; // skip blank / non-existent paths for this platform
}
window.resolveLocalFileSystemURL(localURLs[i], addFileEntry, addError);
}
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
可能的安全配置:
我的 platforms/android/AndroidManifest.xml
文件包含适当的权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这是我在 index.html 中的 CSP(它只是库存的):
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
结果如下:
Android 5. 记下目录和一个文件(屏幕外还有其他的)
Android 6、注意我在cordova.file.externalRootDirectory
下的子目录下有一些文件应该显示;它还应该显示子目录本身。
向@greenapps 致敬——此行为显然是由于 Android 6.
中引入的运行时权限所致
对于 Cordova,有一个插件可以解决这个问题,直到 cordova-android
稍微清理一下(截至 11/6/2017,PhoneGap Build 使用 cordova-android 6.2.3,这取决于 cordova-plugin-compat
来处理这个)。我现在的修复:
cordova plugin add cordova.plugins.diagnostic
然后在例程中添加相应的运行时权限:
// 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);
});
我的 Cordova 应用程序中似乎存在文件读取权限问题,但我终究无法正确找到它。在 Android 5 和 Android 6 之间,我看到对 fileEntry
的相同调用得到完全不同的结果。 有谁知道是否需要更改才能在 Android > 5 中阅读 files/directories?
血淋淋的细节: 我只用 cordova-plugin-file
(调用 cordova create hello
)将代码复制到 helloWorld 应用程序,并得到相同的结果。我的改动如下:
我在 index.html
的正文中添加了一个元素:
<div id="contents"></div>
我还更改了 index.js
中的 stock receivedEvent 方法,只是为了遍历设备上的各种目录和 return cordova-plugin-file
给我的内容:
receivedEvent: function (id) {
"use strict";
var parentElement = document.getElementById(id),
listeningElement = parentElement.querySelector('.listening'),
receivedElement = parentElement.querySelector('.received'),
localURLs = [
cordova.file.documentsDirectory,
cordova.file.externalRootDirectory,
cordova.file.sharedDirectory,
cordova.file.syncedDataDirectory
],
DirsRemaining = localURLs.length,
i,
contents = "",
addFileEntry = function (entry) {
var dirReader = entry.createReader();
dirReader.readEntries(
function (entries) {
var i;
for (i = 0; i < entries.length; i += 1) {
if (entries[i].isDirectory === true) {
contents += "<h2> Directory: " + entries[i].fullPath + "</h2>";
// Recursive -- call back into this subdirectory
DirsRemaining += 1;
addFileEntry(entries[i]);
} else {
contents += "<p> File: " + entries[i].fullPath + "</p>";
}
}
DirsRemaining -= 1;
if (DirsRemaining <= 0) {
if (contents.length > 0) {
document.getElementById("contents").innerHTML = contents;
} else {
// nothing to select -- inform the user
document.getElementById("contents").innerHTML = "No documents found";
}
}
},
function (error) {
console.log("readEntries error: " + error.code);
contents += "<p>readEntries error: " + error.code + "</p>";
}
);
},
addError = function (error) {
// log the error and continue processing
console.log("getDirectory error: " + error.code);
DirsRemaining -= 1;
};
for (i = 0; i < localURLs.length; i += 1) {
if (localURLs[i] === null || localURLs[i].length === 0) {
DirsRemaining -= 1;
continue; // skip blank / non-existent paths for this platform
}
window.resolveLocalFileSystemURL(localURLs[i], addFileEntry, addError);
}
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
可能的安全配置:
我的 platforms/android/AndroidManifest.xml
文件包含适当的权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这是我在 index.html 中的 CSP(它只是库存的):
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
结果如下:
Android 5. 记下目录和一个文件(屏幕外还有其他的)
Android 6、注意我在cordova.file.externalRootDirectory
下的子目录下有一些文件应该显示;它还应该显示子目录本身。
向@greenapps 致敬——此行为显然是由于 Android 6.
中引入的运行时权限所致对于 Cordova,有一个插件可以解决这个问题,直到 cordova-android
稍微清理一下(截至 11/6/2017,PhoneGap Build 使用 cordova-android 6.2.3,这取决于 cordova-plugin-compat
来处理这个)。我现在的修复:
cordova plugin add cordova.plugins.diagnostic
然后在例程中添加相应的运行时权限:
// 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);
});