media.save saying to add WRITE_EXTERNAL_STORAGE permission, when it already has been

 I’m trying to use media.save to save an image to the user’s camera roll. However I’m getting the following error message:

Corona: Developer Error Saving Images requires access to the device's storage! Ensure that your app is using the "android.permission.WRITE\_EXTERNAL\_STORAGE" permission.

I’m using Corona Enterprise, and definitely have the permission in my manifest:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" /\>

So why am I seeing this error?

I’ve also tried adding the READ_EXTERNAL_STORAGE permission, in case Corona tries to read the directory before attempting to save to it, but I still get the same error (according to Android’s docs the READ permission is implicitly granted when you use WRITE, but I thought I’d try it).  

I definitely already have the WRITE_EXTERNAL_STORAGE permission in the manifest (in fact someone from Google asked us to clarify why we needed it so I know for sure that it’s still in the final apk).

I have plenty of storage space available, 1.5GB on the device itself, and 18GB on an SD card - the file being saved is only 0.5MB. This is on a Galaxy S4 btw.

If I print out when the file has finished downloading, and then also before and after I attempt to use media.save, I see the following:

I/Corona(25610): Download complete, total bytes transferred: 576732 I/Corona(25610): call media.save W/ApplicationPackageManager(25610): getCSCPackageItemText() I/Corona(25610): ERROR: Saving Images requires access to the device's Storage! I/Corona(25610): Ensure that your app is using the "android.permission.WRITE\_EXTERNAL\_STORAGE" permission. I/Corona(25610): called media.save

Lines 1, 2 and 6 are lines that I print, and lines 3-5 are printed automatically when this error occurs. There is nothing else in the log between attempting to save, and the save failing. 

Does Ajay or anyone else have any idea what could be causing the problem? I’m now trying to write my own java function which will let me save a file from the app’s internal storage to the external storage, but would prefer to rely on a built in Corona function if I could.

I should’ve pointed out that this is happening on Android 4.4.2, so the new “runtime permission” stuff shouldn’t be applicable.  

However, I’ve noticed something strange. I built an app using Corona SDK and media.save worked just fine. When I went to install that app the install screen said it would get access to:

Privacy: modify or delete the contents of your SD card read the contents of your SD card

and has a USB symbol next to it.

In my app built with Enterprise, I see the following instead:

Privacy: read phone status and identity approximate location (network-based) find accounts on the device

but not the read/write permissions.

I’ve used apk tool to open up the final apk so I could see if the permissions had been removed from the manifest, and they are still there.

I have no idea why those permissions seem to be getting ignored on install.

So after some time I finally solved the problem while trying to make a stripped down project to submit as a bug report…

The cause was that external libraries in the project had their own manifest files, and were overwriting this line in my manifest:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" /\>

with this from their manifests:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" android:maxSdkVersion="18"/\>

The solution was to add this line:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" android:maxSdkVersion="23" tools:replace="android:maxSdkVersion" /\>

I haven’t tested on devices running 6.0+ to see how this line affects them, but it has fixed the issue on < 6.0

For future reference, I found it by looking at this file:

MyProject/Android/android/app/build/outputs/logs/manifest-merger-release-report.txt

Which will show something along these lines:

MERGED from com.company.theirLibrary:1.0.1 android:maxSdkVersion ADDED from AndroidManifest.xml:21:76

where com.company.theirLibrary will show the name of the library causing the issue.

I think that anyone using the old Ant methods probably wouldn’t run into this because you have to set everything in the manifest manually. As I’m using Android Studio and pulling the libraries in using Gradle, those manifest entries were kind of “hidden” until I went searching for the cause of the issue. 

I’ve also tried adding the READ_EXTERNAL_STORAGE permission, in case Corona tries to read the directory before attempting to save to it, but I still get the same error (according to Android’s docs the READ permission is implicitly granted when you use WRITE, but I thought I’d try it).  

I definitely already have the WRITE_EXTERNAL_STORAGE permission in the manifest (in fact someone from Google asked us to clarify why we needed it so I know for sure that it’s still in the final apk).

I have plenty of storage space available, 1.5GB on the device itself, and 18GB on an SD card - the file being saved is only 0.5MB. This is on a Galaxy S4 btw.

If I print out when the file has finished downloading, and then also before and after I attempt to use media.save, I see the following:

I/Corona(25610): Download complete, total bytes transferred: 576732 I/Corona(25610): call media.save W/ApplicationPackageManager(25610): getCSCPackageItemText() I/Corona(25610): ERROR: Saving Images requires access to the device's Storage! I/Corona(25610): Ensure that your app is using the "android.permission.WRITE\_EXTERNAL\_STORAGE" permission. I/Corona(25610): called media.save

Lines 1, 2 and 6 are lines that I print, and lines 3-5 are printed automatically when this error occurs. There is nothing else in the log between attempting to save, and the save failing. 

Does Ajay or anyone else have any idea what could be causing the problem? I’m now trying to write my own java function which will let me save a file from the app’s internal storage to the external storage, but would prefer to rely on a built in Corona function if I could.

I should’ve pointed out that this is happening on Android 4.4.2, so the new “runtime permission” stuff shouldn’t be applicable.  

However, I’ve noticed something strange. I built an app using Corona SDK and media.save worked just fine. When I went to install that app the install screen said it would get access to:

Privacy: modify or delete the contents of your SD card read the contents of your SD card

and has a USB symbol next to it.

In my app built with Enterprise, I see the following instead:

Privacy: read phone status and identity approximate location (network-based) find accounts on the device

but not the read/write permissions.

I’ve used apk tool to open up the final apk so I could see if the permissions had been removed from the manifest, and they are still there.

I have no idea why those permissions seem to be getting ignored on install.

So after some time I finally solved the problem while trying to make a stripped down project to submit as a bug report…

The cause was that external libraries in the project had their own manifest files, and were overwriting this line in my manifest:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" /\>

with this from their manifests:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" android:maxSdkVersion="18"/\>

The solution was to add this line:

\<uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" android:maxSdkVersion="23" tools:replace="android:maxSdkVersion" /\>

I haven’t tested on devices running 6.0+ to see how this line affects them, but it has fixed the issue on < 6.0

For future reference, I found it by looking at this file:

MyProject/Android/android/app/build/outputs/logs/manifest-merger-release-report.txt

Which will show something along these lines:

MERGED from com.company.theirLibrary:1.0.1 android:maxSdkVersion ADDED from AndroidManifest.xml:21:76

where com.company.theirLibrary will show the name of the library causing the issue.

I think that anyone using the old Ant methods probably wouldn’t run into this because you have to set everything in the manifest manually. As I’m using Android Studio and pulling the libraries in using Gradle, those manifest entries were kind of “hidden” until I went searching for the cause of the issue.