Android 6 permissions and expansion files

We’ve just launched our app and are getting crash reports back from some Android 6 devices related to being unable to load from the expansion file. The file in question is a binary data file that is loaded via io.open(). Since the app is crashing at that point, I am unsure whether other files (such as images or audio) would succeed.

I noticed in the blog post from March 16, that it mentioned the following:

Apps using expansion files should have STORAGE permissions granted before launching.

How do we force the game to have these permissions before launching on Android 6? Prompting the user immediately upon startup for the permission does not seem to allow us to load after they have granted it.

EDIT: We’ve managed to verify that this is happening for all file types. Moving the binary files loaded by io.open() back into the apk makes it fail on the first image sheet that is loaded from the expansion file.

You need to use build #2830 or higher.

In that version, your app’s “main.lua” file will not get loaded until Corona confirms that both the read and write external storage permissions have been granted.  This check happens every time the user starts up the app to verify access to the downloaded expansion file.  If not granted, then the user will be stuck in the expansion file download screen.  Every time they launch the app, this screen will ask the user to grant it read/write permission.

You can verify this behavior yourself.  Install your app and its expansion file.  Then deny it read/write external storage permission under Android’s “Settings” screen.  Finally, launch your app and you can see the above permission request happening before your “main.lua” gets loaded.

We’re currently using build #2871 and the API level is set to 23 in our android manifest.

We do not see the permissions check appear on any Android 6 devices unless we explicitly open it in our code via native.showPopup(“requestAppPermission”, opts). We also never see the expansion file download screen.

This doesn’t seem to matter on some devices (Nexus 6P, Samsung S6). These allow the game to read from the expansion files without permissions. We’ve verified this by checking the settings for app and it shows “No permissions granted” even though it allows us to load the files when the app is run.

Other devices (such as LG G3, OnePlus One, HTC One) are blocking access to the files and these are the ones we are seeing crashes on.

Are you doing a Corona Enterprise build?

Yes, this is Enterprise.

You need to add the following entries to your “AndroidManifest.xml” file…

\<manifest\> \<application\> \<meta-data android:name="targetedAppStore" android:value="google"/\> \<meta-data android:name="usesExpansionFile" android:value="true"/\> \</application\> \</manifest\>

The above meta-data entries tells Corona that your app uses Google Play expansion files and that it should do the following on startup:

  • Check if the expansion file is already downloaded.
  • If not downloaded, then Corona will automatically download it via Google licensing.
  • It was also check if your app was granted permission.

If you don’t have the above set in your manifest, then I suspect this crashing issue will happen on older Android OS versions as well.  This is because Google Play will not always automatically download expansion files for you… and this appears to be a device specific limitation.  Perhaps only with forked Android OS versions.  Anyways, Google threatens that the expansion file will not always be downloaded automatically in the following link (2nd paragraph, last sentence).

   https://developer.android.com/google/play/expansion-files.html#DownloaderService

So, Corona will download it for you if you set the above meta-data tags.  But you also need to make sure that Corona’s Google licensing plugin is included in your Android build, because expansion files are downloaded via Google’s licensing feature.  As of daily build #2871, our Corona Google Licensing plugin is always automatically included in an Enterprise build.  But you will still need to add the equivalent licensing permissions to your manifest as documented here…

   https://docs.coronalabs.com/daily/guide/distribution/buildSettings/index.html#expansion-files

Thanks Joshua, that fixed the issue; we were missing the “targetedAppStore” entry in the manifest.

Is there documentation about expected AndroidManifest entries somewhere so we can check if we are missing any others if we run into similar problems in the future?

Great!  Glad it’s working for you.

And for your info, the Lua system.getInfo(“targetAppStore”) function returns whatever value string you set to that “targetedAppStore” meta-data tag.  You don’t have to limit it to what Corona documents it to be.  It just happens to be that the “google” store string is specially handled to enable Google Play specific features such as expansion files.

>> Is there documentation about expected AndroidManifest entries somewhere so we can check if we are missing any others if we run into similar problems in the future?

We mostly prefer to document these in our Enterprise sample/template projects’ “AndroidManifest.xml” files via XML comments.  But that said, we don’t document these in our current “AndroidManifest.xml” files and we really should.  I’ll add that to our to-do list.

The one other thing you should be aware of is custom notification icons.  You need to set these up differently in enterprise by adding them yourself to your project’s “res” directory.

   https://docs.coronalabs.com/daily/guide/events/appNotification/index.html#android-icons-1

You need to use build #2830 or higher.

In that version, your app’s “main.lua” file will not get loaded until Corona confirms that both the read and write external storage permissions have been granted.  This check happens every time the user starts up the app to verify access to the downloaded expansion file.  If not granted, then the user will be stuck in the expansion file download screen.  Every time they launch the app, this screen will ask the user to grant it read/write permission.

You can verify this behavior yourself.  Install your app and its expansion file.  Then deny it read/write external storage permission under Android’s “Settings” screen.  Finally, launch your app and you can see the above permission request happening before your “main.lua” gets loaded.

We’re currently using build #2871 and the API level is set to 23 in our android manifest.

We do not see the permissions check appear on any Android 6 devices unless we explicitly open it in our code via native.showPopup(“requestAppPermission”, opts). We also never see the expansion file download screen.

This doesn’t seem to matter on some devices (Nexus 6P, Samsung S6). These allow the game to read from the expansion files without permissions. We’ve verified this by checking the settings for app and it shows “No permissions granted” even though it allows us to load the files when the app is run.

Other devices (such as LG G3, OnePlus One, HTC One) are blocking access to the files and these are the ones we are seeing crashes on.

Are you doing a Corona Enterprise build?

Yes, this is Enterprise.

You need to add the following entries to your “AndroidManifest.xml” file…

\<manifest\> \<application\> \<meta-data android:name="targetedAppStore" android:value="google"/\> \<meta-data android:name="usesExpansionFile" android:value="true"/\> \</application\> \</manifest\>

The above meta-data entries tells Corona that your app uses Google Play expansion files and that it should do the following on startup:

  • Check if the expansion file is already downloaded.
  • If not downloaded, then Corona will automatically download it via Google licensing.
  • It was also check if your app was granted permission.

If you don’t have the above set in your manifest, then I suspect this crashing issue will happen on older Android OS versions as well.  This is because Google Play will not always automatically download expansion files for you… and this appears to be a device specific limitation.  Perhaps only with forked Android OS versions.  Anyways, Google threatens that the expansion file will not always be downloaded automatically in the following link (2nd paragraph, last sentence).

   https://developer.android.com/google/play/expansion-files.html#DownloaderService

So, Corona will download it for you if you set the above meta-data tags.  But you also need to make sure that Corona’s Google licensing plugin is included in your Android build, because expansion files are downloaded via Google’s licensing feature.  As of daily build #2871, our Corona Google Licensing plugin is always automatically included in an Enterprise build.  But you will still need to add the equivalent licensing permissions to your manifest as documented here…

   https://docs.coronalabs.com/daily/guide/distribution/buildSettings/index.html#expansion-files

Thanks Joshua, that fixed the issue; we were missing the “targetedAppStore” entry in the manifest.

Is there documentation about expected AndroidManifest entries somewhere so we can check if we are missing any others if we run into similar problems in the future?

Great!  Glad it’s working for you.

And for your info, the Lua system.getInfo(“targetAppStore”) function returns whatever value string you set to that “targetedAppStore” meta-data tag.  You don’t have to limit it to what Corona documents it to be.  It just happens to be that the “google” store string is specially handled to enable Google Play specific features such as expansion files.

>> Is there documentation about expected AndroidManifest entries somewhere so we can check if we are missing any others if we run into similar problems in the future?

We mostly prefer to document these in our Enterprise sample/template projects’ “AndroidManifest.xml” files via XML comments.  But that said, we don’t document these in our current “AndroidManifest.xml” files and we really should.  I’ll add that to our to-do list.

The one other thing you should be aware of is custom notification icons.  You need to set these up differently in enterprise by adding them yourself to your project’s “res” directory.

   https://docs.coronalabs.com/daily/guide/events/appNotification/index.html#android-icons-1