Android 在程序运行时申请权限的实例讲解

这里我们以拨打电话申请权限来写个小例子,也就是CALL_PHONE,因为拨打电话会涉及用户手机的资费问题,因而被列为了危险权限,在Android6.0系统出现之前,拨打电话功能的实现其实非常简单,修改activity_mainxml中的代码,如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context="com.example.runtimepermissiontest.MainActivity">

 <Button
 android:id="@+id/make_call"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Make Call"
 android:textAllCaps="false"/>

</android.support.constraint.ConstraintLayout>

我们在布局文件中只定义了一个按钮,当点击按钮时就会去触发拨打电话的逻辑,接着修改MainActivity中的代码,如下:

public class MainActivity extends AppCompatActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 Button makeCall = findViewById(R.id.make_call);
 makeCall.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
  try {
   Intent intent = new Intent(Intent.ACTION_CALL);
   intent.setData(Uri.parse("tel:10000"));
   startActivity(intent);
  }catch (SecurityException e){
   e.printStackTrace();
  }
  }
 });
 }
}

可以看到,在按钮的点击事件中,我们构建了一个隐式Intent,Intent的action指定为Intent.ACTION_CALL,这是一个系统内置的打电话的动作,然后在data部分指定了协议是tel,号码是10000,表示打开拨号界面,这个是不需要声明权限的,而Intent.ACTION_CALL则可以直接拨打电话,因此必须申明权限,另外为了防止程序崩溃,我们将所有操作都放在了异常捕获代码块当中。

那么接下来修改AndroidManifest.xml文件,在其中声明如下权限:

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

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

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

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

</manifest>

这样我们就将拨打电话的功能实现了,并且在低于Android6.0系统的手机上都是可以正常运行的,但是如果我们在6.0或者更高版本系统的手机上运行,点击Make Call按钮就没有任何效果,这时观察logcat中的日志,会报如下错误:

错误信息中提示我们Permission Denial,可以看出,是由于权限被禁止所导致的,因为6.0及以上系统在使用危险权限时都必须进行运行时权限处理。

那么下面我们就来尝试修复这个问题,修改MainActivity中的代码,如下:

public class MainActivity extends AppCompatActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 Button makeCall = findViewById(R.id.make_call);
 makeCall.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
  if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
   ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1);
  }else {
   call();
  }
  }
 });
 }

 private void call(){
 try {
  Intent intent = new Intent(Intent.ACTION_CALL);
  intent.setData(Uri.parse("tel:10000"));
  startActivity(intent);
 }catch (SecurityException e){
  e.printStackTrace();
 }
 }

 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
 switch (requestCode){
  case 1:
  if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
   call();
  }else {
   Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
  }
  break;
  default:
   break;
 }
 }
}

上面的代码将运行权限的完成流程都覆盖了,下面我们来具体解析一下,说白了,运行时权限的核心就是在程序运行过程中由用户授权我们去执行某些危险操作,程序是不可以擅自做主去执行这些危险操作的,因此,第一步就是要去判断用户是不是已经给过我们授权了,借助的是ContextCompat.checkSelfPermission()方法,checkSelfPermission()方法接收两个参数,第一个参数是Context,这个没什么好说的,第二个参数是具体的权限名,比如打电话的权限名就是Manifest.permission.CALL_PHONE,然后使用方法的返回值和packageManager.PERMISSION_CRANTED做比较,相等就说明用户已经授权,不等就表示用户没有授权。

如果已经授权的话就简单了,直接去执行拨打电话的逻辑操作就可以了,这里我们把拨打电话的逻辑封装到call()方法中,如果没有授权的话,则需要调用ActivityCompat.requestPermissions()方法来向用户申请授权,requestPermissions()方法接收3个参数,第一个参数要求是Activity的实例,第二个参数是一个String数组,我们把要申请的权限名放在数组中即可,第三个参数是请求码,只要是唯一值就可以了,这里传入1。

调用完了requestPermissions()方法之后,系统会弹出一个申请权限的对话框,然后用户可以选择同意或拒绝我们的权限申请,不论是哪种结果,最终都会回调到onRequestPermissionsResult()方法中,而授权的结果则封装在grantResults参数当中,这里我们只需要判断一下最后的授权结果,如果用户同意的话就调用call()方法来拨打电话,如果用户拒绝的话我们只能放弃操作,并且弹出一条失败提示。

现在重新运行一下程序,并点击Make Call按钮,效果如图:

由于用户还没有授权过我们拨打电话权限,因此第一次运行会弹出这样一个权限申请的对话框,用户可以选择同意或者拒绝,比如说这里点击了DENY,结果如图:

由于用户没有同意授权,我们只能弹出一个操作失败的提示,下面我们再次点击Make Call,任然会弹出权限申请的对话框,这次点击ALLOW,结果如图:

可以看到,这次我们就成功进入到拨打电话界面了,并且由于用户已经完成了授权操作,之后再点击Make Call按钮就不会再弹出权限申请对话框了,而是可以直接拨打电话,那可能你会担心,万一以后我又后悔了怎么办?没有关系,用户随时都可以将授予程序的危险权限进行关系,进入Settings-->Apps-->RuntimePermissiontTest-->Permissions,界面如图:

在这里我们就可以对任何授予过的危险权限进行关闭了。

以上这篇Android 在程序运行时申请权限的实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Android运行时权限及APP适配方法

    Android 6.0起,Android加强了权限管理,引入运行时权限概念.对于: 1. Android 5.1(API 22)及以前版本,应用权限必须声明在AndroidManifest.xml中,应用在安装时,Android会列出其所需的所有权限供用户确认安装. 2. Android 6.0(API 23)及以后版本,应用权限必须声明在AndroidManifest.xml中,但权限分为普通权限(Normal Permissions)和危险权限(Dangerous Permissions),

  • android开发权限询问的示例代码

    现在基于信息安全问题,特别是版本是23以上权限越严格. 特别是拍照,读,写权限 一般权限允许过,下次就不用询问了的,所以很多应用都喜欢在首页或者启动页直接询问,不允许的就用不了1.下面给出封装好的类,至于什么时候调看项目需要 public class EasyPermissions { private static final String TAG = "EasyPermissions"; public interface PermissionCallbacks extends Act

  • Android 中的危险权限详细整理

    Android 中的危险权限详细整理 前言: Android 中有上百种权限,现在将所有的权限归为两类: 一类是普通权限 一类的危险权限 普通权限是指那些不会威胁到用户安全和隐私的权限,这部分权限系统会自动帮我们进行授权不需要手动操作.危险权限则表示那些可能会触及到用户安全隐私或者对设备安全造成影响的权限,如获取手机联系人信息等权限,申请者部分权限必须有用户收到点击授权才可以,否则程序无法使用相应的功能. 下面列出 Android 中所有的危险权限,一共是9组24个权限. 权限组名 权限名称 C

  • Android 在程序运行时申请权限的实例讲解

    这里我们以拨打电话申请权限来写个小例子,也就是CALL_PHONE,因为拨打电话会涉及用户手机的资费问题,因而被列为了危险权限,在Android6.0系统出现之前,拨打电话功能的实现其实非常简单,修改activity_mainxml中的代码,如下: <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android=&qu

  • 谈谈Android6.0运行时的权限处理

    运行时权限介绍 Android 6.0在我们原有的AndroidManifest.xml声明权限的基础上, 又新增了运行时权限动态检测,以下权限都需要在运行时判断: 1.身体传感器 2.日历    3.摄像头 4.通讯录 5.地理位置 6.麦克风 7.电话 8.短信 9.存储空间 在 Android 6.0 中,app 如果想要获得某些权限,会在应用中弹出一个对话框,让用户确认是否授予该权限. 具体的截图如下: 这要做的好处就是运行一个 app 时可以拒绝其中的某些权限,防止 app 触及到你的

  • Android 7.0 运行时权限弹窗问题的解决

    Android 7.0系统在运行应用的时候,对权限做了诸多限制,normal, dangerous, signature, signatureOrSystem ,取决于保护级别,在确定是否授予权限时,系统可能采取不同的操作. normal 表示权限是低风险的,不会对系统.用户或其他应用程序造成危害: dangerous 表示权限是高风险的,系统将可能要求用户输入相关信息,才会授予此权限: signature 表示只有当应用程序所用数字签名与声明引权限的应用程序所用数字签名相同时,才能将权限授给它

  • Linux程序运行时加载动态库失败的解决方法

    Linux下不能加载动态库问题 当出现下边异常情况 ./test: error while loading shared libraries: libmfs_open.so: cannot open shared object file: No such file or directory 若动态库的路径在(/usr/cluster/.share/lib) 解决办法: 方法一.在/etc/ld.so.conf文件中添加路径,vi /etc/ld.so.conf 添加下边内容 include ld

  • Android省市区三级联动控件使用方法实例讲解

    最近有需求需要实现省市区三级联动,但是发现之前的实现不够灵活,自己做了一些优化.为了方便以后使用,抽离出来放在了github上WheelView.同时把其核心库放在了JCenter中了,可以直接引用.也可以参考项目中的Demo进行引用 下面介绍一下如何使用 如果用的是AndroidStudio那么直接在build.gradle文件中添加依赖: dependencies { compile 'chuck.WheelItemView:library:1.0.1' } 成功引入库之后,可以在需要弹出省

  • 详解Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以上设备越来越多了,所以Android 6.0 权限适配是必不可少的工作,这里主要介绍一下我们公司是如何做Android 6.0权限适配的. Android 6.0以下非运行时权限: 根据上面博客我们很清楚的知道,Android的权限其实就是为了程序之间更加的安全的访问,所以权限有等级之分,比如:No

  • 详解Android数据存储之Android 6.0运行时权限下文件存储的思考

    前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以往直接sdcard根目录上直接新建了一个xxx/cache/目录来做文件存储就会不是那么容易控制了,所以有必要重新认识一下Android文件存储的相关知识了. 背景: 有关外置sdcard的读写权限 <uses-permission android:name="android.permissi

  • 详解Android中Activity运行时屏幕方向与显示方式

    现在我们的手机一般都内置有方向感应器,手机屏幕会根据所处位置自动进行横竖屏切换(前提是未锁定屏幕方向).但有时我们的应用程序仅限在横屏或者竖屏状态下才可以运行,此时我们需要锁定该程序Activity运行时的屏幕方向.还有就是在我们用手机观看视频时,随意的进行横竖屏切换,但播放进度不会随着屏幕的转换而从头开始播放,为了实现这个功能,我们就需要在Activity转换时对当前数据进行保存. 现在根据以上两种需求,个人提出以下解决方案: 一.锁定Activity运行时屏幕方向,如下图(演示锁定横屏):

  • Android中不支持动态申请权限的原因

    作为Android开发者,为程序增加权限是在正常不过的事情了,做法必然是在mainifest中,写入类似这样<uses-permission android:name="android.permission.INTERNET" />的信息. 以静态申请的形式来完成. 于是这里我想抛出一个问题,Android平台支持动态申请权限么. 相信很多人回答都是不支持,当然这个答案是对的,但是为什么不支持呢,知其然更要知其所以然.了解其原因还是相当有必要的. 原因列举 Android没

  • 解析Android应用程序运行机制

    在标准的Windows和Linux桌面操作系统中,同时可以在不同的窗口中运行多个应用程序,每次只有一个应用程序是当前焦点状态,但其他的应用程序都是一个平等的位置.用户可以随时切换每个应用程序,在不需要应用程序时,也需要用户来关闭应用程序. 但是Android操作系统的应用程序却不是采用这种方式. Android中每次只有一个应用程序运行在最前面,除了状态栏的位置,当前应用程序将铺满整个屏幕.用户最常见的应用程序就是应用的主页(Home application),这个程序主要显示背景图和应用程序快

随机推荐