如何在 Android 应用程序中请求权限?

Android 6.0 (API 23)开始,用户在安装时无需请求权限,开发人员需要在运行时请求权限。在运行时只能请求清单文件中定义的权限。

权限类型

1. 安装时权限:如果是Android 5.1.1 (API 22) 或更低版本,在安装时在Google Play Store请求权限。

如果用户接受权限,则安装应用程序。否则应用程序安装被取消

2. Run-Time Permissions:如果是Android 6 (API 23) 或更高版本,则在应用程序运行期间的运行时请求权限。

如果用户接受权限,则可以使用应用程序的该功能。否则要使用该功能,应用程序会再次请求权限

因此,现在在运行时请求权限。在本文中,我们将讨论如何在运行时在 Android 应用程序中请求权限。 

在运行时请求权限的步骤  

第 1 步:在 Android Manifest 文件中声明权限在Android中,使用uses-permission标签 在AndroidManifest.xml文件中声明权限。

<uses-permission android:name=”android.permission.PERMISSION_NAME”/>

在这里,我们声明存储和相机权限。

<!--Declaring the required permissions-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

第二步:修改activity_main.xml文件,添加两个按钮来请求按钮点击权限:权限将被检查并在按钮点击时请求。打开activity_main.xml文件并向其中添加两个按钮。

<!--Button to request storage permission-->
<Button
	android:id="@+id/storage"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="Storage"
	android:layout_marginTop="16dp"
	android:padding="8dp"
	android:layout_below="@id/toolbar"
	android:layout_centerHorizontal="true"/>

<!--Button to request camera permission-->
<Button
	android:id="@+id/camera"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="Camera"
	android:layout_marginTop="16dp"
	android:padding="8dp"
	android:layout_below="@id/storage"
	android:layout_centerHorizontal="true"/>

第 3 步: 检查是否已授予权限。如果尚未授予权限,请用户请求权限:要使用任何服务或功能,都需要权限。因此,我们必须确保为此授予权限。如果不是,则请求权限。

检查权限:从 Android 6.0(API 级别 23)开始,用户有权随时撤销任何应用程序的权限,即使该应用程序的目标 API 级别较低。因此,要使用该服务,应用程序每次都需要检查权限。

句法: 

if(ContextCompat.checkSelfPermission ( thisActivity , Manifest.permission.WRITE_CALENDAR)
   != PackageManager.PERMISSION_GRANTED)
{
    // 未授予权限
}

请求权限:当上述语法中的checkSelfPermission()方法返回PERMISSION_DENIED时,我们需要提示用户该权限。Android 提供了几种可用于请求权限的方法,例如requestPermissions()

句法: 

ActivityCompat.requestPermissions(MainActivity.this, 
                                  permissionArray, 
                                  requestCode);

Here permissionArray is an array of type String.

例子:

// Function to check and request permission
public void checkPermission(String permission, int requestCode)
{
	// Checking if permission is not granted
	if (ContextCompat.checkSelfPermission(MainActivity.this, permission) == PackageManager.PERMISSION_DENIED) {
		ActivityCompat.requestPermissions(MainActivity.this, new String[] { permission }, requestCode);
	}
	else {
		Toast.makeText(MainActivity.this, "Permission already granted", Toast.LENGTH_SHORT).show();
	}
}
// Function to check and request permission.
private fun checkPermission(permission: String, requestCode: Int) {
		if (ContextCompat.checkSelfPermission(this@MainActivity, permission) == PackageManager.PERMISSION_DENIED) {
			// Requesting the permission
			ActivityCompat.requestPermissions(this@MainActivity, arrayOf(permission), requestCode)
		} else {
			Toast.makeText(this@MainActivity, "Permission already granted", Toast.LENGTH_SHORT).show()
		}
}

如果已授予权限,此功能将显示Toast消息,否则提示用户授予权限。

第 4 步:覆盖 onRequestPermissionsResult() 方法: 在用户授予或拒绝权限时调用onRequestPermissionsResult() 。RequestCode是该函数的参数之一,用于检查用户对相应请求的操作。这里显示了一条 toast 消息,指示权限和用户操作。 

例子:

// This function is called when user accept or decline the permission.
// Request Code is used to check which permission called this function.
// This request code is provided when user is prompt for permission.
@Override
public void onRequestPermissionsResult(int requestCode,
									@NonNull String[] permissions,
									@NonNull int[] grantResults)
{
	super.onRequestPermissionsResult(requestCode, permissions, grantResults);

	if (requestCode == CAMERA_PERMISSION_CODE) {

		// Checking whether user granted the permission or not.
		if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

			// Showing the toast message
			Toast.makeText(MainActivity.this, "Camera Permission Granted", Toast.LENGTH_SHORT).show();
		}
		else {
			Toast.makeText(MainActivity.this, "Camera Permission Denied", Toast.LENGTH_SHORT).show();
		}
	}
	else if (requestCode == STORAGE_PERMISSION_CODE) {
		if (grantResults.length > 0
			&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
			Toast.makeText(MainActivity.this, "Storage Permission Granted", Toast.LENGTH_SHORT).show();
		}
		else {
			Toast.makeText(MainActivity.this, "Storage Permission Denied", Toast.LENGTH_SHORT).show();
		}
	}
}
// This function is called when the user accepts or decline the permission.
// Request Code is used to check which permission called this function.
// This request code is provided when the user is prompt for permission.
override fun onRequestPermissionsResult(requestCode: Int,
										permissions: Array<String>,
										grantResults: IntArray) {
		super.onRequestPermissionsResult(requestCode, permissions, grantResults)
		if (requestCode == CAMERA_PERMISSION_CODE) {
			if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				Toast.makeText(this@MainActivity, "Camera Permission Granted", Toast.LENGTH_SHORT).show()
			} else {
				Toast.makeText(this@MainActivity, "Camera Permission Denied", Toast.LENGTH_SHORT).show()
			}
		} else if (requestCode == STORAGE_PERMISSION_CODE) {
			if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				Toast.makeText(this@MainActivity, "Storage Permission Granted", Toast.LENGTH_SHORT).show()
			} else {
				Toast.makeText(this@MainActivity, "Storage Permission Denied", Toast.LENGTH_SHORT).show()
			}
	}
}

下面是这个应用程序的完整代码:

下面是activity_main.xml文件的代码。 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	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=".MainActivity">
	
	<!-- To show toolbar-->
	<android.support.v7.widget.Toolbar
		android:id="@+id/toolbar"
		android:layout_width="match_parent"
		android:background="@color/colorPrimary"
		app:title="GFG | Permission Example"
		app:titleTextColor="@android:color/white"
		android:layout_height="?android:attr/actionBarSize"/>

	<!--Button to request storage permission-->
	<Button
		android:id="@+id/storage"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Storage"
		android:layout_marginTop="16dp"
		android:padding="8dp"
		android:layout_below="@id/toolbar"
		android:layout_centerHorizontal="true"/>

	<!--Button to request camera permission-->
	<Button
		android:id="@+id/camera"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Camera"
		android:layout_marginTop="16dp"
		android:padding="8dp"
		android:layout_below="@id/storage"
		android:layout_centerHorizontal="true"/>

</RelativeLayout>

下面是AndroidManifest.xml文件的代码。 

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

		<!--Declaring the required permissions-->
		<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
		<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
		<uses-permission android:name="android.permission.CAMERA" />

		<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>

下面是MainActivity文件的代码。

import android.Manifest;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

	// Defining Buttons
	private Button storage, camera;

	// Defining Permission codes.
	// We can give any value
	// but unique for each permission.
	private static final int CAMERA_PERMISSION_CODE = 100;
	private static final int STORAGE_PERMISSION_CODE = 101;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		storage = findViewById(R.id.storage);
		camera = findViewById(R.id.camera);

		// Set Buttons on Click Listeners
		storage.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v)
			{
				checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, STORAGE_PERMISSION_CODE);
			}
		});

		camera.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v)
			{
				checkPermission(Manifest.permission.CAMERA, CAMERA_PERMISSION_CODE);
			}
		});
	}

	// Function to check and request permission.
	public void checkPermission(String permission, int requestCode)
	{
		if (ContextCompat.checkSelfPermission(MainActivity.this, permission) == PackageManager.PERMISSION_DENIED) {

			// Requesting the permission
			ActivityCompat.requestPermissions(MainActivity.this, new String[] { permission }, requestCode);
		}
		else {
			Toast.makeText(MainActivity.this, "Permission already granted", Toast.LENGTH_SHORT).show();
		}
	}

	// This function is called when the user accepts or decline the permission.
	// Request Code is used to check which permission called this function.
	// This request code is provided when the user is prompt for permission.

	@Override
	public void onRequestPermissionsResult(int requestCode,
										@NonNull String[] permissions,
										@NonNull int[] grantResults)
	{
		super.onRequestPermissionsResult(requestCode,
										permissions,
										grantResults);

		if (requestCode == CAMERA_PERMISSION_CODE) {
			if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				Toast.makeText(MainActivity.this, "Camera Permission Granted", Toast.LENGTH_SHORT) .show();
			}
			else {
				Toast.makeText(MainActivity.this, "Camera Permission Denied", Toast.LENGTH_SHORT) .show();
			}
		}
		else if (requestCode == STORAGE_PERMISSION_CODE) {
			if (grantResults.length > 0
				&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				Toast.makeText(MainActivity.this, "Storage Permission Granted", Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(MainActivity.this, "Storage Permission Denied", Toast.LENGTH_SHORT).show();
			}
		}
	}
}
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {

	companion object {
		private const val CAMERA_PERMISSION_CODE = 100
		private const val STORAGE_PERMISSION_CODE = 101
	}

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)

		// Defining Buttons
		val storage: Button? = findViewById(R.id.storage)
		val camera: Button? = findViewById(R.id.camera)

		// Set Buttons on Click Listeners
		storage?.setOnClickListener {checkPermission(
					Manifest.permission.WRITE_EXTERNAL_STORAGE,
					STORAGE_PERMISSION_CODE)
		}
		camera?.setOnClickListener {
			checkPermission(Manifest.permission.CAMERA,
					CAMERA_PERMISSION_CODE)
		}
	}

	// Function to check and request permission.
	private fun checkPermission(permission: String, requestCode: Int) {
		if (ContextCompat.checkSelfPermission(this@MainActivity, permission) == PackageManager.PERMISSION_DENIED) {

			// Requesting the permission
			ActivityCompat.requestPermissions(this@MainActivity, arrayOf(permission), requestCode)
		} else {
			Toast.makeText(this@MainActivity, "Permission already granted", Toast.LENGTH_SHORT).show()
		}
	}

	// This function is called when the user accepts or decline the permission.
	// Request Code is used to check which permission called this function.
	// This request code is provided when the user is prompt for permission.
	override fun onRequestPermissionsResult(requestCode: Int,
											permissions: Array<String>,
											grantResults: IntArray) {
		super.onRequestPermissionsResult(requestCode, permissions, grantResults)
		if (requestCode == CAMERA_PERMISSION_CODE) {
			if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				Toast.makeText(this@MainActivity, "Camera Permission Granted", Toast.LENGTH_SHORT).show()
			} else {
				Toast.makeText(this@MainActivity, "Camera Permission Denied", Toast.LENGTH_SHORT).show()
			}
		} else if (requestCode == STORAGE_PERMISSION_CODE) {
			if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				Toast.makeText(this@MainActivity, "Storage Permission Granted", Toast.LENGTH_SHORT).show()
			} else {
				Toast.makeText(this@MainActivity, "Storage Permission Denied", Toast.LENGTH_SHORT).show()
			}
		}
	}
}

输出:

在启动应用程序时:

第一次单击相机按钮时:

在授予权限时:

再次单击相机按钮时: