Android运行时权限

比特逸风
• 阅读 2190

Android运行时权限

参考网址:在运行时请求权限

在Android6.0之前应用请求权限都是在应用安装时将所有权限清单展示给用户,当用户选择安装就默认允许应用请求的所有权限,而Android6.0(API级别23)以后google修改权限请求的方式,首先将权限分为两类:

  • 正常权限:不会给用户带来隐私风险的权限。只要在AndroidManifest.xml中声明即可,系统自动授权。
  • 危险权限:可能会访问用户隐私数据的权限。需要先在AndroidManifest.xml中声明,然后在使用之前通过用户手动授权。
关于权限的分类请参考官网文档:系统权限

新的权限管理分为以下两种情况:

  • 如果手机系统低于Android6.0或者应用的targetSdkVersion低于23,还是按照老的权限管理方式:在AndroidManifest.xml声明的所有权限都会在应用安装时以清单的形式展现给用户,如果用户同意安装就通过了所有的权限申请。
  • 如果手机系统为Android6.0以上并且应用的targetSdkVersion等于或者高于23,就会按照新的权限管理方式:在AndroidManifest.xml中声明的正常权限系统将会系统授权,而危险权限就需要应用在使用权限之前请求用户授权。

注意:当手机系统为Android6.0以上但是应用的targetSdkVersion低于23虽然采用的是安装时授权,但是用户依然可以在设置中手动关闭应用的权限,所以应用开发依然需要考虑缺失某些权限的情况

接下来看看应用是如何检查和请求用户授权的:

  1. 检查授权:使用ContextCompat.checkSelfPermission方法检查Activity是否获得授权,返回值PackageManager.PERMISSION_GRANTED表示已获得授权,PackageManager.PERMISSION_DENIED表示未获得授权,示例代码如下:

    int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.WRITE_CALENDAR);
    if (PackageManager.PERMISSION_GRANTED == permissionCheck) {
        // 已授权
    } else {
        // 未授权,需要请求用户授权
    }
  2. 申请权限:使用ActivityCompat.requestPermissions方法动态申请权限,示例代码如下:

    final static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
    
    ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
  3. 获取权限申请结果:通过ActivityonRequestPermissionsResult回调获取申请结果,示例代码如下:

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE == requestCode) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授权通过
            } else {
                // 用户拒绝授权
            }
        }
    }
  4. 判断用户是否拒绝过授权:用户拒绝授权可能是因为不了解应用获取权限的目的,所以google推荐开发者在用户拒绝授权之后再次请求权限之前可以向用户说明申请权限的目的有利于用户通过授权,可以通过ActivityshouldShowRequestPermissionRationale方法得知用户是否已经拒绝过授权,示例代码如下:

    if (Build.VERSION.SDK_INT > 22 
    && shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        // 用户已经拒绝过授权,可以想用户说明申请权限的目的
    } else {
        // 直接请求权限
    }

通过上述几个步骤已经完成了一次运行时权限申请的全部过程,还有一点requestPermissions方法请求权限的时候,系统唤起的dialog上显示的是开发者所申请权限的权限组的信息,同一个权限组的权限只需要申请一次一旦用户授权通过应用就会获取整个权限组的授权,再次请求同组的其它权限系统会自动授权,理论上来说同组权限只需要申请一次,但是goole的官方文档上依然推荐开发者为每个权限单独申请授权,因为在之后的版本升级中权限的分组可能会发生改变。

最后附上完整的运行时权限申请示例:

class MainActivity : AppCompatActivity() {
    val PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button.setOnClickListener({
            val permissionCheck = ContextCompat.checkSelfPermission(this@MainActivity,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)
            if (PackageManager.PERMISSION_GRANTED == permissionCheck) {
                Toast.makeText(this@MainActivity, "权限已授权", Toast.LENGTH_SHORT).show()
            } else {
                if (Build.VERSION.SDK_INT > 22 && shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    Toast.makeText(this@MainActivity, "授权已经被拒绝过了,可以向用户说明权限用途", Toast.LENGTH_SHORT).show()
                    AlertDialog.Builder(this@MainActivity)
                            .setMessage("权限作用说明")
                            .setPositiveButton("我知道了", { dialog, which ->
                                requsetPermission()
                            })
                            .create().show()
                } else {
                    requsetPermission()
                }
            }
        })
    }

    private fun requsetPermission() {
        ActivityCompat.requestPermissions(this@MainActivity, Array(1) { Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        if (requestCode == PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this@MainActivity, "授权成功", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this@MainActivity, "授权失败", Toast.LENGTH_SHORT).show()
            }
        }
    }
}
点赞
收藏
评论区
推荐文章
东方客主 东方客主
4年前
Android输入法遮挡了输入框,使用android:fitsSystemWindows="true"后界面顶部出现白条
问题1、页面布局文件:<LinearLayoutxmlns:android"http://schemas.android.com/apk/res/android"android:id"@id/layoutorderdetail"android:layoutwidth"matchparent"android:layoutheigh
红橙Darren 红橙Darren
3年前
Android 6.0 运行时权限封装框架
1.概述视频讲解都已经录了好几天,但是最近实在抽不开身一直在忙Unity3D,就连光棍节都在写,上次我们只是写了,但是并未对其做代码封装,这一次我们做一个彻底的处理。  附视频讲解地址:  这里写图片描述2.框架封装2.1.简单例子publicclassMainActivityextendsAppCompatActivity
红橙Darren 红橙Darren
3年前
Android 6.0 运行时权限处理解析
1.概述不知道大家有没有遇到过这种情况,开发app的时候发现自己手机选择照片是正常的,测试那边的一台手机怎么搞都不行,然后查看版本之后才发现是6.0的手机。    随着Android6.07.0我们开发者所要应对的主要就是新版本SDK带来的一些变化,既然是程序员那么我们肯定就特别关注开发部分的变化,其中之一就是权限处理。那么在6.0及以上版
Stella981 Stella981
3年前
Cocos Creator 运行时与本地代码双向通讯
cocoscreator游戏在发布到android/ios等平台时,难免要与本地原生平台互相调用。官方为我们提供了Java原生反射机制和ObjectiveC原生反射机制。以android的Java平台为例cocoscreator运行时调用android原生环境varojsb.reflection.cal
Stella981 Stella981
3年前
Android笔记
  首先是权限,因为WIFI也是可以用于定位的,只是精度没那么高而已,所以6.0之后的权限系统对WIFI的权限进行了限制,除了需要日常的WIFI操作权限之外,还需要定位权限,否则会获取不到WIFI的信息。<!完全的网络访问权限<usespermissionandroid:name"android.pe
Stella981 Stella981
3年前
Android 设置系统闹铃和日历
一、创建定时器 设置权限<usespermissionandroid:name"com.android.alarm.permission.SET_ALARM"/案例https://developer.android.com/reference/android/provider/Alar
Wesley13 Wesley13
3年前
Unity横屏
Android下发现Unity里面的Player设置,并不能完全有效,比如打开了自动旋转,启动的时候还是会横屏,修改XML添加以下代码<applicationandroid:icon"@drawable/ic\_launcher"                    android:label"@string/app\_name"
Stella981 Stella981
3年前
Android版添加phonegap
1.下载插件包。2\.解压所下载的包,从lib目录中得到所需要的所有的库:BaiduSocialShareSDKAndroid2.0.0.jar3\.修改AndroidManifest.xml,增加以下权限:<usespermissionandroid:name"android.permiss
Stella981 Stella981
3年前
Android动态添加Device Admin权限
/Android动态添加DeviceAdmin权限说明:Tony在Android5上研究的怎么动态添加设备管理员权限。
Stella981 Stella981
3年前
Android加载网络图片
AndroidManifest.xml文件中加入以下权限设置:    <usespermissionandroid:name"android.permission.INTERNET"/    <usespermissionandroid:name"android.permission.WRITE\_EXTERNAL\_STORAGE
Stella981 Stella981
3年前
Android选项卡TabHost功能和用法
1、布局文件<TabHostxmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:id"@android:id/tabhost"