Android学习笔记(五十):声明、请求和检查许可

基于安全需求,应用对Android系统提供的content provider或者service的访问需要在安装时进行许可,这就是AndroidManifest.xml文件中的permission中声称,之前已经很多例子。同样如果其他应用要访问我们的数据,我们也可以要求这些应用必须获得用户授权方可访问我们的数据。

申请授权:请求permission

申请许可的格式为

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

Android系统所提供的均已android.permission开头,具体的定义参见reference中Manifest.permission的定义。例如INTENET,WRITE_EXTERNAL_STORAGE, ACCESS_COARSE_LOCATION(粗定位)、ACCESS_FINE_LOCATION,CALL_PHONE。第三方应用将有他们定义自定义的许可。

在安装的时候,系统会提示用户是否同意许可。但是如果通过USB安装,即开发模式,系统将不会出现提示。如果用户不授权,将不被安装和运行。如果在AndroidMenifest.xml中忘了申请授权,则会抛出SecurityException的异常信息。

要求访问者须获得授权:声明permission

如果应用有content provider或者服务,例如按有私人信息,基于安全,同样可要求对其他程序访问进行安全控制。声明permission比请求要复杂些,如下:

<!-- 包括三个部分:(1)android:name,为了避免出现冲突,使用应用的Java的命名空间作为前缀 -->
<permission android:name="com.wei.android.learning.READ_GRAVITY"
                     <!-- permission的标签说明,简单明了 -->
                     android:label="@string/read_gravity_label"
                     <!-- 对permission的进一步说明,比标签要长和详细 -->
                     android:description="@string/read_gravity_description" />

上面只是对这是个可能的permission进行定义,要真正起到保护还需要近一步声明在那里需要保护,可以通过下面两种方式之一。

方式一:在AndroidManifest中表明要求强制许可

这种方式简单。如果对于provider,有readPermission和writePermission,我们在上面已经将读的许可进行了定义,可以被外部引用。例子如下:

<provider android:name=".GravityProvider" android:authorities="com.wei.android.learning.provider"
  android:readPermission="com.wei.android.learning.READ_GRAVITY"
  android:writePermission="com.wei.android.learning.WRITE_GRAVITY" />

若某个应用要通过这个content provider访问数据,如果忘了在manifest中请求许可,运行则会报错,如下图所示。

为了访问该content provider,应用应在manifest中申请许可,在安装时,用户授权后,才能有权限通过该provider来读取信息。本例如下:

<uses-permission android:name="com.wei.android.learning.READ_GRAVITY" />

除了provider之外,activity,service,receiver都可以申明要求许可,增加参数android:permission即可,以activity为例,如下:

<activity  android:name=".xxxxx"  android:label="yyyyyy"  android:permission="com.wei.android.learning.MY_PERMISSION">
  <intent-filter>     … …   </intent-filter> 
</activity>

对于安全架构而言,如果要求了声明了permission,对于activity,没有许可,则无法启动该activity;对于service,没有许可,则无法启动、停止、绑定activity;对于Intent receiver,没有许可,则会忽略通过sendBroadcast( )发送的消息。

方式二:在代码中声明

我们也可以在代码中要求检查权限。请注意,仍需在manifest中对权限进行声明。我们仍以content Provider为例子。我们首先在manifest中声明一个新的permission:<user-permission andriod:name="com.wei.android.learning.MYTEST">。我们将在读数据时进行检查。

public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder){ 
    if ( getContext().checkCallingPermision(“com.wei.android.leanring.MYTEST”) !=PackageManager.PERMISSION_GRNTED )  
       throw new SecurityException(“Required <com.wei.android.learning.MYTEST> Permission”);
    } 
    … … 
}

也可用于service,或者在sendBroadcast( )中进行检查。对于service,如果提供多种级别的权限,例如只读,读写,我们可以在代码中根据权限的级别进行处理,而在manifest中只能提供一种权限,对于多种权限,考虑在代码中区分。对于sendBroadcast( ),如果没有获得权限,则不能接收该广播消息。

一些注意

由于是否获得许可不是在编译时检查,而是在运行是发现,如果我们提供的API要求许可,包括content provider,service,将被其他activity调取的intent,都应当在文档中声明。另外,我们也应当详细告知用户,使他们在安装时给予许可。这也就是为何在permission声明中使用了@string/xxxx的方式,方便多国语言的使用。

Android系统有时会增加一些许可,而之前版本是没有,这会造成以前编写程序的许可授权问题。Android的解决方式如下,在manifest中定义最新版本x:<uses-sdk android:minSdkVersion="x">,例如x=3,表明应用定义的最低版本为Android 1.5版本,那么在安装时,系统自动将以后增添的许可全列上,请求用户授权。

Android的许可方式也有一定的限制。例如所有的许可必须在安装时被授权,哪怕极少使用到的许可,不能在以后授权;用户授权只能同意或者不同意,没有可选的授权方式,例如授权一部分,不授权另一部分。

时间: 2024-10-16 11:14:58

Android学习笔记(五十):声明、请求和检查许可的相关文章

Android学习笔记(十五)——碎片的生命周期(附源码)

碎片的生命周期 点击下载源码 与活动类似,碎片具有自己的生命周期.理解了碎片的生命周期后,我们可以在碎片被销毁时正确地保存其实例,在碎片被重建时将其还原到前一个状态. 1.使用上一篇的项目Fragments,在Fragment1.java文件中添加如下代码: package net.zenail.Fragments; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragm

Android学习笔记二十五之ListView多布局实现

Android学习笔记二十五之ListView多布局实现 这一节是介绍ListView这个控件的最后一节,实现一个Item的多布局.像我们经常在用的各种即时通讯工具,QQ.微信等,假设他们的会话界面是ListView实现的,那么ListView就有多种Item布局,这一节,我们就来实现一个ListView的多种Item. 要实现ListView里面有多种Item,就要重写适配器的两个方法getViewTypeCount()和getItemViewType(int position),第一个方法是

Android学习笔记二十九之SwipeRefreshLayout、RecyclerView和CardView

Android学习笔记二十九之SwipeRefreshLayout.RecyclerView和CardView 前面我们介绍了AlertDialog和几个常用的Dialog,ProgressDialog进度条提示框.DatePickerDialog日期选择对话框和TimePickerDialog时间选择对话框.这一节我们介绍几个新的API控件SwipeRefreshLayout.RecyclerView和CardView,这几个API控件都是google在Android5.0推出的.下面我们来学

Android学习笔记二十之Toast吐司、Notification通知、PopupWindow弹出窗

Android学习笔记二十之Toast吐司.Notification通知.PopupWindow弹出窗 Toast吐司 Toast吐司是我们经常用到的一个控件,Toast是AndroidOS用来显示消息的一种机制,它与Dialog不同,Toast不会获取到焦点,通常显示一段时间之后就会自动消失,下面我们来介绍Toast的几种常用方式: 第一种,默认显示方式,也是最常用的方式: Toast.makeText(MainActivity.this, "这是默认的显示方式", Toast.LE

Android学习笔记(十二)——使用意图传递数据的几种方式

使用意图传递数据的几种方式 点此获取完整代码 我们除了要从活动返回数据,也常常要传递数据给活动.对此我们可以使用Intent对象将这些数据传递给目标活动. 1.创建一个名为PassingData的项目,在activity_main.xml文件中添加一个Button: <Button android:id="@+id/btn_SecondActivity" android:layout_width="fill_parent" android:layout_hei

Android学习笔记五之Service

Android学习笔记五之Service 1.什么是Service? 什么是Service?Service是Android系统的四大组件之一,官方文档是这样描述Service的: A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application comp

Android学习笔记(十四)——在运行时添加碎片(附源码)

在运行时添加碎片 点击获取源码 将UI分割为多个可配置的部分是碎片的优势之一,但其真正强大之处在于可在运行时动态地把它们添加到活动中. 1.使用上一篇创建的Fragments项目,在main.xml文件中注释掉两个<fragment>元素: 2.在FragmentActivity.java中添加下面的代码: FragmentManager fragmentManager = getSupportFragmentManager();//向活动添加碎片 FragmentTransaction fr

Android学习笔记(十六)——碎片之间进行交互(附源码)

碎片之间进行交互 点击下载源码 很多时候,一个活动中包含一个或者多个碎片,它们彼此协作,向用户展示一个一致的UI.在这种情况下,碎片之间能进行通信并交换数据十分重要. 1.使用上一篇中创建的同一个项目,在fragment.xml中添加TextView的标识id: android:id="@+id/lblFragment1" 2.在fragment2.xml中添加一个Button,用于与fragment1进行交互: <Button android:id="@+id/btn

Android学习笔记(十八)——使用意图筛选器和实现浏览网页(附源码)

使用意图筛选器 点击下载源码 1.创建一个Intents项目,给该项目添加一个新类,命名为MyBrowserActivity,在res/layout文件夹下新增一个browser.xml: 2.在AndroidManifest.xml文件中添加如下代码: 添加权限: <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="a

Android学习笔记(十)——使用意图链接活动

使用意图链接活动 1.新建一个名为"UsingIntent"的项目,右击src文件夹下的包名,选择New-->Class选项,并将新的类文件名命名为"SecondActivity": 2.打开AndroidManifest.xml文件,添加如下代码: <activity android:name=".SecondActivity" android:label="Second Activity" > <!