声明、使用与自定义权限

前言:今天突然想起来,前几天,一个在京东的同学,给我打电话,说他在吃饭时与一个技术大牛聊天,他说他android开发已经两年多了,不想再做android了,没什么挑战性了。当时大牛问了他几个问题,一个没答上来。然后,那人说,小伙子,你现在还处于不知道你不知道的阶段,再加把劲吧。然后,乖乖回去写代码。对于我这样一个还处在android入门阶段的人来讲,到达他这个程度已经是望尘莫及了,看来我还要再加把劲,从今天开始,每写一篇博客开头送给大家一句话,送给大家,也写给自己。

 

人生最可怕的,是比你优秀的人却比你更努力。

(加油,永远不要觉得别人望尘莫及,要做的,只是每天进步一点点)

 

一、概述

首先,我先讲一下,为什么需要有权限这个东东;

权限有两个作用:

其一:防止其它程序随便调用。

其二:能够在安装程序时,显式的给用户看,当前要安装的这个程序要用到哪个功能。这个是最重要的,试想,如果你装一个斗地主游戏,却看到要用到打电话、发短信的功能,便可以判定这个程序里面可能包含恶意代码,还是不装为好。

 

下面以打电话为例,来讲解一下系统对权限的要求:

一般情况下,要调用打电话的Activity,代码是这样写的:

 

	Uri uri = Uri.parse("tel:12345678");
	Intent intent = new Intent(Intent.ACTION_CALL, uri);
	startActivity(intent);

如果我们此时直接执行,会出现下面的错误:

 

 

ERROR/AndroidRuntime: java.lang.SecurityException: Permission Denial: 
starting Intent { act=android.intent.action.CALL dat=tel:12345678 cmp=com.android.phone/.OutgoingCallBroadcaster }
...... 
requires android.permission.CALL_PHONE

说的是需要CALL_PHONE的访问权限,这个权限是Android系统自带的phone应用里定义的权限:

......
<uses-permission android:name="android.permission.CALL_PHONE" />
......
<activity android:name="OutgoingCallBroadcaster"
                android:permission="android.permission.CALL_PHONE"
                android:theme="@android:style/Theme.NoDisplay"
                android:configChanges="orientation|keyboardHidden">
            <!-- CALL action intent filters, for the various ways
                 of initiating an outgoing call. -->
            <intent-filter>
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="tel" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="voicemail" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/phone" />
                <data android:mimeType="vnd.android.cursor.item/phone_v2" />
                <data android:mimeType="vnd.android.cursor.item/person" />
            </intent-filter>
</activity>
......

想要使用此功能,必须在我们的AndroidManifest.xml文件中声明使用此权限:

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

这就是要告诉系统,我们的程序要用到打电话的功能。所以当用户安装程序时,系统只需要遍历AndroidManifest.xml文件就能知道我们需要访问哪些外部程序,即需要哪些程序的权限,比如打电话、发短信等,并以列表的形式告诉用户,当前你要安装的程序要用到哪些权限,以便用户决定确定安装,还是取消安装。
 

二、自定义权限

我们写两个应用,一个Test_Permission,一个客户端:Test_Perssion_Client;我们给Test_Permission加上访问权限,然后在客户端直接调Test_Permission的Activity;

首先是新建工程Test_Permission,然后添加访问权限;

添加访问权限的方法,我这里采用图形化工具的方法,在AndroidManifest.xml中,下面的Tab栏,有一栏叫Permissions,选中-》切到权限管理界面,选择Add按钮,增加一个权限;界面如下:

右边栏设置新增Permission的各项属性,Name和Protection level(风险等级)是必须的,其它项都可不填;写好之后,Ctrl + S 保存

其中的各项参数意义如下:摘自《Pro Android 3》中文版

在设定上面的参数后,代码中生成了下面几行代码:

 

 <permission
     android:name="harvic.permission.STARTMYPERSSION"
     android:label="Start My Permission"
     android:protectionLevel="normal" >
 </permission>

所以,现在的AndroidManifest.xml为:

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test_permission"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="14" />
	
	<!-- 声明一个权限  -->  
    <permission
        android:name="harvic.permission.STARTMYPERSSION"
        android:label="Start My Permission"
        android:protectionLevel="normal" >
    </permission>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"  >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

上面,我们只是声明了一个权限,但到底哪个Activity要用这个权限,还不知道。其实这就跟声明一个变量一样,一个变量在声明之后,就存在在类中了,但不用的话就一点意义没有!一样的道理。

下面,我们创建一个Activity,命名为:PerssionActivity
PerssionActivity的XML代码为:将TextView显示的文字改为here it is,来表明已经进入到这个Activity中了;

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.test_permission.PerssionActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="here it is" />

</RelativeLayout>

然后在AndroidManifest.xml中添加上我们上面生成的访问权限:

 

 

         <!-- 为Activity应用已定义的权限 --> 
         <activity
            android:name=".PerssionActivity"
            android:label="@string/title_activity_perssion"
            android:permission="harvic.permission.STARTMYPERSSION" >
            <intent-filter>
                <action android:name="android.intent.action.MYPERSSION" />
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>
        </activity> 

这里有两点注意:

 

1、添加访问权限是使用:android:permission;

2、因为我们要从外部访问PerssionActivity,所以我们必需要为其添加action和category,

<intent-filter>
    <action android:name="android.intent.action.MYPERSSION" />
    <category android:name="android.intent.category.DEFAULT" />  
</intent-filter>

这两个是必不可少的,其中action我们可以对其随意命名,在外部,我们可以通过传递这个action来隐式启动这个Activity,有关隐式启动Activity的问题,参看《intent详解(一)》《intent详解(二)》
不管隐式启动还是显式启动,无论是从内部还是从外部启动这个activity,都必须要加上action和category这两个参数才行,不然根本启动不了。
到此,这个应用就建好了,下面我们就要另建一个应用,来调这个PerssionActivity了。

 

新建一个工程:Test_Perssion_Client;

首先为其添加访问权限:即

 

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

所以总体的AndroidManifest.xml代码为:

 

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test_perssion_client"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="14" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 <uses-permission android:name="harvic.permission.STARTMYPERSSION"/>
</manifest>

然后在布局文件中,添加一个Btn,单击时跳转用,XML布局代码如下:

 

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.test_perssion_client.MainActivity" >

    <Button 
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="permission跳转"/>

</RelativeLayout>

最后是Java代码了:

 

 

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
   
        Button btn=(Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
			//启动方法一:显示启动
		 	Intent intent = new Intent();
//	        表示希望启动com.example.test_permission包中的com.example.test_permission.MainActivity
	        intent.setClassName("com.example.test_permission", "com.example.test_permission.PerssionActivity");
				
			//启动方法二:隐式启动,通过action匹配	
//			Intent intent = new Intent("android.intent.action.MYPERSSION");
	        startActivity(intent);
			}
		});
        
    }
}

上面有两种启动PerssionActivity的方法,一个显式启动,一个隐式启动,在上面的《Intent详解》中都有讲到,这里就不再重复说了。
下面看效果:
                                                                                                     点击之后跳转到PerssionActivity
  
 

问答环节:

问题:我在Test_Permission工程中另加一个Activity来让外部启动,为什么不能直接使用MainActivity从外部启动呢,非要多此一举?

答:其实我刚开始也是直接使用MainActivity多个外部启动的,但如果给MainActivity添加上访问权限后,你会发现,它自己都启动不起来了,不知道为什么会产生这么蛋疼的问题,所以只有另加一个Activity来演示了,如果有哪位仁兄知道为什么,敬请告知。

 

问题:从外部访问需要权限,那在应用程序内部访问还需要添加权限访问吗?

答:不需要,试试就知道了,在我上传的源码中,当点击hello world时,会跳转到Perssion Activity,而我并没有在AndroidManifest.xml中添加

 

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

截图如下:

 

                         启动MainActivity                                             点击“hello world”实现内部跳转

  
 

源码下载地址:http://download.csdn.net/detail/harvic880925/7786463

请大家尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/38683625  谢谢!

 

如果你喜欢我的文章,你可能更喜欢我的公众号

启舰杂谈

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值