Android清单文件详解(二) ---- 应用程序权限声明(安卓中的清单文件)

网友投稿 1073 2022-05-30

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

1.——应用程序的权限申请

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

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

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

Android清单文件详解(二) ---- 应用程序权限声明(安卓中的清单文件)

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

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文件,如下图所示。

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

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

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

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

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

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

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

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

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:protectionLevel:描述了隐含在权限中的潜在风险,该属性的值可以是下表中的一个字符串。

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

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

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"/>

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

3.节点——SDK版本限定

大家都知道,软件对于平台版本是的一定要求的。如果平台版本能够达到软件运行的要求,那就能保证软件的稳定性。比如,大家都知道NFC功能是不能在Android 1.5中运行的,如果正在开发带类似功能的应用程序,那就必须对所在平台有所要求,而节点正是用来满足这种需求的。

节点使用一个整型值来表达应用程序与一个或多个Android平台版本的兼容性。值得注意的是,这些整型值代表的是API级别。应用程序给定的API级别将和一个给定Android系统的API级别做比较。当然,对于不同的Android设备,这可能会有所不同。需要说明的是,这个节点用于指定API级别,而不是用于指定SDK的版本号或Android平台的。

使用此节点的代码如下所示:

android:targetSdkVersion="integer"

android:maxSdkVersion="integer"/>

①android:minSdkVersion:用于指定要运行应用程序所需的最小API级别。如果系统的API级别比该属性指定的值要小,则Android系统会阻止用户安装此应用。在大多数情况下,应指定这个属性。如果没有指定该属性,那么系统会认为此属性值为“1”。

②android:targetSdkVersion:用于指定应用程序的目标API级别。

③android:maxSdkVersion:指定最大的API级别。

4.节点——应用的监控器

节点用于监控应用程序与系统交互,它会在应用程序组件实例化之前被实例化。这个节点在多数情况下用于单元测试。其语法结构如下:

android:handleProfiling=["true"|"false"]

android:icon="drawable resource"

android:label="string resource"

android:name="string"

android:targetPackage="string">

下面详细说明这些属性:

①android:functionalTest:标识这个Instrumentation类是否作为一个功能测试运行,它的默认值是false。

②android:handleProfiling:标识这个Instrumentation对象是否打开和关闭性能分析,它的默认值是false。

③android:icon:这个属性代表这个Instrumentation类的图标

④android:label:该属性是Instrumentation类的标题。

⑤android:name:该属性是Instrumentation子类的名称,是一个类的Java风格的名称,例如com.example.liyuanjinglyj.myInstrumentation。

⑥android:targetPackage:该属性是需要监控的目标应用程序名称,这个名称来自与目标应用程序AndroidManifest.xml中节点的package属性值。

当然在eclipse需要专门创建一个测试项目,而且还要配置这个节点,但是在android studio并不需要这么做,考虑到2015年底谷歌不再支持eclipse,所以只讲解android studio单元测试,而讲解这个节点是因为到现在eclipse依然有大量的开发者使用,所以,讲解了节点的详细说明。

下面举例说明如何进行单元测试:

①创建项目,依然拿我们一直使用的HelloWorld做实验,你会发现项目目录里面有这样一个测试包:

②右键点击这个包,选择NEW-CLASS菜单项,新建MyFirstTest继承自ActivityInstrumentationTestCase2,如下图所示:

package com.example.liyuanjing.helloworld; import android.test.ActivityInstrumentationTestCase2; /** * Created by liyuanjing on 2015/7/14. */ public class MyFirstTest extends ActivityInstrumentationTestCase2{ public MyFirstTest(){ super(MainActivity.class); } }

在这段代码中,ActivityInstrumentationTestCase2中的要换成我们测试的类,因为我们要测试MainActivity所以换成这个。

③我们测试内容为,在编辑框中输入一些字符,当点击按钮后,文本框等于编辑框输入的字符串,MainActivity代码如下:

public class MainActivity extends FragmentActivity { private static final String SDCARD= Environment.getExternalStorageDirectory()+File.separator; private FileFragment fileFragment=new FileFragment(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(savedInstanceState==null){ getSupportFragmentManager().beginTransaction().add(android.R.id.content,fileFragment).commit(); } } public static class FileFragment extends Fragment { private View mRootView; public FileFragment(){} @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view=inflater.inflate(R.layout.file_fragment,container,false); final EditText myEdit=(EditText)view.findViewById(R.id.myEdit); final TextView content=(TextView)view.findViewById(R.id.content); Button myBut=(Button)view.findViewById(R.id.myBut); myBut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { content.setText(myEdit.getText().toString()); } }); this.mRootView=view; return view; } public View getRootView(){ return this.mRootView; } } public FileFragment getFragment(){ return fileFragment; } }

测试类的代码如下:

public class MyFirstTest extends ActivityInstrumentationTestCase2{ private TextView content; private EditText myEdit; private Button myBut; private MainActivity mainActivity; public MyFirstTest(){ super(MainActivity.class); } @Override protected void setUp() throws Exception { super.setUp(); this.mainActivity=(MainActivity)getActivity(); this.content=(TextView)this.mainActivity.getFragment().getRootView().findViewById(R.id.content); this.myEdit=(EditText)this.mainActivity.getFragment().getRootView().findViewById(R.id.myEdit); this.myBut=(Button)this.mainActivity.getFragment().getRootView().findViewById(R.id.mybut); } public void testButtonClick(){ getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_H); getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_E); getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_L); getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_L); getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_O); getInstrumentation().waitForIdleSync(); getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { myBut.performClick(); } }); getInstrumentation().waitForIdleSync(); SystemClock.sleep(1000); assertEquals(this.content.getText().toString(),this.myEdit.getText().toString()); } }

注意:

Ⅰ在MyFirstTest类的构造放中,由于指定了被测试项目的Activity的详细信息,就使得MyFirstTest与Activity关联上。

ⅡsetUp()方法是一个重写的方法,它的作用是在测试前做必要的设置,比如实例化一些对象,打开网络等,它与tearDown()方法成对出现。这里我们没有实现tearDown()方法,当测试完成以后,框架会自动回调基类,也就是tearDown()方法。

最后,运行测试类,如下图所示:

当系统完成测试后,就可以在Android studio集成开发环境中得到下图所示的结果:

在图中可以看到,编写的Test测试类返回值为OK,这就证明测试达到了预期的目的。

Android 网络

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《考取HCIA证书看我就够了》第四篇:[HCIA-IoT]物联网技术之平台层技术概览
下一篇:【IDA-3D 解读】基于实例深度感知的自动驾驶立体视觉三维目标检测(ID/IDA)
相关文章