Search Unity

Avoid Requiring Permissions for OBB Usage

Discussion in 'Android' started by MatthewHarmon, Mar 5, 2018.

  1. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    We use the GooglePlayDownloader plugin to download our OBB in the rare case that Google Play did not successfully push it to the device.

    Unfortunately, this requires the read/write permissions to be set, and we are concerned that the associated permissions dialog may turn off some users. (The wording is a bit "scary.") For a Free-to-play game, every "neck" in the retention funnel needs to be addressed!

    So, is there any known way to add the "just in case" OBB downloader code without requiring the permissions? Clearly, Google Play does this internally.
     
  2. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    Wow, after researching this more it appears to be a very big and complicated problem. Does anybody at Unity have a whitepaper on the best way to handle OBB files?
     
  3. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  4. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    Ha, no. But I'm very, very glad you responded as this seems to be a critical issue to developers that require Android expansion files.

    The problem is complex, but the TLDR is that games do NOT have read/write access to the OBB directory without explicitly requesting READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE in the manifest.

    By doing this, however, newer versions of Android display an onerous permissions warning: "Allow YOUR APP to acces photos, media and files on your device." After casual research, some publishers state that this results in a 10%-15% loss of customers. (They download the game, but do not run it.)

    There are some fairly lengthy threads on this subject, which I have included below for reference. While I know this isn't really a "Unity problem", I was hoping somebody there may have a best-practice suggestion for this situation.

    Some references:
     
  5. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Unity seem to refuse to address this situation properly. As you point out you need this permission for expansion files to work correctly on all devices, and it has to be obtained on boot, any later (via the SkipPermissionsDialog manifest flag) and Unity will occasionally fail to mount it correctly based on our experience with devices in the wild. Google's requirements state that you must inform the user why you're asking for a sensitive permission before asking, but Unity provides no way for you to do this given the above.

    In order to get around this we've had to make a plugin that delays the startup of the UnityPlayerActivity in order to present the user with some context for the permission request before allowing Unity to start up. This works as a jar/manifest combo but not as an AAR for some reason so far (ref my post today).
     
    Tomurtogu likes this.
  6. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    Hi Hutch:

    So are you saying if you use SkipPermissionsDialog and ask for the permission later, you have still encountered devices (or OS versions) that won't properly grant access to the OBB?

    So, it sounds like your solution was to simply include the permissions, and politely ask the user to say "OK' to the onerous "This App wants to read and write all your data and send it to hackers" warning that Android pops up?

    So, we seem stuck in the risky position of either A) implementing a bunch of hacky workarounds or B) just asking for the permission and risk loosing a portion of our users over a perceived security issue.

    Any more advice?

    Ack!
     
  7. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Hi Matthew,

    Yes, due to Google insisting we address the lack of context before the permission request we enabled SkipPermissionsDialog but still asked for storage permission as soon as possible on boot after displaying some context for the user, and this caused hangs on a significant proportion of devices in the wild and we had to revert to Unity's default handling.

    Our more recent title was under 100mb so we avoided the issue but with our next title we'll need to ask for the permission, but with a friendly message in front of it via the method I outlined. It's possible this will scare away some users but I think if the messaging is correct it shouldn't be too bad, the permission text isn't quite as scary as that :) Unfortunately I'm not aware of any other solution short of shrinking your app under 100mb which may or may not be doable.
     
  8. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    Hey, thanks so much for the advice. So when you say "them method I outlined", you mean firing up an activity to do some messaging before Unity boots?

    I just want to be extra clear since after reading some more threads on this - I'm getting more confused, not less :)

    Thanks again - ain't this fun!
     
  9. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Yep that's correct, we fire off a new activity in onStart of the main activity to show some messaging and request the permission before letting Unity continue booting up. It's definitely not exactly a valuable use of time but in our experience Google won't give your app any support unless you comply with this requirement :(
     
  10. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    Man, what a hassle. Thanks much for your help on this. I have one more quick question... do you only do this for Android 6 and above? (since the run time permission "upgrade")

    I hope you don't mind if I pester you again if I get stuck :) It kills me that I have to do anything to extend the bootup time.

    BTW: What is the name of your app, can I check it out?
     
  11. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Yeah we do that via maxSdkVersion. The app with the changes isn't yet live unfortunately so I can't point you at it but I believe CSR2 has a similarly (extremely) basic implementation of the requirements (not via Unity but it works similarly). I have a watch on this thread so feel free to post in here if you need!
     
  12. MatthewHarmon

    MatthewHarmon

    Joined:
    Mar 5, 2015
    Posts:
    24
    Hey Hutch:

    We just about have this working. However, would you be willing to look at our code and let us know if it is similar to what you are doing? I feel there is too much at stake to have this dumb issue be a potential point of failure :)
     
  13. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Hi Matthew, yes sure no problem, feel free to DM me!
     
  14. NecrosDk

    NecrosDk

    Joined:
    Oct 5, 2012
    Posts:
    8
    @hutch_jl
    I'm currently attempting to implement the same solution as you, and have made a library project in android studio that handles the permissions requests.
    I've tried to export an aar file and note in my manifest that the 'permission checker' activity is the entry point by using:
    <action android:name="android.intent.action.MAIN" />

    My logcat shows the error "java.lang.RuntimeException: Unable to instantiate activity ComponentInfo java.lang.ClassNotFoundException: Didn't find class: "

    I then found this thread and saw that you went with a "jar/manifest combo"
    Would you care to elaborate how you managed to pull this off?

    I have tried simply taking the generated .jar file from Android studio, with my classes in them, putting them in the Plugins/Android folder, and using the package name from my java classes in my manifest in Unity (overriding the default).

    I used the following naming structure:

    the Apk has package name: com.company.gamename
    the .jar classes have package name: com.company.gamenamelauncher

    so to declare an activity from the launcher package I do the following in my manifest:

    <activity android:name="com.company.gamenamelauncher.ClassName">

    I get the same "fatal error" and a crash as noted above as when I did the aar method.
    Any help would be super appreciated!
     
  15. Stijn2097

    Stijn2097

    Joined:
    Jan 8, 2015
    Posts:
    7
    Hey guys,

    I'm running into the same problems. Headaches and annoyance over the 100mb apk app limit that is at the base of the problems.
    I hadn't yet heard of the problem hutch_jl mentions:
    This was actually what I was trying to implement but did not yet know that "this caused hangs on a significant proportion of devices in the wild"
    Do you know which devices suffer from this problem?

    So you disabled the "SkipPermissionsDialog" (removed it or set to false)? Or what do you mean with "Unity's default handling"?

    Could either of you share some implementation details or pointers? How do you delay the Unity activity? And you still need to ask the permission (with context) in the start-up/downloader activity (which would also need localization).
     
  16. NecrosDk

    NecrosDk

    Joined:
    Oct 5, 2012
    Posts:
    8
    So. I finally got the method of "Wrapping the app in another app" working.
    There were a lot of steps to it, but some general pointers:

    You need just ONE activity that handles these permissions, and then you need to import the unity library in your android library, and simply start the UnityPlayerActivity when you want to proceed with the game.
    See specifically this page: https://docs.unity3d.com/Manual/AndroidAARPlugins.html
    and the section about "Android Library Projects".
    You can put a .jar file in the Plugins/Android folder, and the manifest for your custom activity in your ".plugin" folder.

    You need to override the default manifest, and the only real difference you have to include, is that the UnityPlayerActivity is NOT flagged as the main activity, but the activity that you created in your library instead. If you just copy the "Resulting" manifest of a build, you're going to include the same "build tag" every build, which is supposed to be unique for every build, which is also included in the .obb file. And if those two don't match across manifest and .obb, your expansion will not load. So make sure not to override this.
    See: https://docs.unity3d.com/Manual/android-manifest.html

    If anyone gets truly stuck with this, feel free to message me and I'll try to help out the best I can.
     
  17. trj_1

    trj_1

    Joined:
    Jul 12, 2017
    Posts:
    3
    @NecrosDk We currently have a situation where people in early access / beta are reporting a black screen on startup and it may be related to what is being reported in this thread. None of us here are Java / Android developers although I can mess around with the code and run gradle tasks through Android Studio. I would say we are close to being stuck on this. Any assistance would be GREATLY appreciated.
     
  18. ABerlemont

    ABerlemont

    Joined:
    Sep 27, 2012
    Posts:
    67
    I assumed Unity would provide some way to check permissions states and to be able to call the native request window ...
    And I don't feel like re-writing an android plugin just to manage this -_- (let alone having the skills necessary to do it without any hiccups).

    Hopefully one day...
     
  19. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
  20. MoribitoMT

    MoribitoMT

    Joined:
    Jun 1, 2013
    Posts:
    301
    Is This obb permission problem solved?
     
  21. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Sorry for some reason I didn't see the notifications on this thread! The way I did this which might be a little different to @NecrosDk was to derive my activity from the main activity (in our case was Prime31's but could be the default Unity player). If you then override the activity lifecycle methods to start your permission request activity, which displays whatever context information you like (we just used a system dialog) before requesting permission, then stopping your activity to give control back to Unity again.

    This seems to be acceptable for Google, we've been through featuring review with it a couple of times.

    @StijnPaladin: We tried SkipPermissionsDialog but we found in the wild it generated black screen on boot issues on some devices as it sounds like @trj_1 is seeing also. We couldn't find a pattern to the issues so it seemed to be a timing issue on boot where Unity in some cases would try to access the obb before permission had been granted and would then hang.

    If anyone is still struggling with this I'll see if I can provide our workaround here. I really do think Unity's attitude with this isn't good enough, Google have required proper handling of this for 3 years now and we're still forced into hacky workarounds.
     
    Sciberus and MoribitoMT like this.
  22. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
  23. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,794
  24. socodev

    socodev

    Joined:
    May 4, 2018
    Posts:
    14
    I'm not sure if anyone here can clarify for me, because I THINK I'm running into a similar issue:

    - Our app utilizes OBB files.
    - Our app downloads said OBB file from the Play Store simultaneously with the APK, and places it in the Android/obb/folder section (for what it's worth, I don't have an SD Card storage setup, just space on the Pixel XL tester phone).
    - Our app asks for permission to use the camera (it's an AR app) and then to read/manage our photos, videos, files on first-time running. (I presume this encapsulates the OBB file as well, feel free to correct me)
    - Our app then runs through the Preloader scene and the loading bar for it... and then does nothing. Sits at 100% on the loading bar, where normally it would load our Main (AR) scene. Based on this, we can only conclude that the OBB is NOT being accessed despite location, and the rest of the scenes and content are not being loaded.

    Now, we're somewhat new to app development here at the office, so I must ask - Is there something that I need to add to the Preloader scene, like a script or a plugin, that "puts humpty-dumpty back together again" so to speak? Is there something that the first scene (from the APK) needs to properly access the OBB file's contents?

    We're sort of lost on this one, can someone illuminate this aspect of the process? Or is this simply part of the permissions problems you guys are running into?
     
  25. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    Yes, using an OBB implies an automatic "read external storage" permission prompt on startup, before the OBB is mounted.
     
  26. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    Which version of Unity is that?
    Do you have skipPermissionDialog in your manifest, or are you relying on the Unity's feature to ask for all permissions on startup?
    What is in the logcat when the second scene can't be loaded?
     
  27. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,794
    Thanks for all the help. If you can, I will sum up the permissions situation and please tell me if I'm wrong anywhere.

    1. Unity asks for READ_EXTERNAL_STORAGE on startup, regardless of skipPermissionDialog if OBB split is enabled.

    (which shouldn't be required normally, but since Android is a buggy mess, in some versions (6.0, maybe 7.0, 7.1 I don't know about newer), it sets the folder the OBB is in as root, so permission is needed...).

    My question is: How can we "provide context" in order to comply with Google's guidelines for the READ_EXTERNAL_STORAGE permissions prompt, if it gets automagically asked before we can actually do anything? It seems that there is no way currently?

    (although, if we're being truthful, the true context is "We need this permission, because android is a buggy mess" and I'm not sure if Google would appreciate it)

    2. Because of the same bug, if the OBB doesn't get downloaded with the APK, we need to ask for WRITE_EXTERNAL_STORAGE before we launch the OBB downloader, because otherwise the OBB downloader will not be able to download anything.

    3. What do I have to do in order to make Google raise the APK limit in order be rid of the .OBB mess they have created? (okay you don't need to answer this one :p ). All other Android stores have managed it, I don't understand why Google is insisting on keeping this around.
     
    ManOfDrive likes this.
  28. socodev

    socodev

    Joined:
    May 4, 2018
    Posts:
    14
    I was actually able to solve this one Yury! There was an issue where I had modified the manifest file directly (as per another user's instructions from one of these discussions), and it corrupted the interaction between the APK and OBB file. I instead went back and applied a different plugin fix for the issue, which allowed for the correct interpretation of the OBB! I then had to patch Vuforia's target acquisition with their own official fix script, which I embedded in a scene that loads before my own Preloader to reacquire their targets from the OBB. Shazam! Works great.

    Thanks for taking the time to respond!

    For your own info on the subject:
    - Running Unity 2018.2.14f1
    - Running Vuforia 7.5.26
    - I don't have skip permission dialogue, but instead let the standard asking of permissions (Camera, then Devices and Files) occur on first startup.
    - There wasn't a log that I ever looked over, as a crash never actually occurred as far as I can tell. The app just figured it was finished with its tasks, because there wasn't technically another scene to load in without a proper read of the OBB.

    Again, thanks for taking the time! (It's a pretty rare phenomenon to see on a dev forum these days :D)
     
    Yury-Habets likes this.
  29. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    :D
    We do respect the skipPermissionDialog flag even for the new built-in permission prompts.
    Providing context is hard. I can imagine you could display a dialog from Java before starting UnityPlayer.

    Can you request the permission in OBBDownloader then?

    I actually have an answer for you. :) And the answer is: Android App Bundle https://developer.android.com/platform/technology/app-bundle/
    - it helps avoid FAT APKs or split APKs for architectures
    - it calculates the on-the-air size instead of the APK size, which helps save few more per cent
    - based on what I've read in https://medium.com/googleplaydev/wh...t-means-for-the-future-of-android-2e34981793a, the size limit for the APK generated from an app bundle is expected to be increased to 500 Mb, eliminating the need for the OBB for 99% of the cases
    - Android app bundle support is in Unity 2017.4 and 2018.3 https://blogs.unity3d.com/2018/10/03/support-for-android-app-bundle-aab-in-unity-2018-3-beta/
    - if that's still not enough, feel free to use Unity Asset Bundles.
    - if you're still not within limits, then you have to switch to using OBB.
     
    AcidArrow and JuliusM like this.
  30. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,794
    Thanks @Yury-Habets for the reply.

    Unfortunately I don't see Android App Bundle being a solution for anything I care about.

    It seems like overkill and overly complicated for our purposes. We don't do different assets per device, so I don't have any use for "dynamic" stuff.

    We just have a bunch of stuff our game uses that we'd like to be downloaded on the device before the our game starts, but apparently that's too much to ask.

    We are also over 500mb in size, so I guess we'll be stuck with the OBB and permissions mess forever.

    Yay.
     
  31. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    Well, Unity currently supports only architecture split. Select the checkbox, build, ship - it's transparent and no overhead, taken that you are using the Play signing. Nothing complicated :)
     
    AcidArrow likes this.
  32. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    61
    Also have been struggeling with this problem for a week now. But i have solved it by using https://github.com/Over17/UnityAndroidPermissions

    1. In my first scene i check if i can access the OBB file
    - If i can i just continue loading the menu scene
    - If not i show a native dialog that explains why we need the READ permission and then i ask for it.
    - If the user still denies the permission i show him a dialog explaining that he must accept it in order to play. I then ask again.
    - If the user ticks the "Never show again" checkbox that becomes available the second time i ask for the permissions i show him another dialog that explains that he now has to go to Settings->Application>->AppName and manually grant the permission.

    I have some problems still tough. For instance the documentation states

    • APK - Consists of the executables (Java and native), plug-ins, scripts, and the data for the first Scene (with the index 0).
    • OBB - Contains everything else, including all of the remaining Scenes, resources, and streaming Assets
    I find this to not be true. In my first scene(index 0) i have a background image setup in a canvas. This image is not available and has been packed in to the OBB. It renders the usual purple(missing) texture.

    It would be nice to have the ability to explicitly choose files that should not be packed in the OBB.
     
  33. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    I would be careful to make sure this works for you "in the wild" - we had a non-negligible number of reports of the device booting to a black screen and not making it to the first scene to do the checks. This was a while ago though so I can't say if it's still the case. The only 100% reliable way I found at the time to address this problem was the approach described above that doesn't rely on Unity starting up at all.
     
  34. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    61
    Thanks for the comment @hutch_jl . I'll definitely consider your approach as it's probably the safest one. But correct me if i'm wrong. Since Android 4.4 we actually get access to the OBB without the READ permission, we only need it for Android 6 where Google F***ed up and had to enable it again? Because on all our phones here at the office our game always pass the OBB check and go straight to the menu scene.
     
  35. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    61
    And @hutch_jl . If it is possible it would save me a couple of days if you could share your solution. It would be much appreciated.
     
  36. hutch_jl

    hutch_jl

    Joined:
    Jan 8, 2013
    Posts:
    40
    Hi Kristofer, yeah it's because of this bug:

    https://issuetracker.google.com/issues/37075181

    Your best bet may be to move to app bundles if you can as Google are raising the limit for those to 500mb without using expansion files, so you avoid the whole problem. I'll see if I can pull together what we did though, it's very basic but does the job.
     
  37. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    Can you please submit a bug report with the project attached, and post the case # here? Thanks!
     
  38. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    61
    @Yury-Habets I'd love to submitt a bug report, i have several bugs in our backlog that are Unity/Android specific. However, i can not attach the entire project, and thats the case for all our projects at our company.

    Reproducing issues in empty projects takes a lot of time and rarely works, at least that is our experience and we only proceed trying to reproduce something if it is critical for the project to move forward and no workaround is available.
     
  39. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    @KristoferBoman unfortunately there is no way for us to fix and verify an issue if there is no bug report and no project. A significant part of the issues is related to the project itself, be it a setting which is messing up or some code or scene setup or something else. This is a reason why a even a single script may not be enough to comprise a bug report.

    The behavior you mentioned is unfamiliar to me; the chances that there is something in the project which is causing it are quite high. As I said, it's hard to say without a bug report.

    How do you know the image has made it into the OBB instead of the APK?
     
  40. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    61
    @Yury-Habets I totally understand that you need the project, and like you say the issues are almost always related to the project itself, and that is of course the reason it is hard to reproduce issues in empty projects.

    We can unfortunately still not attach our projects for many reasons.

    I'm not sure the image has made it into the OBB, it's either in there or it's lost somewhere else :) But it's not in the APK anyway, if it was i would assume it would render correctly in the scene. It only renderes if i also install the OBB.
     
  41. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    Is the image maybe in StreamingAssets?
     
  42. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    61
    @Yury-Habets No, it's not in the StreamingAssets folder. It's a Sprite placed in a Canvas in our first scene with scene index 0.

    PreloadScene.png
     
  43. MetaDOS

    MetaDOS

    Joined:
    Nov 10, 2013
    Posts:
    157
    Hi. So is it possible to use the OBB file without requiring write external storage permission?
     
  44. Yury-Habets

    Yury-Habets

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    1,167
    That's a question with no straight answer.
    General answer is "yes", according to Android documentation, starting with some API level.
    Unfortunately some devices have bugs which make it a "no".
    I can't remember if READ_EXTERNAL_STORAGE is enough for those devices, most likely it is.
    You may want to search for related threads.