前言:今天突然想起来,前几天,一个在京东的同学,给我打电话,说他在吃饭时与一个技术大牛聊天,他说他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详解(二)》
新建一个工程: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详解》中都有讲到,这里就不再重复说了。
问答环节:
问题:我在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 谢谢!