Android M请求权限非活动

Posted

技术标签:

【中文标题】Android M请求权限非活动【英文标题】:Android M request permission non activity 【发布时间】:2015-10-08 18:12:03 【问题描述】:

我的小部件调用Activity 范围之外的安全权限。是否可以在 Activity 之外请求 Android M 的权限?

【问题讨论】:

【参考方案1】:

我正在创建一个需要在许多活动中检查权限的应用程序,因此我创建了一个可以在应用程序中全局使用的静态类。 它奏效了。 这对我有用。

我创建了一个方法来检查不同类中的权限请求,就像这样。

public class CheckForPermissions implements ActivityCompat.OnRequestPermissionsResultCallback 
private static final int MY_PERMISSIONS_REQUEST_READ_LOCATION = 1;


    public static void checkForLocationPermissions(Activity context)
        if(ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)  != PackageManager.PERMISSION_GRANTED
        || ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)  != PackageManager.PERMISSION_GRANTED)
            ActivityCompat.requestPermissions(context,
                    new String[]Manifest.permission.ACCESS_FINE_LOCATION,
                    MY_PERMISSIONS_REQUEST_READ_LOCATION);

    

在我的Activity中,我是这样调用方法的

        CheckForPermissions.checkForLocationPermissions(this);

【讨论】:

【参考方案2】:

我找到了一个似乎可以正常工作的解决方法。诀窍是创建一个透明的活动,该活动仅用于请求权限并在之后立即完成。当然,您仍然需要一个上下文,但它不一定是一个活动。 活动可以通过广播返回结果(授予或拒绝)(因为startActivtyForResult 在活动之外是不可能的)。

您可以使用此活动:

import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AppCompatActivity

internal const val PERMISSIONS_KEY = "permissions"
internal const val ACTION_PERMISSIONS_GRANTED = "GetPermissionsActivity.permissions_granted"
internal const val ACTION_PERMISSIONS_DENIED = "GetPermissionsActivity.permissions_denied"

class GetPermissionsActivity: AppCompatActivity() 

    private val permissionRequestCode = 0

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        ActivityCompat.requestPermissions(
            this,
            intent.getStringArrayExtra(PERMISSIONS_KEY),
            permissionRequestCode
        )
    

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) 
        if (requestCode == permissionRequestCode) 
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) 
                sendBroadcast(Intent(ACTION_PERMISSIONS_GRANTED))
             else 
                sendBroadcast(Intent(ACTION_PERMISSIONS_DENIED))
            
            finish()
         else 
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        
    

活动的这种风格

<style name="Theme.Transparent" parent="Theme.AppCompat">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:backgroundDimEnabled">false</item>
    <item name="android:windowAnimationStyle">@null</item>
</style>

在清单中:

<activity android:name="GetPermissionsActivity" android:theme="@style/Theme.Transparent" />

然后像这样使用它(需要上下文)

class SomeClass : BroadcastReceiver() 

    private fun someFunction(context: Context) 
        val intentFilter = IntentFilter()
        intentFilter.addAction(ACTION_PERMISSIONS_GRANTED)
        intentFilter.addAction(ACTION_PERMISSIONS_DENIED)
        context.registerReceiver(this, intentFilter)
        val intent = Intent(context, GetPermissionsActivity::class.java)
        intent.putExtra(PERMISSIONS_KEY, arrayOf(<your permissions>))
        context.startActivity(intent)
    

    override fun onReceive(context: Context, intent: Intent) 
        when 
            intent.action == ACTION_PERMISSIONS_GRANTED -> 
                context.unregisterReceiver(this)
                onPermissionsGranted()
            
            intent.action == ACTION_PERMISSIONS_DENIED -> 
                context.unregisterReceiver(this)
                onPermissionsDenied()
            
            else -> super.onReceive(context, intent)
        
    

    private fun onPermissionsGranted() 
        // ...
    

    private fun onPermissionsDenied() 
        // ...
    

【讨论】:

【参考方案3】:

您可以使用Easy Permissions 库。

Android 要求这些请求来自Activity。有了 Easy Permissions,这不再是问题,只要您提供 Context,您就可以从任何地方请求许可。此外,如果您请求的权限已被授予,则不会提示用户。

完全披露,我们公司管理和开发这个免费使用的图书馆。话虽如此,我们相信它是一个有用的工具,否则我们不会分享它。

【讨论】:

这对我来说没有任何意义。如果 Android 真的需要使用活动来请求权限,那么您的库必须是纯粹的魔法,因为它可以完成不可能的事情。事实是您使用了上下文。这与标准 checkSelfPermission() 相同。我看不到使用 3rd 方库进行此权限检查的真正优势。也许我错过了什么...... @TheincredibleJan 感谢您与我们联系。 Android 确实需要Activity。图书馆需要Context,就像许多图书馆一样——它很神奇,但它仍然基于现实世界:)。最大的优势是您可以从任何地方请求启用权限,即使是不是Activity 的类。此外,最新版本将允许您自动启用 Manifest 文件中的所有权限。 GitHub 页面上有一个示例应用程序;如果您有几分钟的时间,您绝对应该检查一下。如果您还有其他问题,请告诉我们。 此解决方案在 S5 Android 6.0 上测试过,但不起作用,目前它什么也不做。【参考方案4】:

我认为可以在Activity之外请求权限,只要你使用方法

ActivityCompat.requestPermissions (Activity activity, String[] permissions, int requestCode)

来自支持库并将 Activity 作为方法的参数传递。

例如:

ActivityCompat.requestPermissions(targetActivity, new String[] Manifest.permission.CAMERA, PERMISSION_REQUEST_CODE);

其中 targetActivity 是应该实现该方法的 Activity:

onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)

这就是处理de权限请求结果的方法。

【讨论】:

在 Activity 之外是指来自 Service 或 BroadcastReceiver,你根本没有 Activity。这个答案根本没有帮助。 一般来说,您可以将上下文对象传递给非活动类,并在需要上下文且您没有活动时使用它。不过,请求权限是另一回事。 @Gabe 一方面你是对的,但另一方面,问题并没有指出提问者想从哪里调用请求。所以我认为这是一个正确的答案。 @GabeSechan 在服务和广播的情况下如何在android M中设置权限? 如果权限在AppWidgetProvider中怎么设置?还是应该放在我的RemoteViewsService.RemoteViewsFactory中?我的小部件中的ListView 需要检查位置。【参考方案5】:

您只能向 Activity 或 Fragment 请求权限。

找出 Activity 或 Fragment 中您认为 App 需要权限的点,然后调用 requestPermission 方法。发送通知将不起作用,因为您希望您的代码处理直到您获得请求的权限,然后从 onRequestPermissionResult() 方法恢复您的功能。

【讨论】:

【参考方案6】:

不,这是不可能的。您可以做的是发送一个通知,用户可以点击该通知,然后使用活动来请求/管理权限(可能带有对话框主题)。

【讨论】:

配置活动也是处理这个问题的好地方。尽管用户可以进入权限屏幕并撤销任何先前授予的权限,但仍然需要通知方法。我还考虑将小部件置于权限撤销的 UI 状态作为替代方法。

以上是关于Android M请求权限非活动的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android M 中检查单个请求的多个权限?

在运行时请求权限,Android M+

Android 在活动开始时询问相机权限

Android - 请求查看用户位置的权限

Android M 动态权限获取

Android - AlertDialog 位于任何活动之上,不依赖于特定活动