Android清单文件详解(二) ---- 应用程序权限声明(一)

简介: Android清单文件详解(二) ---- 应用程序权限声明(一)

我们知道,Android系统的各个模块提供了非常强大的功能(比如电话,电源和设置等),通过使用这些功能,应用程序可以表现的更强大,更灵活。不过,使用这些功能并不是无条件的,而是需要拥有一些权限。接下来,我们就开始讲解另一个非常重要的知识点——应用程序权限声明,其中主要包括应用程序的权限声明,自定义应用程序的访问权限和SDK版本限定。


1.<uses-permission>——应用程序的权限申请


权限

描述
android.permission.ACCESS_NETWORK_STATE 允许应用程序访问网络状态
android.permission.ACCESS_WIFI_STATE 允许应用程序访问WI-FI状态信息
com.android.voicemail.permission.ADD_VOICEMALL 允许应用程序往系统中添加一封语音邮件
android.permission.BATTERY_STATS 允许应用程序更新手机电池统计信息
android.permission.BIND_APPWIDGET 允许应用程序通知AppWidget服务哪个应用程序可以访问AppWidget的数据
Launcher是使用此权限的一个实例
android.permission.BLUETOOTH 允许应用程序连接一个已经配对的蓝牙设备
android.permission.BLUETOOTH_ADMIN 允许应用程序主动发现和配对蓝牙设备
android.permission.BROADCAST_PACKAGE_REMOVED 允许医用程序发送应用程序包已经卸载的通知
android.permission.BROADCAST_SMS 允许应用程序广播短信回执通知
android.permission.BROADCAST_STICKY 允许应用程序广播Sticky Intent。
有些广播的数据在其广播完成后被放在系统中,这样应用程序可以快速访问它们的数据,而无需等到下一个广播到来
android.permission.CALL_PHONE 允许应用程序初始化一次电话呼叫
android.permission.CAMERA 请求访问摄像设备
android.permission.CHANGE_CONFIGURATION  允许应用程序修改当前的配置,比如语言种类,屏幕方向等。比如,我们的设置模块就使用了这个权限
android.permission.CHANGE_NEWWORK_STATE 
允许应用程序改变连接状态
android.permission.CHANGE_WIFI_STATE 允许应用程序改变WI-FI连接状态
android.permission.DEVICE_POWER 允许应用程序访问底层设备电源管理
android.permission.EXPAND_STATUS_BAR 允许应用程序展开或者收起状态栏
android.permission.INSTALL_LOCATION_PROVIDER      允许应用程序安装一个数据提供者到本地管理器中
android.permission.INSTALL_PACKAGES 允许应用程序安装另一个应用程序
android.permission.INTERNET 允许应用程序打开网络。
如果希望开发一个和网络相关的应用程序,那么首先应该考虑是否需要这个权限
android.permission.KILL_BACKGROUND_PROCESSES  允许应用程序调用killBackgroundProcesses()方法
android.permission.MODIFY_PHONE_STATE 允许修改电话状态,但不包括拨打电话
android.permission.MOUNT_FORMAT_FILESYSTEMS 允许应用程序格式化可移除的外部存储设备
android.permission.MOUNT_UNMOUNT_FILESYSTEMS 允许应用程序挂载或者卸载外部存储设备
android.permission.NFC 允许应用程序执行NFC的输入输出操作
android.permission.READ_CALENDAR 允许应用程序读取日历的数据
android.permission.READ_CONTACTS 允许应用城西读取联系人的数据
android.permission.READ_PHONE_STATE 允许应用程序访问电话状态
android.permission.READ_SMS 允许应用程序访问短信信息
android.permission.RECEIVE_BOOT_COMPLETED 允许应用程序在系统完成以后接受到android.intent.action.BOOT_COMPLETED广播
android.permission.RECEIVE_MMS 允许应用程序监控MMS
android.permission.RECEIVE_SMS 允许应用程序监控SMS
android.permission.RECEIVE_WAP_PUSH 允许应用程序监控WAP的推送信息
android.permission.SEND_SMS 允许应用程序主动发送短息
android.permission.SET_TIME 允许应用程序设置系统时间
android.permission.SET_TIME_ZONE 允许应用程序设置系统时区
android.permission.SET_WALLPAPER 允许应用程序设置桌面壁纸
android.permission.STATUS_BAR 允许应用程序操作(打开,关闭,禁用)状态栏和它的图标
android.permission.VIBRATE

允许应用程序允许应用程序访问振动设备

android.permission.WAKE_LOCK 允许应用程序使用电源管理器的屏幕锁功能
android.permission.WRITE_CALENDAR 允许用户写入日历数据。如果我们只申请了这个权限,那么我们对日历的数据只有写权限没有读权限
android.permission.WRITE_CONTACTS 允许用户写入联系人数据,如果我们只申请了这个权限,那么我们对联系人的数据只有写入权限,没有读权限
android.permission.WRITE_EXTERNAL_STORAGE 允许应用程序把数据写入外部存储设备
android.permission.WRITE_SETTINGS 允许应用程序读写系统设置
android.permission.WRITE_SMS 允许应用程序写短信


应用程序在不同的场景下可能需要上表所示的某些权限,比如当我们需要使用SD卡时,则需要申请SD卡相关权限。下面我们举例来解释这个问题。


在这个实例中,我们将改造HelloWorld应用程序,并在sdcard的根目录下添加一个名为“abc.txt”的文本文件。由于需要访问外部存储设器,因此需要申请android.permission.WRITE_EXTERNAL_STORAGE权限,否则代码将会失败。具体步骤如下所示。


①需要在HelloWorld应用程序的AndroidManifest.xml文件中添加相应的权限,如下列代码所示:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


②要在原来的代码中添加一些创建文件的代码,如下所示:


public class MainActivity extends FragmentActivity {
    private static final String SDCARD= Environment.getExternalStorageDirectory()+File.separator;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(savedInstanceState==null){
            getSupportFragmentManager().beginTransaction().add(android.R.id.content,new FileFragment()).commit();
        }
    }
    public static class FileFragment extends Fragment {
        public FileFragment(){}
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view=inflater.inflate(R.layout.file_fragment,container,false);
            Button mybut= (Button) view.findViewById(R.id.mybut);
            mybut.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    File sdcardFile=new File(SDCARD+"abc.txt");
                    try {
                        sdcardFile.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            return view;
        }
    }
}


③启动程序,这时在sdcard所链接的目录下,我们会发现已经建立了abc.txt文件,如下图所示。

53.png

最后我们来做一个实验,将AndroidManifest.xml文件中的<uses-permission>节点删除,在相同的目录下并没有发现所创建的文件,这样操作之后,我们就能在日志里面发现一些异常信息,如下图所示。

54.png

从日志中我们可以发现程序抛出了java.io.IOException异常,并且提示“Permission denied”,而它发生的地方,正好是创建文件的地方。因此,我们可以得出一个结论,在试图读写外部存储设备的时候,必须先要申请android.permission.WRITE_EXTERNAL_STORAGE这个权限,否则程序抛出警告性异常,相关操作也就无法进行。


Android提供了丰富的软硬件功能模块,它能让应用程序变得强大,开发过程也更便捷,但在使用前,必须要为应用程序申请必要的权限。这点非常重要,否则应用程序就会出现莫名其妙的错误。


正如前面的实例中看到的结果,如果没有相应的权限,就无法创建文件,而程序并没有显示一个异常的提示,这时我们就可能要花费大量的时间去找问题的根源。


因此,本人建议大家开发之前仔细分析需求,分析应用为什么功能,而这些动能是否需要权限才可以访问。


2.<permission>节点——自定义应用程序的访问权限


前面我们学习了如何使用权限。其实,应用程序除了可以使用权限之外,还可以定义自己的权限,用来限制对本应用程序或其他应用程序的特殊组件或功能访问。在这里,我们来学习<permission>节点的作用——如何声明自己的权限。


手动向AndroidManifest.xml文件中添加一个<permission>节点,它只能包含在<manifest>节点下,其语法如下所示:

<permission android:description="string resource"
android:icon="drawable resource"
android:logo="drawable resource"
android:label="string resource"
android:name="string"
android:permissionGroup="string"
android:protectionLevel=["normal"|"dangerous"|"signature"|"signatureOrSystem"]/>


以上代码中,需要说明的有以下3个属性。


①android:name:声明权限的名称。这个名称必须是唯一的,因此,应该使用Java风格的命名,比如com.test.permission.TEST。


②android:permissionGroup:声明权限从属于哪一个权限组,这个权限组可以是Android预编译的,也可以是自定义的。下表列除了Android系统预编译的系统权限组。

权限组名称

描述
android.permission-group.ACCOUNTS 用于直接访问由帐号管理器管理的帐号
android.permission-group.COST_MONEY 用于使用户不需要直接参与就可花钱的权限
android.permission-group.DEVELOPMENT_TOOLS 与开发特征相关的权限群
android.permission-group.HARDWARE_CONTROLS 用于提供直接访问设备硬件的权限
android.permission-group.LOCATION 用于允许用户访问用户当前位置的权限
android.permission-group.MESSAGES 用于允许应用程序以用户的名义发送信息或者拦截用户收到的信息的权限
android.permission-group.NETWORK 适用于提供网络服务的访问权限
android.permission-group.PERSONAL_INFO 适用于提供访问到用户私人数据的权限,如联系人,日历事件和电子邮件信息
android.permission-group.PHONE_CALLS 适用于关联访问和修改电话状态的权限,比如拦截去电,读取和修改电话的状态
android.permission-group.STORAGE 与SD卡访问有关的权限组
android.permission-group.SYSTEM_TOOLS 与系统API有关的权限组


③android:protectionLevel:描述了隐含在权限中的潜在风险,该属性的值可以是下表中的一个字符串。


意义
normal 默认值。低风险的权限,它可以使请求的应用程序访问孤立的应用程序级的功能,给其他应用程序,系统或者用户带来最小的风险。系统在安装时,会自动授予这种类型的权限给请求的应用程序,无须用户明确声明。
dangerous

高风险权限,它将事请求的应用程序能访问用户的私有数据或者控制那些会对用户产生负面影响的设备。由于这种权限存在潜在的风险,系统可能不会自动被赋予请求的应用程序。例如,任何一个由应用程序请求的危险权限可能会显示给用户,并且在处理之前被要求确认。例如,以下权限就属于此类权限。

<permission android:name="android.permission.RECEIVE_SMS"

android:permissionGroup="android.permission-group.MESSAGES"

android:protectionLevel="dangerous"/>

如果应用程序使用了这个权限,就有可能导致其他应用程序无法收到短信通知,此时我们认为使用这种权限是危险的。

signature 签名级别。系统只在请求的应用程序用同样的签名作为声明权限时才授予该权限。如果认证匹配,则系统不通知用户或者无须用户明确批准就可以自动授权。
  signatureOrSystem  

签名或者系统级别。系统仅仅将它授给Android系统镜像文件(*.img文件)中的应用程序,或者是和系统镜像中的那些用同样认证签名的应用程序。一般情况下,尽量避免使用该选项,这是由于signature保护层级应满足大多数需求和工程,而不管应用程序被确切地安装在何处。signatureOrSystem权限适用于特定的特殊环境,在这样的环境里,多个厂商已经将应用程序构建到系统镜像中,并且需要明确共享特定特征。


在<permission>节点中,除了上面介绍的3个属性外,还有其他一些属性只是为了便于阅读而存在,这里我们不在详细介绍。


在Android系统提供的应用程序中,有一些定义了自己的权限,比如Launcher。下面的代码片段用Launcher 的AndroidManifest.xml片段来说明如何手动声明自己的权限:

<permission 
android:name="com.android.launcher.permission.INSTALL_SHORT-CUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
android:label="@string/permlab_install_shortcut"
android:description="@string/perdesc_install_shortcut"/>


因为声明权限这一功能使用频率比较低,因此读者在开发应用程序的时候需要思考是否有必要声明自己的权限。

相关文章
|
24天前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
5天前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
6天前
|
存储 搜索推荐 Java
打造个性化安卓应用:从设计到实现
【10月更文挑战第30天】在数字化时代,拥有一个个性化的安卓应用不仅能够提升用户体验,还能加强品牌识别度。本文将引导您了解如何从零开始设计和实现一个安卓应用,涵盖用户界面设计、功能开发和性能优化等关键环节。我们将以一个简单的记事本应用为例,展示如何通过Android Studio工具和Java语言实现基本功能,同时确保应用流畅运行。无论您是初学者还是希望提升现有技能的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧。
|
9天前
|
搜索推荐 开发工具 Android开发
打造个性化Android应用:从设计到实现的旅程
【10月更文挑战第26天】在这个数字时代,拥有一个能够脱颖而出的移动应用是成功的关键。本文将引导您了解如何从概念化阶段出发,通过设计、开发直至发布,一步步构建一个既美观又实用的Android应用。我们将探讨用户体验(UX)设计的重要性,介绍Android开发的核心组件,并通过实际案例展示如何克服开发中的挑战。无论您是初学者还是有经验的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧,帮助您在竞争激烈的应用市场中脱颖而出。
|
11天前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
25 2
|
15天前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
43 5
|
15天前
|
移动开发 Dart 搜索推荐
打造个性化安卓应用:从零开始的Flutter之旅
【10月更文挑战第20天】本文将引导你开启Flutter开发之旅,通过简单易懂的语言和步骤,让你了解如何从零开始构建一个安卓应用。我们将一起探索Flutter的魅力,实现快速开发,并见证代码示例如何生动地转化为用户界面。无论你是编程新手还是希望扩展技能的开发者,这篇文章都将为你提供价值。
|
24天前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
40 4
|
24天前
|
编解码 Android开发 UED
构建高效Android应用:从内存优化到用户体验
【10月更文挑战第11天】本文探讨了如何通过内存优化和用户体验改进来构建高效的Android应用。介绍了使用弱引用来减少内存占用、懒加载资源以降低启动时内存消耗、利用Kotlin协程进行异步处理以保持UI流畅,以及采用响应式设计适配不同屏幕尺寸等具体技术手段。
47 2
|
1月前
|
JSON API Android开发
探索安卓开发之旅:打造你的第一个天气应用
在这篇文章中,我们将一起踏上一段激动人心的旅程,学习如何在安卓平台上开发一个简单的天气应用。通过实际操作和代码示例,我们将逐步构建一个能够显示当前位置天气情况的应用。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供清晰的指导和启发性的见解,帮助你理解和掌握安卓开发的基础知识。让我们一起探索代码的世界,解锁新技能,实现你的创意和梦想。
下一篇
无影云桌面