Android 运行时权限示例

2023-11-20

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

什么是 Android 运行时权限?

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

危险和正常的android权限

Android 将某些权限定义为危险权限,将某些权限定义为正常权限。这两种类型的共同点是它们需要在 Manifest 文件中定义。从 Android 6.0 开始,运行时仅检查危险权限,而不会检查正常权限。正常权限的一个例子是android.permission.INTERNET。危险权限分为几类,使用户更容易了解他们允许应用程序执行哪些操作。如果用户接受组/类别中的一项权限,则他们接受整个组。危险许可的一个例子是android.permission.FINE_LOCATION and android.permission.COARSE_LOCATION。启用任何位置权限都会启用所有位置权限。

请求Android运行时权限

方法requestPermissions(String[] permissions, int requestCode);是一个公共方法,用于请求危险权限。我们可以通过传递权限字符串数组来请求多个危险权限。Note:属于两个不同组的 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);

它返回一个整数值许可授予 or 没有权限. Note:如果用户拒绝应用程序中的关键权限,则shouldShowRequestPermissionRationale(String permission);用于描述用户对权限的需要。让我们开发一个应用程序来检查权限是否已经存在。如果没有,则在运行时请求。

Android 运行时权限项目结构

android runtime permissions project

Android运行时权限代码

The 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.journaldev.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>

The MainActivity.java定义如下。

package com.journaldev.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();
    }

}

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

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

在上面的代码中,检查和请求的两个权限是 CAMERA 和 LOCATION。导入静态权限完整类名允许我们只编写 PERMISSION 对象而不是完全限定路径。checkPermission()对每个权限调用 checkSelfPermission。requestPermission() calls ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);. onRequestPermissionsResult检查权限是否被授予。在我们的代码中,如果未授予这两种权限,则会弹出警报对话框,显示必须请求权限。要做到这一点shouldShowRequestPermissionRationale(String permission)被调用,它会调用一个警报对话框,显示需要权限。您可以从“设置”->“应用程序”->“权限”手动撤销权限。Note:运行时权限特定方法仅自 API 23 起可用。因此,每个方法都会检查以下条件:

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

The output of the android runtime permissions example application in action is given below. android runtime permissions example This brings an end to this tutorial. You can download the final Android Runtime Permissions project from the link below.

下载Android运行时权限示例项目

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 运行时权限示例 的相关文章

随机推荐

  • Python 枚举函数

    enumerate 是 Python 中的一个内置函数 允许您在循环迭代时拥有一个自动计数器 Python enumerate 功能 The enumerate 函数采用以下形式 enumerate iterable start 0 该函数
  • 如何在 Ubuntu 18.04 上部署 Mattermost

    Mattermost 是一个企业级即时消息平台 是一个开源自托管 Slack 替代品 它是用 Golang 和 React 编写的 可以使用 MySQL 或 PostgreSQL 作为数据库后端 Mattermost 将您的所有团队沟通集中
  • 如何在 Ubuntu 18.04 上安装 OpenCart

    OpenCart是一个免费开源的 PHP 电子商务平台 将强大的功能与灵活性和用户友好的界面相结合 OpenCart 具有用户管理 多商店 附属机构 折扣 产品评论 多语言和多个支付网关等功能 是许多在线商家的首选平台 在本教程中 我们将向
  • 如何在 CentOS 7 上停止和禁用 Firewalld

    防火墙D是一个完整的防火墙解决方案 可动态管理网络连接和接口的信任级别 它使您可以完全控制允许或禁止进出系统的流量 从 CentOS 7 开始 FirewallD 取代 iptables 成为默认的防火墙管理工具 强烈建议保持 Firewa
  • 如何使用 Mysqldump 备份和恢复 MySQL 数据库

    本教程介绍如何使用 mysqldump 实用程序从命令行备份和恢复 MySQL 或 MariaDB 数据库 mysqldump 实用程序创建的备份文件基本上是一组可用于重新创建原始数据库的 SQL 语句 mysqldump 命令还可以生成
  • 如何在 Ubuntu 20.04 上安装 Spotify

    Spotify是一种数字音乐流媒体服务 可让您即时访问数百万首歌曲 从经典老歌到最新热门歌曲 本指南展示了在 Ubuntu 20 04 上安装 Spotify 的两种方法 Spotify 可以通过 Snapcraft 商店作为 snap 包
  • 如何在 Debian 9 上设置或更改时区

    使用正确的时区对于许多与系统相关的任务和流程都很重要 例如 cron 守护进程使用系统的时区来执行 cron 作业 并且日志文件中的时间戳基于同一系统的时区 系统的时区是在安装过程中设置的 但以后可以轻松更改 本教程展示如何在 Debian
  • 如何在 Ubuntu 20.04 上安装 VMware Workstation Player

    VMwareWorkstation Player 是一款桌面虚拟化软件 允许您在一台计算机上运行多个独立的操作系统 借助 VMware Player 您可以创建并运行自己的虚拟机 并评估由许多软件供应商提供的作为虚拟设备分发的软件VMwar
  • 如何在 CentOS 8 上设置 Apache 虚拟主机

    Apache 虚拟主机允许您在一台计算机上运行多个网站 使用虚拟主机 您可以指定站点文档根 包含网站文件的目录 为每个站点创建单独的安全策略 使用不同的 SSL 证书等等 本文介绍如何在 CentOS 8 服务器上设置 Apache 虚拟主
  • 如何在 Ubuntu 18.04 上安装 VLC 媒体播放器

    VLC 是最流行的开源多媒体播放器之一 它是跨平台的 几乎可以播放所有多媒体文件以及 DVD 音频 CD 和不同的流媒体协议 本教程介绍如何在 Ubuntu 18 04 上安装 VLC 媒体播放器 相同的说明适用于 Ubuntu 16 04
  • 如何在 CentOS 8 上安装和配置 Redis

    Redis 是一个开源内存键值数据存储 它可以用作数据库 缓存和消息代理 并支持各种数据结构 例如字符串 哈希 列表 集合等 Redis 通过 Redis Sentinel 提供高可用性 并通过 Redis Cluster 跨多个 Redi
  • 如何在Linux中删除组(groupdel命令)

    在 Linux 中 组用于组织和管理用户帐户 组的主要目的是定义一组权限 例如读 写或执行允许对于可以在组内的用户之间共享的给定资源 可以使用以下命令创建一个新组groupadd命令 如果不再需要某个组并且可以从系统中删除 本文介绍了如何在
  • Python 加入列表

    Python join list 的意思是将一串字符串与指定的分隔符连接起来形成一个字符串 有时 当您必须将列表转换为字符串时 它很有用 例如 将字母列表转换为逗号分隔的字符串以保存在文件中 Python 加入列表 我们可以用蟒蛇字符串jo
  • Java Hello World 程序

    每当我们开始学习一门编程语言时 第一个程序总是打印Hello World 在上一篇文章中 我们了解到如何在 Windows 10 上安装 Java 现在我们准备编写并运行我们的第一个 Hello World Java 程序 Java Hel
  • 从 Python 调用 C 函数

    我们可以使用 Python 程序调用 C 函数ctypes module 从 Python 调用 C 函数 它涉及以下步骤 创建具有所需函数的 C 文件 c 扩展名 使用 C 编译器创建共享库文件 so 扩展名 在 Python 程序中 从
  • Java中的迭代器设计模式

    迭代器设计模式中的行为模式之一 迭代器模式用于提供遍历一组对象的标准方法 迭代器模式广泛应用于Java集合框架 Iterator 接口提供了遍历集合的方法 迭代器设计模式 According to GoF iterator design p
  • 如何使用 HAProxy 在 Ubuntu VPS 上设置 HTTP 负载平衡

    关于HAProxy HAProxy 高可用性代理 是一个开源负载均衡器 可以对任何 TCP 服务进行负载均衡 它特别适合 HTTP 负载平衡 因为它支持会话持久性和第 7 层处理 与数字海洋专用网络 HAProxy 可以配置为前端 通过专用
  • SSH 要点:使用 SSH 服务器、客户端和密钥

    介绍 SSH 是一种安全协议 用作远程连接 Linux 服务器的主要方式 它通过生成远程 shell 来提供基于文本的界面 连接后 您在本地终端中输入的所有命令都会发送到远程服务器并在那里执行 在这份备忘单式的指南中 我们将介绍一些使用 S
  • 安卓谷歌智能锁

    在本教程中 我们将讨论智能锁功能并在 Android 应用程序中实现它 谷歌智能锁 Smart Lock 用于通过一劳永逸地保存凭据来自动登录您的应用程序 这意味着 如果您在一段时间后重新安装应用程序 您可以使用之前保存的凭据自动登录 前提
  • Android 运行时权限示例

    欢迎来到 Android 运行时权限示例 随着介绍安卓6 0棉花糖 Google 改变了应用程序处理权限的方式 在本教程中 我们将研究引入的新 Android 运行时权限以及如何处理它们 如果处理不当 可能会导致应用程序崩溃 什么是 And