如何在Android Marshmallow中向服务请求权限

109
在Android Marshmallow中,应该在需要使用权限时,在运行时请求权限,而不是在安装应用程序时一次性请求所有权限。然而,我似乎只能从Activity请求权限,这是一个问题,因为我的应用程序仅包含服务。 (你可能会问为什么?该应用程序内置了一个Android Wear表盘,并且手机只是查找附近的照片并将其发送到手表 - 不需要Activity。但它确实需要位置权限。)
那么,有没有办法从服务请求权限?或者以某种方式强制在安装时授予权限,就像过去一样?

这个问题也在Application类中。 - itzhar
试一下这个,可能会起作用 https://dev59.com/J1wX5IYBdhLWcg3w-Thv#41221852 - Bipin Bharti
我的库可以轻松处理来自任何上下文的运行时权限,并且还可以处理“不再询问”。https://github.com/nabinbhandari/Android-Permissions - Nabin Bhandari
5个回答

52

requestPermission()只能从一个Activity中调用,而不能从Service中调用(与只需要PackageManagercheckPermission()不同)。因此,您需要做一些额外的工作来解决这个问题;您需要在应用中提供一个Activity,例如,您的Service可以检查它所需的权限,如果它们尚未被授予,则可以创建一个通知,并且可以用一个描述性的短消息告知用户为什么有一个通知以及当他们单击通知时需要发生什么等。


这是Benjamin Poiesz提出的解决方案。您可以从23:40开始收听此podcast - xiaomi
你也可以在Fragment中调用requestPermission()。 - Misagh Emamverdi
4
当我在设置中关闭了位置权限,而一个正在后台持续检查位置更新的服务仍在运行时,该如何解决这种情况?因为没有活动,当我重新打开应用程序时,这将导致服务崩溃。 - stud91
1
@stud91 至少在每次请求位置更新时捕获安全异常或查询权限。这将防止您的应用程序崩溃(尽管如果权限已被撤销,则不会获取任何位置)。更好的做法是:检查权限,如果缺少权限,则显示一个通知,该通知将用户带到一个仅用于权限对话框的占位符活动。 - user149408
9
这是我的解决方法:https://github.com/mvglasow/satstat/blob/master/src/com/vonglasow/michael/satstat/utils/PermissionHelper.java。它可以从任何实现了`OnRequestPermissionsResultCallback`的`Context`中调用。其功能类似于标准的`requestPermission()`。 - user149408
本杰明·波伊兹的解决方案在哪里? - KansaiRobot

15

我同意,这对服务来说非常麻烦。我认为你应该在Android开发者预览页面上报告此问题。

目前,我认为最好的解决方案是在服务上检查权限,并在权限缺失时显示通知。更好的方法是创建一个DialogActivity,在用户按下通知时请求权限。


7
请查看PermissionEverywhere库。它允许您从任何上下文中请求权限。
它创建了一个通知,点击后打开一个活动来请求权限。
库的 Github 页面中提供了示例代码:
@Override
  protected Boolean doInBackground(Void... params) {
      PermissionResponse response = PermissionEverywhere.getPermission(getApplicationContext(), 
      new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
              REQ_CODE,
              "Notification title", 
              "This app needs  a write permission", 
              R.mipmap.ic_launcher)
              .call();
      //waits..
      boolean isGranted = response.isGranted();

      if(isGranted){ //changed from isGrante to isGranted
      // Do stuff
      }
  }

2
我在一个服务中尝试了异步版本,但它没有起作用。onComplete从未被调用过。 - Leo DroidCoder
好主意,但它在存储库中不可用。 - naXa stands with Ukraine
2
这个包对我很有用,感谢您的建议。不过,我没有尝试异步版本。另外,对于那些在使用PermissionEverywhere时遇到问题的人,请确保在清单文件中声明了帮助器活动,并确保在声明时将其绑定到正确的包(如果您正在使用PermissionEverywhere作为单独的包)。花了我很长时间才意识到我实际上没有在清单文件中指定PermissionEverywhere包。 - user3570982
我运行了PermissionEverywhere的演示应用程序,但它没有工作。 - User
无法使其正常工作,而且 GitHub 的问题多年来一直没有得到回答。我认为这已经被放弃了。 - topher217

5

有一个非常简单的库可以实现这一点。您可以从任何地方(甚至是从服务)检查权限,根据应用程序是否在前台或后台,它会显示普通对话框或生成通知要求权限。代码真的很容易理解,也很容易使用。

请尝试一下:Android Permissions


-2

您可以使用ResultReceiver创建用户答案的接收器,然后将其作为回调传递给Activity,通过通知的PendingIntent参考资料


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接