程序运行时权限申请及targetSdkVersion的区别

Android面试:compileSdkVersion、targetSdkVersion、minSdkVersion作用与区别 作用 Android Studio 新建一个工程后,build.gradle里会有compileSdkVerson、targetSdkVersion、minSdkVersion这几个字段,这些配置有啥意义呢? compileSdkVersion: 和编译时有关。比如我们当前compileSdkVersion=28(Andorid 9.0),Android 10 新增了有关5G的api。我们的app想尽早使用5G相关的api,这时只需要将compileSdkVersion=29(Android. 阅读详情

为什么要在说权限申请的时候,说targetSdkVersion呢!其实是有原因的,因为目标版本的值的修改,对权限的申请检查是有很大的影响!
例如当targetSdkVersion版本小于23(6.0)的时候,其在编译的时候,不会对权限申请去进行判断,只有在运行过程中才会知道。
当targetSdkVersion大于等于23的时候,就会在编译时候检查代码是否有申请权限的判断。也就会有如下提示:

Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with `checkPermission`) or explicitly handle a potential `SecurityException 

消除这个错误,可以降低targetSdkVersion版本号(<23)或者在具体操作前在进行一次对权限申请的判断即可。(以下代码会有说明)。

说完了targetSdkVersion后,再来说权限申请过程。
权限分为普通权限和危险权限。普通权限在AndroidMainfest中直接申请。
其中所有的普通权限如下:

  • ACCESS_LOCATION_EXTRA_COMMANDS
  • ACCESS_NETWORK_STATE
  • ACCESS_NOTIFICATION_POLICY
  • ACCESS_WIFI_STATE
  • BLUETOOTH
  • BLUETOOTH_ADMIN
  • BROADCAST_STICKY
  • CHANGE_NETWORK_STATE
  • CHANGE_WIFI_MULTICAST_STATE
  • CHANGE_WIFI_STATE
  • DISABLE_KEYGUARD
  • EXPAND_STATUS_BAR
  • GET_PACKAGE_SIZE
  • INSTALL_SHORTCUT
  • INTERNET
  • KILL_BACKGROUND_PROCESSES
  • MODIFY_AUDIO_SETTINGS
  • NFC
  • READ_SYNC_SETTINGS
  • READ_SYNC_STATS
  • RECEIVE_BOOT_COMPLETED
  • REORDER_TASKS
  • REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
  • REQUEST_INSTALL_PACKAGES
  • SET_ALARM
  • SET_TIME_ZONE
  • SET_WALLPAPER
  • SET_WALLPAPER_HINTS
  • TRANSMIT_IR
  • UNINSTALL_SHORTCUT
  • USE_FINGERPRINT
  • VIBRATE
  • WAKE_LOCK
  • WRITE_SYNC_SETTINGS

所有的危险权限:
危险权限需要在使用的时候,才去申请该权限。用户同意就开启,不同意就不能使用该功能!其中运行时权限如下所示:(运行时权限,使用到如下权限,必须进行判断是否有申请权限–分大类)
1.Calendar
2.Camera
3.Contacts
4.Location
5.MICROPhone
6.Phone
7.Sms
8.Sensors
9.Storage
具体细小的分类如下:
这里写图片描述

简单的一个打电话申请权限事例,targetSdkVersion版本在23

        /**
         * 拨打电话
         */
        mCreateDB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 如果没有权限,判断不相等,就去申请权限
                 * Manifest.permission.CALL_PHONE 表示打电话需要申请的权限
                 * 1,表示申请的标示嘛
                 */
                if (ContextCompat.checkSelfPermission(MainActivity.this,
                        Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this,
                            new String[]{Manifest.permission.CALL_PHONE}, 1);
                } else {
                    //有权限,直接呼出去
                    Call();
                }
            }
        });
    }

    private void Call() {
        try {
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10000"));
            /**
             * targetSdkVersion在23时,在具体操作前,会进一步判断是否是否有申请权限
             * 避免程序崩溃,
             */
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //用户同意或者拒绝(动作)后的回调
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case 1:
                //授权的结果会封装在gransResults中
                if(grantResults.length >0 && grantResults[0]==PackageManager.PERMISSION_GRANTED) {
                    Call();
                }else {
                    Toast.makeText(this,"您应该同意该权限",Toast.LENGTH_LONG).show();
                }
                break;
            default:
        }
    }

以上:在用户同意该权限后,下次进来就不需要在申请权限了,如果拒绝该权限后,如果再次想使用该功能,则又会让用户去申请!

如果有多个权限需要用户去申请,我们可以不必一个一个去申请,学习一下向下面的写法:

 //进行运行时权限处理,定义权限集合
        List<String> permissionList = new ArrayList<>();
        //读取手机联系人,需要权限,并添加到权限集合中
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_CONTACTS);
        }
        //地理位置权限
        if (ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(ACCESS_COARSE_LOCATION);
        }
        //申请权限
        if (!permissionList.isEmpty()) {
            //将集合转化成数组
            String[] permissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(this, permissions, 1);
        } else {
            //说明授权了
            readContactData();
        }
 //多个权限响应
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
               if(grantResults.length > 0) {
                    //拒绝权限集合
                    List<String> refusePermissions = new ArrayList<>();
                    for (int i = 0; i < grantResults.length; i++) {
                        int grantResult = grantResults[i];
                        String permission = permissions[i];
                        if(grantResult != PackageManager.PERMISSION_GRANTED) {
                            refusePermissions.add(permission);
                        }
                    }

                    if(refusePermissions.isEmpty()) {
                        //说明都授权了
                           readContactData();
                    }else {
                        //未授权
                    }
                }
                break;
            default:
        }
    }

再高版本的基础库中例如26版本中,是需要实现ActivityCompat.OnRequestPermissionsResultCallback接口,才能有所回调响应
如下图:

public class PermissionContact implements ActivityCompat.OnRequestPermissionsResultCallback{
    private static PermissionContact mPermissionContact;
    private Activity mActivity;
    public  static PermissionContact getInstance() {
        if (mPermissionContact == null) {
            mPermissionContact = new PermissionContact();
        }
        return mPermissionContact;
    }
    public void ApplyPermission(Activity activity) {
        mActivity = activity;
        List<String> permissionList = new ArrayList<>();
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission_group.STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission_group.STORAGE);
        }
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.RECEIVE_SMS);
        }
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.CALL_PHONE);
        }
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if(ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_CONTACTS);
        }

        if(!permissionList.isEmpty()) {
            String[] permissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(activity,permissions,1);
        }else {
            // 说明都授权了

        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1 :
                if(grantResults.length > 0) {
                    //拒绝权限集合
                    List<String> refusePermissions = new ArrayList<>();
                    for (int i = 0; i < grantResults.length; i++) {
                        int grantResult = grantResults[i];
                        String permission = permissions[i];
                        if(grantResult != PackageManager.PERMISSION_GRANTED) {
                            refusePermissions.add(permission);
                        }
                    }

                    if(refusePermissions.isEmpty()) {
                        //说明都授权了
                    }else {
                        //未授权
                            Toast.makeText(mActivity,"拒绝权限",Toast.LENGTH_SHORT).show();

                    }
                }
                break;
        }
    }
}

所以,还是要注意不同版本的区别

或者直接用开源库 Easy Permissions处理权限 或者 Permissions DisPatcher处理
以上:

compileSdkVersion,minSdkVersion,targetSdkVersion 的区别和比较 Android大家都知道的,版本碎片化比较严重,做版本的适配是必须,从而有了下面的这些知识点。 1.compileSdkVersion,minSdkVersion,targetSdkVersion作用和如何选择关系. 2.Support Library 包的选择,v4,v7等包到底是干啥的。 3.我们到底该如何选择这些东西运行项目的时候才能正确运行。   下面我将围绕这些问题和疑问来给大 阅读详情

相关推荐

Android应用防护绕过实战:基于Frida的AutojsPro自动化脚本适配方案

在Android应用自动化测试与脚本开发领域,应用防护机制(如模拟器检测、签名校验、代码混淆)是常见的技术挑战。其核心原理在于应用通过检测运行环境、验证代码完整性等手段,识别并阻止非预期的自动化操作。理解这些防护机制的技术原理,对于开发稳定的自动化脚本、进行安全评估以及学习移动应用逆向工程都具有重要价值。通过动态插桩(Hook)技术,可以在应用运行时拦截和修改关键函数调用,从而实现绕过检测的目的。Frida作为主流的动态Hook框架,提供了强大的JavaScript API,能够在不修改源码的情况下,实时监

weixin_30781433的博客 471

详解 MinSdkVersion、CompileSdkVersion、TargetSdkVersion 三者的区别、作用与关系(超详细图文教程)

对 Android 项目来说,MinSdkVersion、CompileSdkVersion、TargetSdkVersion 这三个属性是必不可少的,贯穿于应用开发的始终,它们的作用也非常重要,只有搞清楚它们三者的内在含义和逻辑关系才能「正确」地设定或修改它们的数值,以确保应用在不同版本的 Android 系统上正常的运行。用较低的 minSdkVersion 来覆盖最大的人群,用最新的 SDK 设置 targetSdkVersion 和 compileVersion 来获得最好的外观和行为。

指尖流连敲击梦想,代码行行承载远方! 2万+

Android——《Android第一行代码》10.6节服务的最佳实践,应用8.0以上Android系统需要修改的地方

【背景】:参照书籍写的代码,辛苦写完,分析完原理,运行起来确有很多,解决这些问题,查了大量的资料,走了很多弯路,最后仅通过一个基本知识点解决,写在这里,记录下来,后来者参考了,少走些弯路。 【问题】:先从遇到的问题说起 1、程序运行,直接闪退。 ——Android 8.0以上系统使用通知,需要添加渠道,详见另一篇博文。 2、刚运行,没有操作别的,就出现异常卡死问题,再次打开APP,开始下载...

数字世界 万物互联 1259

Android之targetSdkVersion详解

Google 官方发布文章解析 compileSdkVersion、minSdkVersion 以及 targetSdkVersion 的含义,以及合理设置各个值的意义,原文Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion(后面简称 “原文”),还有翻译版。 其中,compileSdkVersion 和 mi...

LVXIANGAN的专栏 1万+

Drupal远程代码执行漏洞(CVE-2018-7600)实战复现:从检测到写入WebShell的全过程

本文详细解析了Drupal远程代码执行漏洞(CVE-2018-7600)的实战复现过程,从环境搭建、漏洞检测到WebShell写入的全流程。该高危漏洞影响Drupal 6.x至8.x版本,允许攻击者未经授权执行任意代码。文章提供了多种POC构造方法和高级利用技巧,帮助安全研究人员深入理解漏洞原理并掌握验证技术。

weixin_29322553的博客 275

图形学基础知识:着色(三)Rendering Pipeline与Shader

管线(Pipeline) 什么是管线? 管线我们可以理解为流水线,流水线大家都懂,就是工厂里面生产东西的一整套流程。例如饮料厂要生产饮料,需要洗瓶子,倒饮料,加盖,包装等等,这一整套过程就是流水线。那么我们要把一个三维场景渲染成一幅二维的图像,同样需要一个先干嘛再干嘛然后干嘛最后干嘛的过程,这个过程或流水线,我们就称之为管线。 实时渲染管线(Real-time Rendering Pipeline) 通过前面几篇的学习,我们知道了要把一个三维场景渲染成一幅二维的图像大致分为以下几个步骤: M.

王王王渣渣的博客 2532

Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?

上一篇所说内容是所有 App 安装到 Android14 设备上的影响和需要注意的内容,本篇接下来就要介绍当 targetSdkVersion 升级到 34 时,App 需要注意和修改的地方。1. 核心功能变更1.1 前台服务类型在 targetSdkVersion >= 34 的情况下,必须为应用内的每个前台服务(Foreground Service)指定至少一种前台服务类型。什么是前台服务?

weixin_42504805的博客 5705

【CMU-自主导航与规划】Autonomous Exploration Development Environment 实战:从环境搭建到多场景测试

本文详细介绍了CMU开源自主导航开发环境(Autonomous Exploration Development Environment)的实战部署与测试。内容涵盖从Ubuntu与ROS环境搭建、仿真场景配置,到核心导航模块(地形分析、局部避障、航点跟踪)的深度解析,并演示了如何集成TARE探索与FAR规划等上层算法,最终指导连接真实SLAM与实车部署,完成多场景性能评估。

weixin_29215391的博客 706

Android targetSdkVersion你真的了解吗?

先抛出一个问题: 我们的应用开发的时候android最新版本是6.0,当一年过去之后,7.0发布了,那么我们的应用在7.0手机上是否还能运行?会奔溃吗? 根据我们的实际经验,觉得应该不会奔溃,可能有些功能会有问题,但是具体是那一块呢?又说不太好,这就涉及到了Android的向前兼容的问题了。 我们在创建App的时候经常会设置这几个参数 android { ...

Mr.SSY的博客 8万+

国产信创麒麟操作系统 (kylin v10 x86架构) 离线安装nginx步骤(亲测,超详细步骤)、修改nginx配置文件、启动、重启、关闭nginx记录(亲测有效)

国产信创麒麟操作系统 (kylin v10 x86架构) 离线安装nginx步骤(亲测,超详细步骤)、修改nginx配置文件、启动、重启、关闭nginx记录(亲测有效)

qq445829096的博客 2766

ABAP RANGES及比较符号

RANGES *选项介绍: *1.SIGN 值为 I 和 E 。 I是包含, E是排除, 一般使用I。 2.OPTION 如果HIGH 为空 ,为单值选择 。有 EQ、NE、GT、LE、LT等逻辑操作 对于的 CP包含 NP是排除 如果HIGH 不为空 为区间选择 有BT,NB可选 *3.LOW 低值 *4.HIGH 高值 lt:less than 小于 le:less than or equal to 小于等于 eq:equal to 等于 ne:

Pegasus666的博客 5389

28、compileSdkVersion,minSdkVersion,targetSdkVersion 的区别和比较

28、compileSdkVersion,minSdkVersion,targetSdkVersion 的区别和比较 https://blog.youkuaiyun.com/lanxuan1993/article/details/84975565 1.compileSdkVersion,minSdkVersion,targetSdkVersion作用和如何选择关系. 2.Support Library 包的选择,v4,v7等包到底是干啥的。 3.我们到底该如何选择这些东西运行项目的时候才能正确运行。 下.

kuangben2000的博客 529

OceanBase数据库:从入门到精通全栈教程目录(含架构解析、性能调优与实战案例)

《OceanBase数据库专栏》全面解析蚂蚁集团自主研发的分布式关系型数据库,涵盖从基础到高级的完整知识体系。专栏分为入门篇、原理篇、使用篇等七大模块,包含35+篇深度文章,详细讲解OceanBase的高可用架构、Paxos协议、LSM树存储引擎等核心技术。特别提供MySQL/Oracle迁移指南、金融/电商场景实践案例,以及性能调优、运维监控等实战内容。适合开发者、DBA及架构师快速掌握OceanBase的核心特性和行业应用,助力企业实现数据库分布式转型。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 982

AndroidMenifest.xml中minSdkVersion、targetSdkVersion、targetApiLevel的区别

在AndroidMenifest.xml中,常常会有下面的语句: &lt;uses-sdk android:minSdkVersion="4" android:targetSdkVersion="10" android:maxSdkVersion="10" /&gt; 在default.properties中,会看到下面的语句: target=android-10 如果是使用Eclipse的话,...

学习笔记 73

手把手教你学Simulink——逆变器场景:基于PR控制器的单相逆变器并网控制策略仿真

摘要:本文详细介绍基于PR控制器的单相逆变器并网控制策略的Simulink仿真实现。首先分析PR控制器在单相逆变应用中的优势,然后逐步讲解模型搭建过程,包括主电路设计(直流电源、全桥逆变器、L滤波器)、控制回路实现(参考电流生成、坐标变换、PR控制器设计)以及关键参数设置。通过仿真验证了PR控制器对电网频率的精确跟踪能力,并网电流THD<3%。最后提出优化建议,如加入状态观测器、自适应参数整定等改进方向。该建模方法为可再生能源系统中的逆变器控制提供了有效验证手段。

MHD0815的博客 497

c++中,部署Ethercat IGH + PREEMPT_RT 环境,跑DC模式,如何实现?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1357

如何选择 compileSdkVersion, minSdkVersion 和 targetSdkVersion

英文原文:Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion当你发布一个应用之后,(取决于具体的发布时间)可能没过几个月 Android 系统就发布了一个新版本。这对你的应用意味着什么,所有东西都不能用了?别担心,向前兼容是 Android 非常关注的事情。用户在升级到新版 Android 的时候,用以前版本的 S...

顾曲周郞的博客 433

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

compileSdkVersion,minSdkVersion,targetSdkVersion作用和如何选择关系

文章地址[:http://www.jianshu.com/p/72d311d72fcb] 1.compileSdkVersion,minSdkVersion,targetSdkVersion作用和如何选择关系.2.Support Library 包的选择,v4,v7等包到底是干啥的。3.我们到底该如何选择这些东西运行项目的时候才能正确运行。下面我将围绕这些问题和疑问来给大家一步步讲解他们的关系。一

赏金猎人 510

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Android 6.0 动态权限Permission相关

随着Android 6.0发布以及普及,我们开发者所要应对的主要就是新版本SDK带来的一些变化,首先关注的就是权限机制的变化。对于6.0的几个主要的变化,查看查看官网的这篇文章http://developer.android.com/intl/zh-cn/about/versions/marshmallow/android-6.0-changes.html,其中当然包含Runtime Permis...

qianshanyany的博客 210

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Andriod 6.0 动态权限Permission相关

Andriod 6.0 动态权限Permission相关随着Android 6.0发布以及普及,我们开发者所要应对的主要就是新版本SDK带来的一些变化,首先关注的就是权限机制的变化。

yeyu_wuhen的博客 549

Android版本差异适配方案(5.0-11.0)

Android版本差异适配方案(5.0-9.0) 一个好的APP最好支持90%设备,由于不同版本系统提供的API可能不同,所以了解不同版本间系统差异很重要,这样才能更好的适配更多的智能设备。你的应用足不足够健壮要看你的应用在主流版本运行是否流畅。这篇文章记录开发过程中遇到的相对重要以及常用的适配方案,希望对读者有所帮助。 Android 版本号及对应的版本名 版本号 版本名 中文名 ...

博由心生,福泽一生 6715

2026年C语言零基础入门:从环境搭建到实战项目全攻略

C语言作为一门通用、过程式的计算机编程语言,其核心价值在于提供了对计算机底层硬件和内存的直接控制能力。理解其工作原理,如指针、内存管理和函数调用栈,是掌握系统编程、性能优化和深入理解高级语言运行机制的基础。在系统编程、嵌入式开发、游戏引擎和高性能计算等对效率和底层控制有严苛要求的应用场景中,C语言依然是不可替代的基石。本教程正是围绕这些核心概念,结合2026年的现代开发环境,为初学者设计了一条从零开始的清晰学习路径,涵盖了环境搭建、核心语法精讲、指针难点剖析,并最终通过一个学生成绩管理系统实战项目,将函数、

weixin_34409357的博客 357
上一篇: android 安装apk对不同版本的要求
下一篇: 接入腾讯应用宝(YSDK)注意事项
掉头发程序员
博客等级 码龄10年 40粉丝 138原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值