-
Notifications
You must be signed in to change notification settings - Fork 760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Storage updates in Android 11 #426
Comments
Seems like the fix that was merge #417 in order to solve #408 will no longer work for android 11 (API level 30). |
Yes, you're correct. In API 29, there is a new file system policy. #417 utilised an available flag to request the old file system system, but API 30 will ignore that flag, forcing app developers to implement the new policy model. To learn about the new android model, you should probably read up on Scoped Storage. I briefly read up on this last weekend and it appears that some apps may require to migrate their data locations depending on where they store data. Scoped storage means just that, you're access to the filesystem is limited to a certain scope. Parts of the file system that you might have had access before may be impossible to access in API 30. This means app developers should take this time to determine if they need to migrate data. Read the android notice for more information on migration. Given the usual pattern, users have probably until August 2021 before Google force API 30 for new apps, and November 2021 before users are forced to use API 30 on existing apps. The new MANAGE_EXTERNAL_STORAGE permission I believe will essentially make the app behave pre API 29 without the legacy storage flag, but will likely be highly scrutinised by Google if the app uses it without a justified reason. This could be an opt in feature by documenting how one can add this permission using config-file or edit-config. The users must be targeting API 30 in order to use this permission, it isn't available in API 29. Lastly, getting familiar with the MediaStore APIs sounds like is quite important, because apps can access some external filesystem storages, for accessing pictures, videos, and other media-related resources. What needs to be changed exactly in the Apache codebase I'm not so certain myself, I'm not that familiar with the code base. |
Adding ' android:requestLegacyExternalStorage="true"' to AndroidManifest.xml solves the problem. Read more at https://developer.android.com/training/data-storage/use-cases. |
@olsbg this won't work for android 11, it does and will work for android 10. |
Can you share how you achieved this? |
Instead of saving files to the file system I use the social sharing plugin. This way a user is prompted with options on what he wants to do with the file I just created in memory: |
Thanks, @HarelM , |
@Vatsov Are you reading a file a user selects? If so I don't think there's an issue that is related to Android 11, or at least I hope not as you open the file picker and this should be OK even in Android 11 as far as I know. |
@HarelM Yes, I’m trying to read the file which the user selects with So I decided firstly to copy the file to |
FYI window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory + "/Download" used to work but now fails with Code 1 on Android 10 both without specifying android:requestLegacyExternalStorage="true" and with. I can't test on Android 11. It would be really useful to know if there's a plan for the maintainers to create a new release which makes the plugin work with Android 10 and 11 without the need to manually tweak files like the manifest. Hope there is. This is a really useful plugin. Thanks |
What should work
It's important to read the Android Notes before you target API 30. You may need to migrate your files to another folder to maintain access to them when targeting API 30 using the new APIs. Who this will affectThis will affect any app that reads or writes to the external file system (aka the I'll be adding a help wanted label. We don't have a planned solution yet. If a volunteer would take the lead and finding a solution to prepare a PR, I encourage to use our Dev Mailing List so that we can discuss requirements and potential solutions. Useful Links: https://developer.android.com/about/versions/11/privacy/storage |
@breautek Thanks for the quick response and useful summary. I'll have to think about this :-) |
I've recently implanted a small android app which had to save images to a folder/media storage so I might publish my conclusions here once I'm done... |
Did you mean running |
Yes, but you still need to use build tools version 29, otherwise the build will fail to recognize |
Great, thanks, indeed I made
I tested it now and it allows me to use
Did you mean this in
Thanks in advance |
"Build Tools" is part of the Android SDK, you can download it using the Android Studio's SDK Manager tool. |
@breautek thanks. I also used your answer, citing the source, to reply on stackoverflow the open issue. |
Adding android:requestLegacyExternalStorage="true" is throwing AAPT: error: attribute android:requestLegacyExternalStorage not found. Because cordova 9.x.x is building with SDK-28 even i mention targetSdkVersion as 29. Is there any workaround for that? |
You need to be using build tools 29. https://cordova.apache.org/docs/en/dev/guide/platforms/android/index.html#adding-sdk-packages |
Seems like opening a file in android 11 doesn't work. It does work in android 10. I'm not using any code but simply input with type=file to pick a file. |
@HarelM do you have any updates on this issue? |
Not yet, but we are talking about two different issues:
To summarize my experience:
Also I've just seen recently that starting from August/November this year Google is changing the policy to target API level 30 for all new/updated applications so this has to be solved soon from my point of view... |
Thank you @HarelM , regarding point 1. could you kindly tell me exactly which social sharing plugin do you use? |
|
With Android 10 save to persistant has worked but i get this error:
Not allowed sounds for me like a permission problem. Has someone else the same problem? How can i fix this? |
If I add cordova-android 10.1.0 then only it shows Android target: android-30 while ionic cordova platform add android. PS D:\Project> ionic cordova platform add android@10.1.0
|
cant acess the file :/ in sdk 30 |
@chrisjdev Thank you. This is a great workaround for the time being. |
i still cant acess my file , im using 👍 but the the file path isent acessible , i get no acessible path only console log "sucess:" |
After making the change to the FilePath.java in plugins folder, have you tried removing and adding the Android platform? |
i did, but i just realise that if i run window.open on my path : "file:///data/user/0/events.staff.booking.app/cache/FB_IMG_1637505177709.jpg" .. the image opens ... i just cant get it to upload to my server dont know why i get upload code:1 ... using file-tranfere plugin ... |
Addressing a few comments over the past few days:
You're only getting Instead of doing:
The root
Starting with cordova-android@10, cordova-android uses WebViewAssetLoader by default and disables local file system access as recommended by the android docs. This is because this option is deemed insecure, but was a critical component that Cordova that depended on with on other alternative until Android introduced the WebViewAssetLoader. Using the WebViewAssetLoader also overcomes some other same-origin issues as requests appear to come from a true origin rather than the filesystem which has a This also means you can't use use file system urls directly like before. I think I might have to make a blog post about this but you can still read the file (assuming you have access to that file) as a blob and use Object URLs. Alternatively, if you want the previous cordova-android behaviour, you can enable the This is not related to the cordova-plugin-file, so I would respectfully ask to refrain from posting more on this. If you have further questions on this, you can reach reach out to our Slack community. (Link is a temporary link since the main link is down at the time of writing...)
Note that adding the MANAGE_EXTERNAL_STORAGE permission may work for you but it also may limit your ability to deploy to the Google Play store. This permission will require justification and Google reserves the right to block your app from the play store if they feel like your app don't need this permission. |
@breautek I have added AndroidInsecureFileModeEnabled preference in config.xml but it is not working for me. |
Thank you for the explanation @breautek. My issue was that I wasn't using WebViewAssetLoader. Simply replacing @brunoalex are you able to access |
#please let me know I'm also facing same issue for android 11 device (Cordova android@10 ). window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, function(dir) { |
@alex-steinberg i can acess the file, but the funtions i used to upload the file after selecting from the galery to the server arent working in sdk30.. "ft.upload(imageURI, server, function(r)" ... |
I have a similar problem.. my app downloads and unzips images in ///storage/emulated/0/Android/data/myappid/files/ but the app cannot access the images by javascript or by code ex. looks very confused |
@alex-steinberg - We have set targetSdkVersion to 30 in config.xml file and created build using platform 9.1.0. Below code works fine in lower android version (till android 10). In android 11 while reading a pdf file from download loaction, we get error as GET file:///storage/emulated/0/Download/Test.pdf net::ERR_ACCESS_DENIED this.fileChooser.open() base64EncodeFile(src){ We have also tried below code To copy from download folder to internal storage. It gives {"code":1,"message":"NOT_FOUND_ERR"} error pathsrc : file:///storage/emulated/0/Download/Test.pdf fileName : Test.pdf this.file.copyFile(pathsrc, fileName, this.file.dataDirectory, fileName). Below code is using copyTo method, it gives error as FileError {code: 1} window.resolveLocalFileSystemURL(pathsrc, function (fileSystem) { |
I am trying to write file using following code: this.file.checkDir(this.directorypath, 'AppFolder').then((dirExists) => {
this.file.writeFile(this.downloadDirectory, update_file + '.'+saveExtention, fileData, { replace: true }).then((fileEntry) => {
let mimeTestType = mimeType;
let path = fileEntry.nativeURL
this.openingFile(path, mimeTestType)
resolve(true)
}).catch((ex) => {
resolve(true)
console.error('Error')
})
}, (response) => {
this.file.createDir(this.directorypath, 'AppFolder', true).then((response) => {
this.file.writeFile(this.downloadDirectory, update_file + '.'+saveExtention, fileData, { replace: true }).then((fileEntry) => {
let mimeTestType = mimeType;
let path = fileEntry.nativeURL
this.openingFile(path, mimeTestType)
resolve(true)
}).catch((ex) => {
resolve(true)
console.error('Error')
})
})
})
}); This works till android 10 but not in android 11, it throws error. |
This simple example app should shed some light on some of the issues raised here. At the very least, it would make a good place to continue the conversation around using files on Android 11 Cordova apps since, as has been mentioned, the problems experienced here aren't caused by the |
With config.xml <widget ..... xmlns:android="http://schemas.android.com/apk/res/android">
...
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
<application android:usesCleartextTraffic="true" android:requestLegacyExternalStorage="true"/>
</edit-config>
...
Without |
Add code below to AndroidManifest.xml, and you can write file to storage root directory like cordova.file.externalRootDirectory: <manifest xmlns:tools="http://schemas.android.com/tools">
...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
<application android:requestLegacyExternalStorage="true">
...
</manifest> You can use this method: var folderpath = cordova.file.externalRootDirectory + "Download";
window.resolveLocalFileSystemURL(folderpath, function (dir) {
dir.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
fileEntry.createWriter(function (writer) {
writer.onwrite = function (writing) {
console.log("WRITING...");
};
writer.write(fileData);
console.log("SUCCESS");
}, function () {
console.log("FAIL");
});
});
}); Tested on Android 11 |
This isn't standard behaviour or it works because the build isn't targeting API 30 or later as the Android docs explicitly states WRITE_EXTERNAL_STORAGE when targeting API 30 / Android 11 or later. Additionally when targeting API 30, scoped storage is enforced and requestLegacyExternalStorage is ignored. |
This is becoming a bit messy :) From updating from SDK v30 upwards the APP breaks exactly by merely reading the file system (cordova
$.getJSON(cordova.file.applicationDirectory + 'www/json/anomalies.json', function (data) {
console.log(data)
}) 1 - @breautek just confirm me please, if I remember correctly the issue regarding the transition from SDK 29 upwards was merely related with writing content to the device file system, right? 2 - @alex-steinberg mentions replacing My package.json: {
"name": "in-my-district",
"displayName": "In my District!",
"version": "1.2.25",
"description": "Report to your municipality certain irregularities in your neighborhood or district",
"homepage": "https://nomeubairro.app/",
"android-version-code": 10225,
"scripts": {
"test": "standard && node test/convertHbsToHtml.js && html-validate test/www/index.html && printf '\\n\\nTest OK\\n\\n'",
"version": "cordova-set-version --version ${npm_package_version} && git add config.xml && node scripts/setAndroidVersionCode.js -v ${npm_package_version} && git add package.json",
"push-version": "git push && git push origin v${npm_package_version}",
"build-release-apk": "npm test && scripts/buildReleaseAPK.sh",
"build-release-aab": "npm test && scripts/buildReleaseAAB.sh",
"run-release-on-device": "scripts/runReleaseOnDevice.sh",
"run-debug-on-device": "adb get-state 1>/dev/null 2>&1 && echo 'DEVICE ATTACHED' || { echo 'No device attached'; exit 1; } && cordova run android --device --debug",
"regenerate-png-files": "./res/icon/generateIcons.sh && ./res/screen/generateScreens.sh && cp res/icon/android/512.png www/img/logo.png && cp res/icon/android/512.png ../fastlane/metadata/android/en-US/images/icon.png && git add res/* www/img/logo.png ../fastlane/metadata/android/en-US/images/icon.png && git commit -m 'PNGs regenerated'"
},
"repository": {
"type": "git",
"url": "git://github.com/jfoclpf/in-my-district.git"
},
"author": "João Pimentel Ferreira",
"license": "GPL-3.0",
"dependencies": {
"@fortawesome/fontawesome-free": "6.2.1",
"async": "^3.2.4",
"bootstrap": "^5.2.3",
"cordova": "^11.1.0",
"cordova-browser": "^6.0.0",
"cordova-import-npm": "^1.0.35",
"cordova-pdf-generator": "^2.1.1",
"cordova-plugin-cache-clear": "^1.3.8",
"cordova-plugin-device": "^2.1.0",
"cordova-plugin-geolocation": "^4.1.0",
"cordova-plugin-inappbrowser": "^5.0.0",
"cordova-plugin-is-debug": "^1.0.0",
"cordova-plugin-screen-orientation": "^3.0.2",
"cordova-plugin-simple-image-resizer": "0.2.0",
"cordova-plugin-splashscreen": "^6.0.2",
"cordova-plugin-statusbar": "^3.0.0",
"cordova-plugin-whitelist": "^1.3.4",
"cordova-set-version": "^13.0.1",
"crypto-js": "^4.1.1",
"es6-promise-plugin": "^4.2.2",
"exif-js": "^2.3.0",
"express-handlebars": "^6.0.6",
"fs": "0.0.1-security",
"jAlert": "^4.9.1",
"jquery": "^3.6.3",
"leaflet": "^1.9.3",
"leaflet-image": "^0.4.0",
"leaflet.markercluster": "^1.5.3",
"path": "^0.12.7",
"whitelist": "^1.0.2"
},
"cordova": {
"plugins": {
"cordova-plugin-geolocation": {
"GPS_REQUIRED": "true"
},
"cordova-plugin-email-composer": {
"ANDROID_SUPPORT_V4_VERSION": "27.+"
},
"cordova-plugin-statusbar": {},
"cordova-plugin-screen-orientation": {},
"cordova-plugin-device": {},
"cordova-plugin-whitelist": {},
"cordova-pdf-generator": {},
"cordova-plugin-splashscreen": {},
"cordova-plugin-inappbrowser": {},
"cordova-plugin-is-debug": {},
"cordova-plugin-androidx-adapter": {},
"cordova-plugin-file": {
"ANDROIDX_WEBKIT_VERSION": "1.4.0"
},
"cordova-plugin-camera": {
"ANDROID_SUPPORT_V4_VERSION": "27.+",
"ANDROIDX_CORE_VERSION": "1.6.+"
},
"cordova-plugin-network-information": {},
"cordova-plugin-app-version": {},
"@globules-io/cordova-plugin-ios-xhr": {},
"cordova-plugin-simple-image-resizer": {
"ANDROID_EXIFINTERFACES_VERSION": "27.+"
}
},
"platforms": [
"ios",
"android"
]
},
"devDependencies": {
"@globules-io/cordova-plugin-ios-xhr": "github:globules-io/cordova-plugin-ios-xhr",
"command-line-args": "^5.2.1",
"cordova-android": "^10.1.2",
"cordova-plugin-androidx-adapter": "^1.1.3",
"cordova-plugin-app-version": "^0.1.14",
"cordova-plugin-camera": "^6.0.0",
"cordova-plugin-email-composer": "github:jfoclpf/cordova-plugin-email-composer#pr-Fix_361-Android_11_support",
"cordova-plugin-file": "^7.0.0",
"cordova-plugin-network-information": "^3.0.0",
"fs-extra": "^11.1.0",
"handlebars": "^4.7.7",
"html-minifier": "^4.0.0",
"html-validate": "^7.13.1",
"npm-check-updates": "^16.6.2",
"semver": "^7.3.8",
"standard": "^17.0.0",
"uglify-js": "^3.17.4",
"uglifycss": "0.0.29",
"walk": "^2.3.15",
"xml2js": "^0.4.23"
},
"standard": {
"ignore": [
"www/js/res/*",
"test/www/*",
"platforms/",
"plugins/"
]
}
} config.xml: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.in.my.district" version="1.2.25" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>No meu Bairro!</name>
<description>
Comunique ao seu município anomalias no seu bairro, como buracos na calçada ou lixo por recolher
</description>
<author email="joao.pimentel.ferreira@gmail.com" href="https://www.joaopimentel.com/">
João Pimentel Ferreira
</author>
<content src="index.html"/>
<icon height="512" src="res/icon/universal/512.png" width="512"/>
<icon density="xhdpi" height="196" src="res/icon/universal/196.png" width="196"/>
<icon density="xxxhdpi" height="192" src="res/icon/universal/192.png" width="192"/>
<icon density="xxhdpi" height="144" src="res/icon/universal/144.png" width="144"/>
<icon density="hdpi" height="72" src="res/icon/universal/72.png" width="72"/>
<icon density="mdpi" height="48" src="res/icon/universal/48.png" width="48"/>
<access origin="*"/>
<allow-navigation href="*"/>
<allow-intent href="http://*/*"/>
<allow-intent href="https://*/*"/>
<preference name="OverrideUserAgent" value="APP/com.in.my.district"/>
<preference name="windows-target-version" value="10.0"/>
<preference name="windows-phone-target-version" value="10.0"/>
<preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle"/>
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets"/>
<preference name="StatusBarOverlaysWebView" value="false"/>
<preference name="StatusBarBackgroundColor" value="#FFFFFF"/>
<preference name="StatusBarStyle" value="blacktranslucent"/>
<preference name="AndroidXEnabled" value="true"/>
<hook src="hooks/generateJsFiles.js" type="before_prepare"/>
<hook src="hooks/convertHbsToHtml.js" type="after_prepare"/>
<hook src="hooks/minifyFiles.js" type="after_prepare"/>
<hook src="node_modules/cordova-import-npm/scripts/importNpmPackages.js" type="before_prepare"/>
<platform name="android">
<preference name="android-minSdkVersion" value="31"/>
<preference name="android-targetSdkVersion" value="33"/>
<preference name="AndroidPersistentFileLocation" value="Compatibility"/>
<allow-intent href="market:*"/>
<icon height="512" src="res/icon/android/512.png" width="512"/>
<icon density="xhdpi" height="192" src="res/icon/android/192.png" width="192"/>
<icon density="xxxhdpi" height="192" src="res/icon/android/192.png" width="192"/>
<icon density="xxhdpi" height="144" src="res/icon/android/144.png" width="144"/>
<icon density="hdpi" height="72" src="res/icon/android/72.png" width="72"/>
<icon density="mdpi" height="48" src="res/icon/android/48.png" width="48"/>
<splash density="hdpi" src="res/screen/android/screen-hdpi-portrait.png"/>
<splash density="port-hdpi" src="res/screen/android/screen-hdpi-portrait.png"/>
<splash density="ldpi" src="res/screen/android/screen-ldpi-portrait.png"/>
<splash density="port-ldpi" src="res/screen/android/screen-ldpi-portrait.png"/>
<splash density="mdpi" src="res/screen/android/screen-mdpi-portrait.png"/>
<splash density="port-mdpi" src="res/screen/android/screen-mdpi-portrait.png"/>
<splash density="xhdpi" src="res/screen/android/screen-xhdpi-portrait.png"/>
<splash density="port-xhdpi" src="res/screen/android/screen-xhdpi-portrait.png"/>
</platform>
<platform name="ios">
<allow-intent href="itms:*"/>
<allow-intent href="itms-apps:*"/>
<icon src="res/icon/ios/16.png" width="16" height="16"/>
<icon src="res/icon/ios/20.png" width="20" height="20"/>
<icon src="res/icon/ios/29.png" width="29" height="29"/>
<icon src="res/icon/ios/32.png" width="32" height="32"/>
<icon src="res/icon/ios/40.png" width="40" height="40"/>
<icon src="res/icon/ios/48.png" width="48" height="48"/>
<icon src="res/icon/ios/50.png" width="50" height="50"/>
<icon src="res/icon/ios/55.png" width="55" height="55"/>
<icon src="res/icon/ios/57.png" width="57" height="57"/>
<icon src="res/icon/ios/58.png" width="58" height="58"/>
<icon src="res/icon/ios/60.png" width="60" height="60"/>
<icon src="res/icon/ios/64.png" width="64" height="64"/>
<icon src="res/icon/ios/72.png" width="72" height="72"/>
<icon src="res/icon/ios/76.png" width="76" height="76"/>
<icon src="res/icon/ios/80.png" width="80" height="80"/>
<icon src="res/icon/ios/87.png" width="87" height="87"/>
<icon src="res/icon/ios/88.png" width="88" height="88"/>
<icon src="res/icon/ios/100.png" width="100" height="100"/>
<icon src="res/icon/ios/114.png" width="114" height="114"/>
<icon src="res/icon/ios/120.png" width="120" height="120"/>
<icon src="res/icon/ios/128.png" width="128" height="128"/>
<icon src="res/icon/ios/144.png" width="144" height="144"/>
<icon src="res/icon/ios/152.png" width="152" height="152"/>
<icon src="res/icon/ios/167.png" width="167" height="167"/>
<icon src="res/icon/ios/172.png" width="172" height="172"/>
<icon src="res/icon/ios/180.png" width="180" height="180"/>
<icon src="res/icon/ios/196.png" width="196" height="196"/>
<icon src="res/icon/ios/216.png" width="216" height="216"/>
<icon src="res/icon/ios/256.png" width="256" height="256"/>
<icon src="res/icon/ios/512.png" width="512" height="512"/>
<icon src="res/icon/ios/1024.png" width="1024" height="1024"/>
<preference name="iosPersistentFileLocation" value="Library"/>
<preference name="NativeXHRLogging" value="full"/>
<preference name="AllowUntrustedCerts" value="true"/>
<preference name="InterceptRemoteRequests" value="all"/>
<preference name="CustomUserAgent" value="APP/com.in.my.district"/>
<preference name="allowFileAccessFromFileURLs" value="true"/>
<preference name="allowUniversalAccessFromFileURLs" value="true"/>
<edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da sua localização para indicar o endereço da ocorrência a ser enviada ao seu município</string>
</edit-config>
<edit-config target="NSLocationAlwaysAndWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da sua localização para indicar o endereço da ocorrência a ser enviada ao seu município</string>
</edit-config>
<edit-config target="NSLocationAlwaysUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da sua localização para indicar o endereço da ocorrência a ser enviada ao seu município</string>
</edit-config>
<edit-config target="NSLocationAlwaysAndWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da sua localização para indicar o endereço da ocorrência a ser enviada ao seu município</string>
</edit-config>
<edit-config target="NSCameraUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da acesso à câmera para tirar fotos às anomalias</string>
</edit-config>
<edit-config target="NSPhotoLibraryUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da acesso à galeria, caso você já tenha tirado anteriormente a foto à ocorrência</string>
</edit-config>
<edit-config target="NSPhotoLibraryAddUsageDescription" file="*-Info.plist" mode="merge">
<string>Necessita da acesso à galeria para guardar algumas fotos, mesmo que temporariamente</string>
</edit-config>
<edit-config target="UIFileSharingEnabled" file="*-Info.plist" mode="merge">
<true/>
</edit-config>
<edit-config target="LSSupportsOpeningDocumentsInPlace" file="*-Info.plist" mode="merge">
<true/>
</edit-config>
<edit-config target="UISupportsDocumentBrowser" file="*-Info.plist" mode="merge">
<true/>
</edit-config>
</platform>
</widget> |
@jfoclpf You're using a jquery API that presumably uses an XHR request to fetch data from a The webview doesn't have direct access to While the browser itself doesn't have direct access to the FS, native plugins still does, so if you used the actual cordova plugin API,
Here's an untested example (may have syntax errors or a function name might be wrong, going off memory...) resolveLocalFilesystemURL(cordova.file.applicationDirectory + 'www/json/anomalies.json', (fileEntry) => {
fileEntry.file((file) => {
let reader = new FileReader();
reader.onloadend = () => {
console.log('JSON String', reader.result);
};
reader.readAsText(file);
});
}, (error) => {
console.error('resolve error', error);
}); If you're using the WebViewAssetLoader, the latest version of this plugin as a |
Came to this issue repeatedly when searching for a way to fix opening files on Android that broke since skd 29. export async function openFile(remoteUrl: string, fileName: string, mimeType: string) {
if (!isCordova(window)) {
window.open(remoteUrl, '_blank');
return;
}
const transfer = FileTransfer.create();
const extension = mime.extension(mimeType);
const devicePath = `${File.dataDirectory}${fileName}.${extension}`;
await transfer.download(remoteUrl, devicePath);
const fileEntry = await File.resolveLocalFilesystemUrl(devicePath);
await FileOpener.open(fileEntry.nativeURL, mimeType);
} |
Feature Request
Support the android 11 new file system based policy.
Motivation Behind Feature
Support the changes that are planned for android 11 (API level 30)
Feature Description
I'm not sure how to fully describe this, but basically support what's documented here:
https://developer.android.com/about/versions/11/privacy/storage
Alternatives or Workarounds
Not targeting API level 30 until this is supported?
The text was updated successfully, but these errors were encountered: