Android marshmallow 请求权限?

我目前正在开发一个需要几个“危险”权限的应用程序。所以我尝试在Android Marshmallow(API级别23)中添加“请求许可”,但不知道如何做到这一点。

如何在我的应用程序中使用新的权限模型请求权限?

343981 次浏览

android - m即API 23引入了运行时的权限来减少android设备的安全漏洞,用户现在可以在运行时直接管理应用程序权限。因此,如果用户拒绝应用程序的特定权限,您必须通过询问您在查询中提到的权限对话框来获得它。

所以在行动前检查,即检查你是否有权限访问资源链接,如果你的应用程序没有这个特殊的权限,你可以请求权限链接,并像下面这样处理权限请求响应。

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {


// permission was granted, yay! Do the
// contacts-related task you need to do.


} else {


// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}


// other 'case' lines to check for other
// permissions this app might request
}
}

所以最后,如果你打算使用新版本,最好先执行行为变化,以避免强制关闭:)

权限最佳实践

你可以通过官方示例应用程序在这里

使用下面的代码打开一个对话框:

 ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
1);

得到Activity结果如下所示:

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {


// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {


// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {


// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}


// other 'case' lines to check for other
// permissions this app might request
}
}

更多信息:https://developer.android.com/training/permissions/requesting.html

我使用了谷歌开发人员编写的这个包装器(推荐)。它超级容易使用。

https://github.com/googlesamples/easypermissions < a href = " https://github.com/googlesamples/easypermissions " > < / >

功能处理检查和请求许可,如果需要

public void locationAndContactsTask() {
String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS };
if (EasyPermissions.hasPermissions(this, perms)) {
// Have permissions, do the thing!
Toast.makeText(this, "TODO: Location and Contacts things", Toast.LENGTH_LONG).show();
} else {
// Ask for both permissions
EasyPermissions.requestPermissions(this, getString(R.string.rationale_location_contacts),
RC_LOCATION_CONTACTS_PERM, perms);
}
}

快乐编码:)

我使用它作为一个基Fragment类。我只要求一个片段的权限,但是您可以重构它并创建一个类似的Activity版本。

public class BaseFragment extends Fragment {


private static final int PERMISSION_REQUEST_BLOCK_INTERNAL = 555;
private static final String PERMISSION_SHARED_PREFERENCES = "permissions";


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_BLOCK_INTERNAL) {
boolean allPermissionsGranted = true;


for (int iGranting : grantResults) {
if (iGranting != PermissionChecker.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}


if (allPermissionsGranted && permissionBlock != null) {
permissionBlock.run();
}


permissionBlock = null;
}
}


public void runNowOrAskForPermissionsFirst(String permission, Runnable block) {
if (hasPermission(permission)) {
block.run();
} else if (!hasPermissionOrWillAsk(permission)) {
permissionBlock = block;
askForPermission(permission, PERMISSION_REQUEST_BLOCK_INTERNAL);
}
}


public boolean hasPermissionOrWillAsk(String permission) {
boolean hasPermission = hasPermission(permission);
boolean hasAsked = hasPreviouslyAskedForPermission(permission);
boolean shouldExplain = shouldShowRequestPermissionRationale(permission);


return hasPermission || (hasAsked && !shouldExplain);
}


private boolean hasPermission(String permission) {
return (ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED);
}


private boolean hasPreviouslyAskedForPermission(String permission) {
SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE);
return prefs.getBoolean(permission, false);
}


private void askForPermission(String permission, int requestCode) {
SharedPreferences.Editor editor = getContext().getSharedPreferences(PERMISSION_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit();


editor.putBoolean(permission, true);
editor.apply();


requestPermissions(new String[] { permission }, requestCode);
}
}

你应该使用两个关键方法:

  • hasPermissionOrWillAsk -使用这个来查看一个权限是否已经被一个不想再次被请求的用户请求并被拒绝。当用户给出他们不想要某个特性的最终答案时,这对于禁用UI非常有用。

  • runNowOrAskForPermissionsFirst -使用它来运行一些需要权限的代码。如果用户已经授予权限,则代码将立即运行。否则,如果用户授予权限,代码将在稍后运行。或者根本没有。这很好,因为您在一个地方指定了代码。

这里有一个例子:

mFragment.runNowOrAskForPermissionsFirst(Manifest.permission.ACCESS_FINE_LOCATION, new Runnable() {
@Override
public void run() {
...do something if we have permission...
}
});

很高兴得到反馈。并不是说这个特定的例子有点简化,因为您还需要检查设备上是否启用了Location Services。(这与权限不同。)此外,它一次只支持一种权限,但是如果您需要它一次支持多个权限,那么修改它就很简单。

我使用这个结构来检查我的应用程序是否有权限,如果没有权限就请求。所以在我的主代码中,我想检查写以下:

int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (!checkIfAlreadyhavePermission()) {
requestForSpecificPermission();
}
}

模块checkIfAlreadyhavePermission()实现如下:

private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}

模块requestForSpecificPermission()实现如下:

private void requestForSpecificPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
}

和覆盖活动:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//granted
} else {
//not granted
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

更多细节请参考这个链接:http://revisitingandroid.blogspot.in/2017/01/how-to-check-and-request-for-run-time.html

对于一次多个权限,您可以使用此选项。这对我很有用。我有另一个解。如果你给你的targetSdkVersion咆哮22它为我工作。它的行为就像从manifest。xml中获得许可。经过测试,对我有用。

final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;


private void insertDummyContactWrapper() {
List<String> permissionsNeeded = new ArrayList<String>();


final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("GPS");
if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add("Read Contacts");
if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
permissionsNeeded.add("Write Contacts");


if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}


insertDummyContact();
}


private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}












@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
{
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
insertDummyContact();
} else {
// Permission Denied
Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

欲知详情。检查波纹管链接

https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

从Android Marshmallow开始,我们需要向用户请求特定的权限。我们还可以检查代码是否已经给予了权限。下面是一些常用的权限:

  • < p > android.permission_group.CALENDAR

    • android.permission.READ_CALENDAR
    • android.permission.WRITE_CALENDAR
    • 李< / ul > < / >
    • < p > android.permission_group.CAMERA

      • android.permission.CAMERA
      • 李< / ul > < / >
      • < p > android.permission_group.CONTACTS

        • android.permission.READ_CONTACTS
        • android.permission.WRITE_CONTACTS
        • android.permission.GET_ACCOUNTS
        • 李< / ul > < / >
        • < p > android.permission_group.LOCATION

          • android.permission.ACCESS_FINE_LOCATION
          • android.permission.ACCESS_COARSE_LOCATION
          • 李< / ul > < / >
          • < p > android.permission_group.MICROPHONE

            • android.permission.RECORD_AUDIO
            • 李< / ul > < / >
            • < p > android.permission_group.PHONE

              • android.permission.READ_PHONE_STATE
              • android.permission.CALL_PHONE
              • android.permission.READ_CALL_LOG
              • android.permission.WRITE_CALL_LOG
              • android.permission.ADD_VOICEMAIL
              • android.permission.USE_SIP
              • android.permission.PROCESS_OUTGOING_CALLS
              • 李< / ul > < / >
              • < p > android.permission_group.SENSORS

                • android.permission.BODY_SENSORS
                • 李< / ul > < / >
                • < p > android.permission_group.SMS

                  • android.permission.SEND_SMS
                  • android.permission.RECEIVE_SMS
                  • android.permission.READ_SMS
                  • android.permission.RECEIVE_WAP_PUSH
                  • android.permission.RECEIVE_MMS
                  • android.permission.READ_CELL_BROADCASTS
                  • 李< / ul > < / >
                  • < p > android.permission_group.STORAGE

                    • android.permission.READ_EXTERNAL_STORAGE
                    • android.permission.WRITE_EXTERNAL_STORAGE
                    • 李< / ul > < / >

下面是检查权限的示例代码:

if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.WRITE_CALENDAR)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
alertBuilder.setCancelable(true);
alertBuilder.setMessage("Write calendar permission is necessary to write event!!!");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
});
} else {
ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_CALENDAR}, MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
}

有一个很好的库,当后台服务需要权限时,可以使用它来请求权限。尽管库的一个限制是它不能被用来确定当前是否给应用程序权限。它总是问用户app是否还没有它们。

请尝试一下,因为它使生活更简单

为了处理运行时权限,谷歌提供了一个库项目。你可以从这里检查这个https://github.com/googlesamples/easypermissions

EasyPermissions是通过向构建中添加以下依赖项来安装的。gradle文件:

dependencies {
compile 'pub.devrel:easypermissions:0.3.0'
}

开始使用EasyPermissions,让你的Activity(或Fragment)覆盖onRequestPermissionsResult方法:

public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {


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


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


// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}


@Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Some permissions have been granted
// ...
}


@Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Some permissions have been denied
// ...
}
}
在这里,您将得到这个库如何工作的工作示例 https://github.com/milon87/EasyPermission < / p >

这可能是一种更干净的方式。在数组中添加您的所有权限

private static final String[] INITIAL_PERMS={
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
};
private static final int INITIAL_REQUEST=1337;

不管你的权限是什么,为每个权限创建方法

@RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessFineLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}


@RequiresApi(api = Build.VERSION_CODES.M)
private boolean canAccessCoarseLocation() {
return(hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION));
}


@RequiresApi(api = Build.VERSION_CODES.M)
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}

onCreate中调用此方法

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(!canAccessCoarseLocation() || !canAccessFineLocation()){
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}

现在重写onRequestPermissionsResult

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


if(requestCode == INITIAL_REQUEST){
if (canAccessFineLocation() && canAccessCoarseLocation())  {
//call your method
}
else {
//show Toast or alert that this permissions is neccessary
}
}
}

从Android棉花糖(API 23)和以上默认禁用所有危险权限(根据官方文档官方文档)。安装后,当应用程序第一次打开时,你必须在运行时授予权限。

我通过以下方式实现了这一点:

public class MarshMallowPermission {


public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_GALLERY = 0;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_CAMERA = 1;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE = 2;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
public static final int LOCATION_PERMISSION_REQUEST_CODE = 4;
Activity activity;
Context mContext;


public MarshMallowPermission(Activity activity) {
this.activity = activity;
this.mContext = activity;
}


public boolean checkPermissionForExternalStorage(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}


public boolean checkPermissionForCamera(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}


public boolean checkLocationPermission(){


int result = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}


public void requestPermissionForExternalStorage(int requestCode){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(mContext.getApplicationContext(), "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
}
}


public void requestPermissionForCamera(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
Toast.makeText(mContext.getApplicationContext(), "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
}
}
public void requestPermissionForLocation(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION)){
Toast.makeText(mContext.getApplicationContext(), "Location permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
}
}
}

在活动课上:

 public class MainActivity extends AppCompatActivity{


private MarshMallowPermission marshMallowPermission;


@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("NavHome", "Oncreate_nav");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


marshMallowPermission = new MarshMallowPermission(MainActivity.this);






if (!marshMallowPermission.checkPermissionForExternalStorage()) {
marshMallowPermission.requestPermissionForExternalStorage(MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE);
}
}


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


switch (requestCode) {
case MarshMallowPermission.EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE_BY_LOAD_PROFILE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {


//permission granted successfully


} else {


//permission denied


}
break;
}
}


}
  if (CommonMethod.isNetworkAvailable(MainActivity.this)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.CAMERA);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
//showing dialog to select image
callFacebook();
Log.e("permission", "granted MarshMallow");
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
}
} else {
Log.e("permission", "Not Required Less than MarshMallow Version");
callFacebook();
}
} else {
CommonMethod.showAlert("Internet Connectivity Failure", MainActivity.this);
}

我的类请求运行时权限在ActivityFragment

它还帮助你显示基本原理或打开设置,以便在用户拒绝权限(有/没有Never ask again)选项后更容易启用权限

class RequestPermissionHandler(private val activity: Activity? = null,
private val fragment: Fragment? = null,
private val permissions: Set<String> = hashSetOf(),
private val listener: Listener? = null
) {
private var hadShowRationale: Boolean = false


fun requestPermission() {
hadShowRationale = showRationaleIfNeed()
if (!hadShowRationale) {
doRequestPermission(permissions)
}
}


fun retryRequestDeniedPermission() {
doRequestPermission(permissions)
}


private fun showRationaleIfNeed(): Boolean {
val unGrantedPermissions = getPermission(permissions, Status.UN_GRANTED)
val permanentDeniedPermissions = getPermission(unGrantedPermissions, Status.PERMANENT_DENIED)
if (permanentDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowSettingRationale(unGrantedPermissions)
if (consume != null && consume) {
return true
}
}


val temporaryDeniedPermissions = getPermission(unGrantedPermissions, Status.TEMPORARY_DENIED)
if (temporaryDeniedPermissions.isNotEmpty()) {
val consume = listener?.onShowPermissionRationale(temporaryDeniedPermissions)
if (consume != null && consume) {
return true
}
}
return false
}


fun requestPermissionInSetting() {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val packageName = activity?.packageName ?: run {
fragment?.requireActivity()?.packageName
}
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
activity?.apply {
startActivityForResult(intent, REQUEST_CODE)
} ?: run {
fragment?.startActivityForResult(intent, REQUEST_CODE)
}
}


fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_CODE) {
for (i in grantResults.indices) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
markNeverAskAgainPermission(permissions[i], false)
} else if (!shouldShowRequestPermissionRationale(permissions[i])) {
markNeverAskAgainPermission(permissions[i], true)
}
}
var hasShowRationale = false
if (!hadShowRationale) {
hasShowRationale = showRationaleIfNeed()
}
if (hadShowRationale || !hasShowRationale) {
notifyComplete()
}
}
}


fun onActivityResult(requestCode: Int) {
if (requestCode == REQUEST_CODE) {
getPermission(permissions, Status.GRANTED).forEach {
markNeverAskAgainPermission(it, false)
}
notifyComplete()
}
}


fun cancel() {
notifyComplete()
}


private fun doRequestPermission(permissions: Set<String>) {
activity?.let {
ActivityCompat.requestPermissions(it, permissions.toTypedArray(), REQUEST_CODE)
} ?: run {
fragment?.requestPermissions(permissions.toTypedArray(), REQUEST_CODE)
}
}


private fun getPermission(permissions: Set<String>, status: Status): Set<String> {
val targetPermissions = HashSet<String>()
for (p in permissions) {
when (status) {
Status.GRANTED -> {
if (isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
Status.TEMPORARY_DENIED -> {
if (shouldShowRequestPermissionRationale(p)) {
targetPermissions.add(p)
}
}
Status.PERMANENT_DENIED -> {
if (isNeverAskAgainPermission(p)) {
targetPermissions.add(p)
}
}
Status.UN_GRANTED -> {
if (!isPermissionGranted(p)) {
targetPermissions.add(p)
}
}
}
}
return targetPermissions
}


private fun isPermissionGranted(permission: String): Boolean {
return activity?.let {
ActivityCompat.checkSelfPermission(it, permission) == PackageManager.PERMISSION_GRANTED
} ?: run {
ActivityCompat.checkSelfPermission(fragment!!.requireActivity(), permission) == PackageManager.PERMISSION_GRANTED
}
}


private fun shouldShowRequestPermissionRationale(permission: String): Boolean {
return activity?.let {
ActivityCompat.shouldShowRequestPermissionRationale(it, permission)
} ?: run {
ActivityCompat.shouldShowRequestPermissionRationale(fragment!!.requireActivity(), permission)
}
}


private fun notifyComplete() {
listener?.onComplete(getPermission(permissions, Status.GRANTED), getPermission(permissions, Status.UN_GRANTED))
}


private fun getPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences("SHARED_PREFS_RUNTIME_PERMISSION", Context.MODE_PRIVATE)
}


private fun isNeverAskAgainPermission(permission: String): Boolean {
return getPrefs(requireContext()).getBoolean(permission, false)
}


private fun markNeverAskAgainPermission(permission: String, value: Boolean) {
getPrefs(requireContext()).edit().putBoolean(permission, value).apply()
}


private fun requireContext(): Context {
return fragment?.requireContext() ?: run {
activity!!
}
}


enum class Status {
GRANTED, UN_GRANTED, TEMPORARY_DENIED, PERMANENT_DENIED
}


interface Listener {
fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>)
fun onShowPermissionRationale(permissions: Set<String>): Boolean
fun onShowSettingRationale(permissions: Set<String>): Boolean
}


companion object {
const val REQUEST_CODE = 200
}
}

Activity中使用like

class MainActivity : AppCompatActivity() {
private lateinit var smsAndStoragePermissionHandler: RequestPermissionHandler


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


smsAndStoragePermissionHandler = RequestPermissionHandler(this@MainActivity,
permissions = setOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_EXTERNAL_STORAGE),
listener = object : RequestPermissionHandler.Listener {
override fun onComplete(grantedPermissions: Set<String>, deniedPermissions: Set<String>) {
Toast.makeText(this@MainActivity, "complete", Toast.LENGTH_SHORT).show()
text_granted.text = "Granted: " + grantedPermissions.toString()
text_denied.text = "Denied: " + deniedPermissions.toString()
}


override fun onShowPermissionRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this@MainActivity).setMessage("To able to Send Photo, we need SMS and" + " Storage permission")
.setPositiveButton("OK") { _, _ ->
smsAndStoragePermissionHandler.retryRequestDeniedPermission()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.dismiss()
}
.show()
return true // don't want to show any rationale, just return false here
}


override fun onShowSettingRationale(permissions: Set<String>): Boolean {
AlertDialog.Builder(this@MainActivity).setMessage("Go Settings -> Permission. " + "Make SMS on and Storage on")
.setPositiveButton("Settings") { _, _ ->
smsAndStoragePermissionHandler.requestPermissionInSetting()
}
.setNegativeButton("Cancel") { dialog, _ ->
smsAndStoragePermissionHandler.cancel()
dialog.cancel()
}
.show()
return true
}
})


button_request.setOnClickListener { handleRequestPermission() }
}


private fun handleRequestPermission() {
smsAndStoragePermissionHandler.requestPermission()
}


override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
smsAndStoragePermissionHandler.onRequestPermissionsResult(requestCode, permissions,
grantResults)
}


override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
smsAndStoragePermissionHandler.onActivityResult(requestCode)
}
}

Github上的代码

Demo

试试这个

这是在棉花糖版本中请求许可的最简单的方式。

 if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED&&ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
//TO do here if permission is granted by user
}
else
{
//ask for permission if user didnot given
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
requestPermissions(new String[]{Manifest.permission.CAMERA,Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
}

不要忘记在manifest文件中添加相同的权限

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

< >强第二种方法 检查权限是否被授予的代码?< / p >

ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}, 1);

然后重写这个方法

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
//                    grantResult[0] means it will check for the first postion permission which is READ_EXTERNAL_STORAGE
//                    grantResult[1] means it will check for the Second postion permission which is CAMERA
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(this, "Permission not Granted", Toast.LENGTH_SHORT).show();
return;
}
}
}

你可以使用我的库- NoPermission(它只是一个类)

compile 'ru.alexbykov:nopermission:1.1.1'

样本

PermissionHelper permissionHelper = new PermissionHelper(this); //don't use getActivity in fragment!


permissionHelper.check(Manifest.permission.READ_CONTACTS)
.onSuccess(this::onSuccess)
.onDenied(this::onDenied)
.onNeverAskAgain(this::onNeverAskAgain)
.run();

onRequestPermissionResult:

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

我认为api比谷歌的EasyPermissions更方便。

下面的代码可以完美地工作。我用一个例子来解释。

在我的情况下,我把权限检查单独放在一个util类,并通过特定的权限,我需要从适当的类检查。这样就可以在整个应用程序中重用权限检查util文件。

下面的代码部分显示了函数调用。在这种情况下,我请求android.Manifest.permission.READ_EXTERNAL_STORAGE权限。

//the below call is from a fragment
@OnClick(R.id.button)//butterknife implementation
public void attachPressed() {
if (PermissionUtils.hasThisPermission(getContext(), android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
onAttachPressed();
} else {
PermissionUtils.isPermissionRequestNeeded(getActivity(), this, android.Manifest.permission.READ_EXTERNAL_STORAGE, PermissionUtils.REQUEST_GROUP_STORAGE);
}
}

在上述情况下,如果允许,则检查权限,否则调用onAttachPressed();函数,则检查请求权限。

下面是在我的例子PermissionUtils中的util类中的代码

public final class PermissionUtils {


public static final int REQUEST_GROUP_STORAGE = 1508;


private PermissionUtils() {
}


public static boolean hasThisPermission(Context context, String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}


public static boolean isPermissionRequestNeeded(Activity activity, Fragment fragment, String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasThisPermission(activity, permission)) {
final String[] permissions = new String[]{permission};
if (fragment == null) {
activity.requestPermissions(permissions, requestCode);
} else {
fragment.requestPermissions(permissions, requestCode);
}
return true;
}
return false;
}
}

在请求之后,如果你想从onRequestPermissionsResult调用函数,否则你需要再次按下按钮进行函数调用。

所以只需从onRequestPermissionsResult调用它

//the below call  is from a fragment
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PermissionUtils.REQUEST_GROUP_STORAGE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onAttachPressed();
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
}

通过避免编写大量代码来获得许可的简单方法,

https://github.com/sachinvarma/EasyPermission

如何添加:

repositories {
maven { url "https://jitpack.io" }
}


implementation 'com.github.sachinvarma:EasyPermission:1.0.1'

如何获得许可:

 List<String> permission = new ArrayList<>();
permission.add(EasyPermissionList.READ_EXTERNAL_STORAGE);
permission.add(EasyPermissionList.ACCESS_FINE_LOCATION);


new EasyPermissionInit(MainActivity.this, permission);

希望能对别人有所帮助。

我使用< >强RxPermission < / >强库来请求权限。因为它是很长的代码,我们必须写请求许可。

RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity instance // Must be done during an initialization phase like onCreate
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) { // Always true pre-M
// I can control the camera now
} else {
// Oups permission denied
}
});

在你的build.gradle中添加这些依赖项

allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}


dependencies {
implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}

应用程序中任意位置的运行时权限下面是例子

use dependency
maven { url 'https://jitpack.io' }
dependencies {
implementation 'com.github.irshadsparky:PermissionLib:master-SNAPSHOT'
}

并像这样调用代码:

PermissionHelper.requestCamera(new PermissionHelper.OnPermissionGrantedListener() {
@Override
public void onPermissionGranted() {


}
});

你可以找到更多Github

我通过了所有的答案,但不满足我确切需要的答案,所以这里有一个例子,我写的,完美的工作,甚至用户单击别再问了复选框。

  1. 创建一个方法,当你想请求运行时权限时将被调用,比如readContacts(),或者你也可以有openCamera(),如下所示:

    private void readContacts() {
    if (!askContactsPermission()) {
    return;
    } else {
    queryContacts();
    } }
    

Now we need to make askContactsPermission(), you can also name it as askCameraPermission() or whatever permission you are going to ask.

    private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;


}
return false;
}

在写这个函数之前,确保你已经定义了如下实例变量:

    private View parentLayout;
private boolean contactPermissionNotGiven;;




/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;

现在是重写onRequestPermissionsResult方法的最后一步,如下所示:

/**
* Callback received when a permissions request has been completed.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}

这里我们已经完成了运行时权限,插件是openPermissionSettingDialog(),如果用户通过单击别再问了复选框永久禁用权限,则只需打开设置屏幕。方法如下:

    private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
我们错过了什么? 1. 在strings.xml

中定义使用的字符串

<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>

  1. onCreate方法中初始化parentLayout变量

    . parentLayout = findViewById(R.id.content)
  2. AndroidManifest.xml中定义所需的权限

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

  1. The queryContacts method, based on your need or the runtime permission you can call your method before which the permission was needed. in my case I simply use the loader to fetch the contact as shown below:

    private void queryContacts() {
    getLoaderManager().initLoader(0, null, this);}
    

This works great happy coding :)

将权限添加到AndroidManifest.xml .

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

检查Android版本是否需要运行时权限。

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
}

如果没有授予权限,请用户授予权限。

private void askForPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(c, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
Toast.makeText(c, "Please grant the requested permission to get your task done!", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
}
}
}

不管是否获得许可,都要做一些事情。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission with request code 1 granted
Toast.makeText(this, "Permission Granted" , Toast.LENGTH_LONG).show();
} else {
//permission with request code 1 was not granted
Toast.makeText(this, "Permission was not Granted" , Toast.LENGTH_LONG).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

运行时权限在严重耦合的活动中创建了大量样板代码。为了减少代码并使事情变得简单,你可以使用德克斯特库。

android运行时权限

private static final int PERMISSION_REQ_WRITE_EXTERNAL_STORAGE = 101;


public void onClick(View view) {
if (view.getId() == yourBtn.getId()) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
this.storageWork();
} else {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, PERMISSION_REQ_WRITE_EXTERNAL_STORAGE);
}
}
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQ_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
this.storageWork();
}
}
}


public void storageWork(){
}

OnClick方法是检查运行时权限

如果权限受限,则请求权限

如果你正在使用AndroidX Activity 1.2.0AndroidX Fragment 1.3.0:

有新的活动结果api,你可以用来请求权限:

val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
// Permission granted. Do the tasks.
}
}
launcher.launch(Manifest.permission.ACCESS_FINE_LOCATION)

我从我的旧代码中找到了一个解决方案,它真的很好,仍然在我的最新应用程序上工作。

把它放在MainActivity类或Start Activity类上

private RequestPermissionHandler mRequestPermissionHandler;

在创建

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRequestPermissionHandler = new RequestPermissionHandler();
handleButtonClicked();
}

私有函数handleButtonClicked()

private void handleButtonClicked() {
mRequestPermissionHandler.requestPermission(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.WAKE_LOCK


}, 123, new RequestPermissionHandler.RequestPermissionListener() {
@Override
public void onSuccess() {
//Toast.makeText(MainActivity.this, "request permission success", Toast.LENGTH_SHORT).show();
}


@Override
public void onFailed() {
Toast.makeText(MainActivity.this, "request permission failed", Toast.LENGTH_SHORT).show();
}
});


}

RequestPermissionHandler.java类

import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;


import java.util.ArrayList;
import java.util.List;


import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;


public class RequestPermissionHandler {
private Activity mActivity;
private RequestPermissionListener mRequestPermissionListener;
private int mRequestCode;


public void requestPermission(Activity activity, @NonNull String[] permissions, int requestCode,
RequestPermissionListener listener) {
mActivity = activity;
mRequestCode = requestCode;
mRequestPermissionListener = listener;


if (!needRequestRuntimePermissions()) {
mRequestPermissionListener.onSuccess();
return;
}
requestUnGrantedPermissions(permissions, requestCode);
}


private boolean needRequestRuntimePermissions() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}


private void requestUnGrantedPermissions(String[] permissions, int requestCode) {
String[] unGrantedPermissions = findUnGrantedPermissions(permissions);
if (unGrantedPermissions.length == 0) {
mRequestPermissionListener.onSuccess();
return;
}
ActivityCompat.requestPermissions(mActivity, unGrantedPermissions, requestCode);
}


private boolean isPermissionGranted(String permission) {
return ActivityCompat.checkSelfPermission(mActivity, permission)
== PackageManager.PERMISSION_GRANTED;
}


private String[] findUnGrantedPermissions(String[] permissions) {
List<String> unGrantedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (!isPermissionGranted(permission)) {
unGrantedPermissionList.add(permission);
}
}
return unGrantedPermissionList.toArray(new String[0]);
}


public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == mRequestCode) {
if (grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
mRequestPermissionListener.onFailed();
return;
}
}
mRequestPermissionListener.onSuccess();
} else {
mRequestPermissionListener.onFailed();
}
}
}


public interface RequestPermissionListener {
void onSuccess();


void onFailed();
}
}

这样就行了:

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CONTACTS}, 0);
}