Android Runtime权限示例

时间:2020-02-23 14:29:14  来源:igfitidea点击:

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

什么是Android运行时权限?

随着Android 6.0(SDK 23)的引入,在有必要使用时会提示用户在运行时输入一些特定权限。

因此,我们想到的第一个问题是–旧版应用程序是否可以在Android Marshmallow上运行?如果targetSdkVersion为22或者更小,答案是肯定的。

因此,Android运行时权限支持向后兼容。
现在这并不意味着我们可以通过将sdk版本设置为22来使用旧的权限模型。
使用棉花糖的用户可以从"设置"->"应用"中撤消危险权限(稍后将讨论危险权限和普通权限)。
->权限。
在我们尝试调用某些需要用户尚未授予的权限的函数的情况下,该函数将突然抛出Exception(java.lang.SecurityException),这将导致应用程序崩溃。
因此,我们需要在我们的应用程序中实现这个新的android权限模型。

危险和正常的android权限

Android将某些权限定义为危险,而将某些权限定义为正常。
这两种类型的共同点是它们需要在列表文件中定义。

从Android 6.0起,只有危险权限会在运行时检查,而普通权限则不会。
普通权限的一个示例是" android.permission.INTERNET"。

危险权限分为几类,使用户更容易理解他们允许应用程序执行的操作。
如果用户在组/类别中接受一个权限,则他们将接受整个组。
危险许可的一个示例是" android.permission.FINE_LOCATION"和" android.permission.COARSE_LOCATION"。
启用任何位置权限都将全部启用。

请求Android运行时权限

方法requestPermissions(String [] Permissions,int requestCode);是一个公共方法,用于请求危险的权限。
我们可以通过传递权限的字符串数组来请求多个危险权限。

注意:属于两个不同组的Android权限会提示用户每个用户单独的对话框。
如果它们属于同一组,则将仅显示一个对话框提示。
请求的结果将被传递到方法onRequestPermissionResult中。

范例:假设我们要在应用中访问摄像头和位置。
两者都是危险的权限。
启动该应用程序时,我们会显示一条提示,要求您访问这些权限。
让我们将权限添加到字符串数组中,然后调用requestPermissions,如下所示:

String[] perms = {"android.permission.FINE_LOCATION", "android.permission.CAMERA"};

int permsRequestCode = 200; 
requestPermissions(perms, permsRequestCode);

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){

  switch(permsRequestCode){

      case 200:

          boolean locationAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
          boolean cameraAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;

          break;

  }

}

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

checkSelfPermission(String perm);

它返回PERMISSION_GRANTED或者PERMISSION_DENIED的整数值。

注意:如果用户拒绝在应用程序中很重要的权限,则使用" shouldShowRequestPermissionRationale(StringPermission);"来描述用户对权限的需求。

让我们开发一个应用程序,检查许可是否已经存在。
如果不是,则在运行时请求。

Android Runtime Permissions代码

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

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:app="https://schemas.android.com/apk/res-auto"
  xmlns:tools="https://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  app:layout_behavior="@string/appbar_scrolling_view_behavior"
  tools:context="com.theitroad.runtimepermissions.MainActivity"
  tools:showIn="@layout/activity_main">
  <Button
      android:id="@+id/check_permission"
      android:layout_width="match_parent"
      android:layout_centerInParent="true"
      android:layout_height="wrap_content"
      android:text="Check Permission"
  <Button
      android:id="@+id/request_permission"
      android:layout_below="@+id/check_permission"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Request Permission"
</RelativeLayout>

MainActivity.java定义如下。

package com.theitroad.runtimepermissions;

import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.view.View;
import android.widget.Button;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  private static final int PERMISSION_REQUEST_CODE = 200;
  private View view;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);

      Button check_permission = (Button) findViewById(R.id.check_permission);
      Button request_permission = (Button) findViewById(R.id.request_permission);
      check_permission.setOnClickListener(this);
      request_permission.setOnClickListener(this);

  }

  @Override
  public void onClick(View v) {

      view = v;

      int id = v.getId();
      switch (id) {
          case R.id.check_permission:
              if (checkPermission()) {

                  Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

              } else {

                  Snackbar.make(view, "Please request permission.", Snackbar.LENGTH_LONG).show();
              }
              break;
          case R.id.request_permission:
              if (!checkPermission()) {

                  requestPermission();

              } else {

                  Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

              }
              break;
      }

  }

  private boolean checkPermission() {
      int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
      int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);

      return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
  }

  private void requestPermission() {

      ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);

  }

  @Override
  public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
      switch (requestCode) {
          case PERMISSION_REQUEST_CODE:
              if (grantResults.length > 0) {

                  boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                  boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;

                  if (locationAccepted && cameraAccepted)
                      Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
                  else {

                      Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();

                      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                          if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                              showMessageOKCancel("You need to allow access to both the permissions",
                                      new DialogInterface.OnClickListener() {
                                          @Override
                                          public void onClick(DialogInterface dialog, int which) {
                                              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                  requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
                                                          PERMISSION_REQUEST_CODE);
                                              }
                                          }
                                      });
                              return;
                          }
                      }

                  }
              }

              break;
      }
  }

  private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
      new AlertDialog.Builder(MainActivity.this)
              .setMessage(message)
              .setPositiveButton("OK", okListener)
              .setNegativeButton("Cancel", null)
              .create()
              .show();
  }

}

注意:将在运行时要检查的权限添加到应用程序标签上方的列表文件中,如下所示:

<uses-permission android:name="android.permission.CAMERA" 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" 

在上面的代码中,检查和请求的两个权限是CAMERA和LOCATION。
导入静态权限完整类名使我们可以只编写PERMISSION对象,而不编写完全限定的路径。

checkPermission()对每个权限调用checkSelfPermission。

requestPermission()调用ActivityCompat.requestPermissions(this,new String [] {ACCESS_FINE_LOCATION,CAMERA},PERMISSION_REQUEST_CODE);

onRequestPermissionsResult检查是否授予权限。
在我们的代码中,如果未同时授予两个权限,则会弹出一个警告对话框,显示强制要求该权限的需求。
为此,应调用" shouldShowRequestPermissionRationale(String权限)",这将显示一个警告对话框,显示对权限的需求。
您可以从"设置"->"应用程序"->"权限"手动撤消权限。

注意:特定于运行时权限的方法仅自API 23起可用。
因此,在每种方法中都会检查以下条件:

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