Search code examples
androidandroid-permissionsandroid-6.0-marshmallow

Options for dealing with Android 6.0's new permissions requirements from a service or model component?


I'm looking into porting some existing code to take Android M's new way of dealing with permissions into consideration. However the permission API needs to have an activity associated with it (for example the requestPermissions() method's first parameter is an activity).

So how should a service that needs to check if a permissions has been granted and request for permissions use this new API if the service doesn't have an activity?

Is it possible for the service to create a dummy invisible activity just for use with the permissions API? (if its possible I don't like the thought of doing that anyway though).

Or suppose its not a service but a model class that needs to perform a permissions check, in MVC a model shouldn't have any knowledge of the Vs and Cs and yet now either it has to in order to know which Activity to use with the permission API. Or potentially lots of code might have to migrate from model code into Activity code.

Any thoughts on how to migrate non activity based code that needs to check/prompt for permissions over to Android 6.0?

Update: I left out an important piece of information - this is code that is pre-installed (our company provides code that device manufacture's place in rom) and often may be run at device boot time and run in the background. Therefore the usual situation of a user being prompted for permission when they launch the app or later (and there therefore being an activity at that point) does not necessarily apply.


Solution

  • So how should a service that needs to check if a permissions has been granted and request for permissions use this new API if the service doesn't have an activity?

    There is almost always an activity, except for pre-installed apps and plugins for other apps. Otherwise, your service is unlikely to ever run, as nothing will have used an explicit Intent to start up one of your app's components, so it will remain in the stopped state.

    For the ~99.9% of Android apps that have an activity already, if the permissions are needed for the whole operation of the app, request them on first run. As Snild Dolkow notes, if the user later revokes the permission through Settings, you can detect that without an activity, then use other UI options (e.g., Notification, app widget) to let the user know that operation is suspended until they grant you the permissions again, which they would then do through your activity.

    Is it possible for the service to create a dummy invisible activity just for use with the permissions API?

    Presumably you can have a Theme.NoDisplay activity use requestPermissions(). However, from the user's standpoint, it will not make much sense, unless there's some alternative UI (app widget?) that they are interacting with. Popping up a permission dialog out of nowhere is unlikely to make you popular.

    UPDATE 2019-06-15: Note that Android Q bans services popping up activities frmo the background. Please use a notification instead.

    in MVC a model shouldn't have any knowledge of the Vs and Cs and yet now either it has to in order to know which Activity to use with the permission API

    Do not touch the models until you have requested the permission, and gracefully fail if the permission is revoked. You already have to gracefully fail in other circumstances (out of disk space, no Internet connection, etc.), so a revoked permission should be handled in much the same way.

    using this new 6.0 API seems like an recipe for bad design and tight coupling

    You are welcome to your opinion. Based on what I have read, the Android engineers believe that asking the user for permissions is part of the user experience and is best handled at the UI layer as a result.

    Again: the vast majority of Android apps will not have a problem with this, as they have a user interface. Apps that do not have a user interface and need dangerous permissions are in for some amount of rework.

    this is code that is pre-installed (our company provides code that device manufacture's place in rom) and often may be run at device boot time

    First, please understand that this is so far from normal that you can't even see normal from where you are due to the curvature of the Earth. :-) You can't really complain that Google did not optimize this particular scenario.

    As I understand it, even system apps should be asking for runtime permissions. The Camera app did, for example, on the 6.0 preview. That being said, there's gotta be some database on the device somewhere that is tracking what has been granted, and presumably there is some way to pre-populate it. However, the user could still revoke it from Settings, presumably. But, the manufacturer could pull some stunts (e.g., messing with the Settings app) to possibly even preclude that scenario. I'd be looking in the same area as "how do I get it so my app cannot be force-stopped?" that device manufacturers can do.

    Your alternatives would be to get rid of the dangerous permissions or to migrate your app off the SDK and into a standard Linux binary that would be run as part of the boot process and be put into a Linux user group that has access to the stuff that you need.