Skip to content

Commit 5731347

Browse files
committed
feat(android)!: add removable and media dirs to known paths, then add to allowed
1 parent a0e6f47 commit 5731347

File tree

2 files changed

+81
-19
lines changed

2 files changed

+81
-19
lines changed

README.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ Each URL is in the form _file:///path/to/spot/_, and can be converted to a
103103
* `cordova.file.externalCacheDirectory` - Application cache on external storage.
104104
(_Android_)
105105

106+
* `cordova.file.externalMediaDirectory` - Application media directory on external storage. (_Android_)
107+
106108
* `cordova.file.externalRootDirectory` - External storage (SD card) root. (_Android_, _BlackBerry 10_)
107109

108110
* `cordova.file.tempDirectory` - Temp directory that the OS can clear at will. Do not
@@ -117,6 +119,14 @@ Each URL is in the form _file:///path/to/spot/_, and can be converted to a
117119

118120
* `cordova.file.sharedDirectory` - Files globally available to all applications (_BlackBerry 10_)
119121

122+
* `cordova.file.removableExternalApplicationStorageDirectories` - Application space on removable external storages. (_Android_)
123+
124+
* `cordova.file.removableExternalDataDirectories` - Where to put app-specific data files on removable external storages. (_Android_)
125+
126+
* `cordova.file.removableExternalCacheDirectories` - Application cache on removable external storages. (_Android_)
127+
128+
* `cordova.file.removableExternalMediaDirectories` - Application media directory on removable external storages. (_Android_)
129+
120130
## File System Layouts
121131

122132
Although technically an implementation detail, it can be very useful to know how
@@ -162,8 +172,14 @@ the `cordova.file.*` properties map to physical paths on a real device.
162172
|       `Documents` | | documents | r/w | Yes | No | Yes |
163173
| `<sdcard>/` | externalRootDirectory | sdcard | r/w\*\*\* | Yes | No | No |
164174
| &nbsp;&nbsp;&nbsp;`Android/data/<app-id>/` | externalApplicationStorageDirectory | - | r/w | Yes | No | No |
165-
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`cache` | externalCacheDirectory | cache-external | r/w | Yes | No\*\*| No |
175+
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`cache` | externalCacheDirectory | cache-external | r/w | Yes | No\*\*| No |
166176
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`files` | externalDataDirectory | files-external | r/w | Yes | No | No |
177+
| &nbsp;&nbsp;&nbsp;`Android/media/<app-id>/` | externalMediaDirectory | - | r/w | Yes | No | No |
178+
| `<removable sdcard>/` (0 or more) | | - | r/w\*\*\* | Yes | No | No |
179+
| &nbsp;&nbsp;&nbsp;`Android/data/<app-id>/` | removableExternalApplicationStorageDirectories | - | r/w | Yes | No | No |
180+
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`cache` | removableExternalCacheDirectories | - | r/w | Yes | No\*\*| No |
181+
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`files` | removableExternalDataDirectories | - | r/w | Yes | No | No |
182+
| &nbsp;&nbsp;&nbsp;`Android/media/<app-id>/` | removableExternalMediaDirectories | - | r/w | Yes | No | No |
167183

168184
\* The OS may periodically clear this directory, but do not rely on this behavior. Clear
169185
the contents of this directory as appropriate for your application. Should a user

src/android/FileUtils.java

+64-18
Original file line numberDiff line numberDiff line change
@@ -619,9 +619,21 @@ private boolean needPermission(String nativeURL, int permissionType) throws JSON
619619
if(j.has("externalApplicationStorageDirectory")) {
620620
allowedStorageDirectories.add(j.getString("externalApplicationStorageDirectory"));
621621
}
622-
ArrayList<String> allowedExtraPatternStorageDirectories = new ArrayList<String>();
623-
// basic pattern for usual application storage directory, to extend the allowed list to external SD cards for example
624-
allowedExtraPatternStorageDirectories.add("/Android/data/" + cordova.getActivity().getPackageName() + "/");
622+
if (j.has("removableExternalApplicationStorageDirectories")) {
623+
JSONArray array = j.getJSONArray("removableExternalApplicationStorageDirectories");
624+
for (int i = 0; i < array.length(); i++) {
625+
allowedStorageDirectories.add(array.getString(i));
626+
}
627+
}
628+
if (j.has("removableExternalMediaDirectories")) {
629+
JSONArray array = j.getJSONArray("removableExternalMediaDirectories");
630+
for (int i = 0; i < array.length(); i++) {
631+
allowedStorageDirectories.add(array.getString(i));
632+
}
633+
}
634+
if (j.has("externalMediaDirectory")) {
635+
allowedStorageDirectories.add(j.getString("externalMediaDirectory"));
636+
}
625637

626638
if(permissionType == READ && hasReadPermission()) {
627639
return false;
@@ -636,11 +648,6 @@ else if(permissionType == WRITE && hasWritePermission()) {
636648
return false;
637649
}
638650
}
639-
for (String extraPatternDirectory : allowedExtraPatternStorageDirectories) {
640-
if (nativeURL.contains(extraPatternDirectory)) {
641-
return false;
642-
}
643-
}
644651
return true;
645652
}
646653

@@ -1045,17 +1052,56 @@ private JSONObject requestAllPaths() throws JSONException {
10451052
ret.put("applicationStorageDirectory", toDirUrl(context.getFilesDir().getParentFile()));
10461053
ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
10471054
ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
1048-
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
1049-
try {
1050-
ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
1051-
ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
1052-
ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
1053-
ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
1054-
}
1055-
catch(NullPointerException e) {
1055+
try {
1056+
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
1057+
ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
1058+
ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
1059+
ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
1060+
ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
1061+
}
1062+
1063+
JSONArray removableExternalApplicationStorageDirs = new JSONArray();
1064+
JSONArray removableExternalDataDirs = new JSONArray();
1065+
JSONArray removableExternalCacheDirs = new JSONArray();
1066+
JSONArray removableExternalMediaDirs = new JSONArray();
1067+
String externalMediaDir = null;
1068+
for (File filesDir : context.getExternalFilesDirs(null)) {
1069+
if (filesDir != null) {
1070+
if (Environment.isExternalStorageRemovable(filesDir)) {
1071+
removableExternalApplicationStorageDirs.put(toDirUrl(filesDir.getParentFile()));
1072+
removableExternalDataDirs.put(toDirUrl(filesDir));
1073+
}
1074+
}
1075+
}
1076+
for (File cacheDir : context.getExternalCacheDirs()) {
1077+
if (cacheDir != null) {
1078+
if (Environment.isExternalStorageRemovable(cacheDir)) {
1079+
removableExternalCacheDirs.put(toDirUrl(cacheDir));
1080+
}
1081+
}
1082+
}
1083+
for (File mediaDir : context.getExternalMediaDirs()) {
1084+
if (mediaDir != null) {
1085+
String dirUrl = toDirUrl(mediaDir);
1086+
if (Environment.isExternalStorageRemovable(mediaDir)) {
1087+
removableExternalMediaDirs.put(dirUrl);
1088+
} else {
1089+
if (externalMediaDir != null) {
1090+
LOG.w(LOG_TAG, "External media directory already found ; skip other value " + dirUrl);
1091+
continue;
1092+
}
1093+
externalMediaDir = dirUrl;
1094+
}
1095+
}
1096+
}
1097+
ret.put("removableExternalApplicationStorageDirectories", removableExternalApplicationStorageDirs);
1098+
ret.put("removableExternalDataDirectories", removableExternalDataDirs);
1099+
ret.put("removableExternalCacheDirectories", removableExternalCacheDirs);
1100+
ret.put("removableExternalMediaDirectories", removableExternalMediaDirs);
1101+
ret.put("externalMediaDirectory", externalMediaDir);
1102+
} catch (NullPointerException e) {
10561103
/* If external storage is unavailable, context.getExternal* returns null */
1057-
LOG.d(LOG_TAG, "Unable to access these paths, most liklely due to USB storage");
1058-
}
1104+
LOG.d(LOG_TAG, "Unable to access these paths, most likely due to USB storage");
10591105
}
10601106
return ret;
10611107
}

0 commit comments

Comments
 (0)