如何从 Android Marshmallow 中的服务请求权限

Posted

技术标签:

【中文标题】如何从 Android Marshmallow 中的服务请求权限【英文标题】:How to request permissions from a Service in Android Marshmallow 【发布时间】:2015-11-24 09:24:10 【问题描述】:

android Marshmallow 中,权限应该在需要时在运行时请求,而不是在安装应用时一次性请求。但是,我似乎只能从 Activity 请求权限,这是一个问题,因为我的应用程序只包含服务。 (您可能会问,这是为什么呢?该应用程序内置了一个 Android Wear 表盘,手机所做的只是查找附近的照片以发送到手表 - 不需要 Activity。但它确实需要位置权限。)

那么,有什么方法可以向服务请求权限?还是像过去一样强制在安装时授予权限?

【问题讨论】:

这个问题也在Application类中 试试这个可能有用***.com/a/41221852/5488468 我的库可以从任何上下文轻松处理运行时权限,还可以处理“不再询问”。 github.com/nabinbhandari/Android-Permissions 【参考方案1】:

requestPermission() 只能从Activity 而不是Service 调用(不像checkPermission() 只需要PackageManager)。所以你需要做一些额外的工作来解决这个问题;您确实需要在您的应用程序中提供Activity,例如,您的Service 可以检查它需要的权限,如果尚未授予权限,它可以创建一个通知并通过描述性简短通知用户关于为什么会有通知以及点击通知时需要发生什么等的消息。

【讨论】:

这是Benjamin Poiesz提出的解决方案。你可以从 23:40 开始收听这个podcast 你也可以在fragment内部调用requestPermission()。 运行后台服务定期检查位置更新的解决方案是什么,我只是在设置中关闭了位置权限。由于没有活动,当我重新打开应用程序时,这会导致我的服务崩溃 @stud91 至少,在每次请求位置更新时捕获安全异常或查询权限。这将防止您的应用程序崩溃(尽管如果权限被撤销,您将不会获得任何位置)。更好的是:检查权限,如果没有,显示一条通知,将用户带到一个 Activity,它只是权限对话框的占位符。 我是这样解决的:github.com/mvglasow/satstat/blob/master/src/com/vonglasow/… 它可以从任何Context 调用,它也实现了OnRequestPermissionsResultCallback。功能类似于标准requestPermission()【参考方案2】:

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

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

【讨论】:

【参考方案3】:

看看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
      
  

【讨论】:

我在 Service 中尝试过异步版本,但没有成功。 onComplete 从未被调用过 好主意,但它在存储库中不可用 这个包对我有用,谢谢你的建议。不过,我会注意到,我没有尝试异步版本。此外,对于那些在使用 PermissionEverywhere 时遇到问题的人,请确保在清单中声明帮助程序活动,并确保在声明它时,它与正确的包相关联(如果您使用 PermissionEverywhere 作为单独包装)。我花了很长时间才意识到我实际上并没有在清单中指定 PermissionEverywhere 包。 我运行了PermissionEverywhere 的演示应用程序,但没有成功。 无法正常工作,而且 github 问题多年后仍未得到答复。认为这已被放弃。【参考方案4】:

有一个非常简单的库可以做到这一点。您可以从任何地方(甚至从服务)检查权限,根据应用程序是在前台还是后台,它要么显示正常对话框,要么生成请求权限的通知。该代码非常容易理解,也非常易于使用。

试试看:Android Permissions

【讨论】:

【参考方案5】:

您可以使用ResultReceiver 创建用户回答的接收者,然后通过通知的PendingIntent 将其作为回调传递给活动。 Reference

【讨论】:

以上是关于如何从 Android Marshmallow 中的服务请求权限的主要内容,如果未能解决你的问题,请参考以下文章

如何使用默认裁剪意图裁剪 android marshmallow 中的图像?

如何在 Android 6.0 Marshmallow 中访问相机?

Android 自定义权限 - Marshmallow

如何以编程方式打开 Android 6.0 (Marshmallow) 上特定应用的权限屏幕?

如何在 Android Marshmallow 平台上高效开发系统应用?

如何在打盹模式下移动设备(Android Preview M / Marshmallow)?