安卓运行时权限示例

欢迎使用Android运行时权限示例。随着Android 6.0棉花糖 的推出,谷歌改变了应用程序处理权限的方式。在本教程中,我们将研究引入的新的Android运行时权限以及如何处理它们。如果处理不当,可能会导致应用程序崩溃。

什么是Android运行时权限?

随着Android 6.0(SDK 23)的引入,当用户需要使用时,会在运行时提示他们需要一些特定的权限。因此,我们想到的第一个问题是--旧的应用程序会在Android棉花糖上运行吗?如果目标SdkVersion为22或更低,则答案是 。因此,Android运行时权限支持向后兼容。现在,这并不意味着我们可以通过将SDK版本设置为22来使用旧的权限模型。使用棉花糖的用户可以从设置->应用->权限中撤销危险权限(我们稍后将讨论危险权限和正常权限)。如果我们试图调用一些需要用户尚未授予权限的函数,该函数将突然抛出一个异常(java.lang.SecurityException),这将导致应用程序崩溃。因此,我们需要在应用程序中实现这个新的Android权限模型。

危险和正常的Android权限

Android将一些权限定义为危险权限,另一些定义为正常权限。这两种类型的共同点是它们需要在Manifest文件中定义。从Android 6.0开始,只在运行时检查危险权限,而不检查正常权限。普通权限的一个例子是android.permission.INTERNET。危险权限被分成不同的类别,以便用户更容易理解他们允许应用程序执行的操作。如果用户接受组/类别中的一个权限,则他们接受整个组。例如,android.permission.FINE_Locationandroid.permission.COARSE_Location就是危险权限。启用任何位置权限都会启用所有权限。

请求Android运行时权限

方法questPermises(String[]Permittions,int questCode);是一个公共方法,用于请求危险权限。我们可以通过传递权限字符串数组来请求多个危险权限。注意 :Android权限属于两个不同的组,每个组都会有一个单独的对话框提示用户。如果它们属于同一组,则只会显示一个对话框提示。请求的结果将传入onRequestPermissionResult方法。例如:假设我们想要访问应用程序中的摄像头和位置。两者都是危险的权限。当应用程序启动时,我们将显示一个提示,请求访问这些权限。让我们将权限添加到字符串数组中,并调用请求权限,如下所示:

 1String[] perms = {"android.permission.FINE_LOCATION", "android.permission.CAMERA"};
 2
 3int permsRequestCode = 200; 
 4requestPermissions(perms, permsRequestCode);
 5
 6@Override
 7public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
 8
 9    switch(permsRequestCode){
10
11        case 200:
12
13            boolean locationAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
14            boolean cameraAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;
15
16            break;
17
18    }
19
20}

现在,我们不希望用户继续接受他已经接受的权限。即使该权限先前已被授予,也必须再次检查以确保用户随后没有撤销该权限。为此,需要对每个权限调用以下方法。

1checkSelfPermission(String perm);

返回整数值PERSISSION_GRANDED 或** PERSISSION_DENIED** 。** 注意** :如果用户拒绝了APP中的关键权限,则使用shouldShowRequestPermissionRationale(字符串权限);来描述用户对该权限的需求。让我们开发一个应用程序来检查权限是否已经存在。如果不是,则在运行时请求它。

Android运行时权限项目结构

安卓运行时权限project

Android运行时权限-code

content_main.xml包含两个按钮,分别用于检查和请求权限。

 1<?xml version="1.0" encoding="utf-8"?>
 2<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
 3    xmlns:app="https://schemas.android.com/apk/res-auto"
 4    xmlns:tools="https://schemas.android.com/tools"
 5    android:layout_width="match_parent"
 6    android:layout_height="match_parent"
 7    android:paddingBottom="@dimen/activity_vertical_margin"
 8    android:paddingLeft="@dimen/activity_horizontal_margin"
 9    android:paddingRight="@dimen/activity_horizontal_margin"
10    android:paddingTop="@dimen/activity_vertical_margin"
11    app:layout_behavior="@string/appbar_scrolling_view_behavior"
12    tools:context="com.journaldev.runtimepermissions.MainActivity"
13    tools:showIn="@layout/activity_main">
14    <Button
15        android:id="@+id/check_permission"
16        android:layout_width="match_parent"
17        android:layout_centerInParent="true"
18        android:layout_height="wrap_content"
19        android:text="Check Permission"/>
20    <Button
21        android:id="@+id/request_permission"
22        android:layout_below="@+id/check_permission"
23        android:layout_width="match_parent"
24        android:layout_height="wrap_content"
25        android:text="Request Permission"/>
26</RelativeLayout>

MainActivity.java定义如下。

  1package com.journaldev.runtimepermissions;
  2
  3import android.content.DialogInterface;
  4import android.content.pm.PackageManager;
  5import android.os.Build;
  6import android.os.Bundle;
  7import android.support.design.widget.Snackbar;
  8import android.support.v4.app.ActivityCompat;
  9import android.support.v4.content.ContextCompat;
 10import android.support.v7.app.AlertDialog;
 11import android.support.v7.app.AppCompatActivity;
 12import android.support.v7.widget.Toolbar;
 13
 14import android.view.View;
 15import android.widget.Button;
 16
 17import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 18import static android.Manifest.permission.CAMERA;
 19
 20public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 21
 22    private static final int PERMISSION_REQUEST_CODE = 200;
 23    private View view;
 24
 25    @Override
 26    protected void onCreate(Bundle savedInstanceState) {
 27        super.onCreate(savedInstanceState);
 28        setContentView(R.layout.activity_main);
 29        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 30        setSupportActionBar(toolbar);
 31
 32        Button check_permission = (Button) findViewById(R.id.check_permission);
 33        Button request_permission = (Button) findViewById(R.id.request_permission);
 34        check_permission.setOnClickListener(this);
 35        request_permission.setOnClickListener(this);
 36
 37    }
 38
 39    @Override
 40    public void onClick(View v) {
 41
 42        view = v;
 43
 44        int id = v.getId();
 45        switch (id) {
 46            case R.id.check_permission:
 47                if (checkPermission()) {
 48
 49                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();
 50
 51                } else {
 52
 53                    Snackbar.make(view, "Please request permission.", Snackbar.LENGTH_LONG).show();
 54                }
 55                break;
 56            case R.id.request_permission:
 57                if (!checkPermission()) {
 58
 59                    requestPermission();
 60
 61                } else {
 62
 63                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();
 64
 65                }
 66                break;
 67        }
 68
 69    }
 70
 71    private boolean checkPermission() {
 72        int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
 73        int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);
 74
 75        return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
 76    }
 77
 78    private void requestPermission() {
 79
 80        ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);
 81
 82    }
 83
 84    @Override
 85    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
 86        switch (requestCode) {
 87            case PERMISSION_REQUEST_CODE:
 88                if (grantResults.length > 0) {
 89
 90                    boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
 91                    boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
 92
 93                    if (locationAccepted && cameraAccepted)
 94                        Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
 95                    else {
 96
 97                        Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();
 98
 99                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
100                            if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
101                                showMessageOKCancel("You need to allow access to both the permissions",
102                                        new DialogInterface.OnClickListener() {
103                                            @Override
104                                            public void onClick(DialogInterface dialog, int which) {
105                                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
106                                                    requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
107                                                            PERMISSION_REQUEST_CODE);
108                                                }
109                                            }
110                                        });
111                                return;
112                            }
113                        }
114
115                    }
116                }
117
118                break;
119        }
120    }
121
122    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
123        new AlertDialog.Builder(MainActivity.this)
124                .setMessage(message)
125                .setPositiveButton("OK", okListener)
126                .setNegativeButton("Cancel", null)
127                .create()
128                .show();
129    }
130
131}

注意:在应用程序标签上方的Manifest文件中添加运行时需要检查的权限;

1<uses-permission android:name="android.permission.CAMERA" />
2<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

在上面的代码中,检查和请求的两个权限是摄像机和位置。导入静态权限完整类名允许我们只编写权限对象,而不是完全限定路径。check Permission()调用每个权限上的check SelfPermission。questPermission()调用ActivityCompat.questPermission(this,new字符串[]{ACCESS_FINE_LOCATION,CAMERA},PERMISSION_REQUEST_CODE);onRequestPermissionsResult检查是否授予权限。在我们的代码中,如果这两个权限都没有被授予,则会弹出一个警告对话框,显示强制需要请求权限。为此,将调用shoudShowRequestPermissionRationale(字符串权限),这将调用一个警告对话框来显示需要权限。您可以在设置->应用->权限中手动撤销权限。 :运行时权限的具体方法仅在API 23以后的版本中提供。因此,在每个方法中都会检查以下条件:

1if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)

android运行时权限示例应用程序的输出如下所示。android运行时权限示例本教程到此结束。您可以从下面的链接下载最终的Android插件项目。

下载安卓运行时权限示例Project

参考文献:https://developer.android.com/training/permissions/requesting.html

Published At
Categories with 技术
Tagged with
comments powered by Disqus