Android6.0M許可權管理實戰,完美輕量級封裝

NO IMAGE

轉載請註明出處:http://blog.csdn.net/linglongxin24/article/details/53189359
本文出自【DylanAndroid的部落格】


Android6.0M許可權管理實戰,完美輕量級封裝

隨著Android版本的不斷更新,Android再許可權管理方面的詬病越來越明顯。Google的Android開發人員也意識到了Android應用在許可權管理方面的各種問題,讓好多使用者摸不著頭腦就使用了使用者的隱私資料。
為了在許可權這方面加強管理,給使用者一個比較好的體驗。Android 6.0代號M的釋出徹底解決了這一問題,取而代之的做法是這樣的:
app在執行時逐個詢問使用者授予許可權。Android 6.0(api23)M系統中,做了一些限制, 開發者在使用到每條許可權時必須自己呼叫相關程式碼請求使用者授予許可權。如果沒有獲得某項許可權,直接使用相關功能,則會導致自己程式crash.。為了解決這方面的問題,我們每次請求某一個許可權要寫好多程式碼解決這個問題,非常的麻煩。
下面是我做的一個輕量級的封裝,可以減少很多重複的工作。

效果圖
請求許可權

使用者禁止了許可權

一.Android6.0M對許可權的劃分

Android6.0M中對使用者的許可權分為了一般許可權和危險許可權,這些危險許可權除了在AndroidManifest.xml中註冊以外,還需要在使用的時候對使用者進行請求許可權彈窗提醒,才可以使用。
這些危險許可權如下:

二.封裝一個MPermissionsActivity的思路和步驟

  • 第一步:檢測所有的許可權是否都已授權
   /**
* 檢測所有的許可權是否都已授權
*
* @param permissions
* @return
*/
private boolean checkPermissions(String[] permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
  • 第二步:獲取許可權集中需要申請許可權的列表
 /**
* 獲取許可權集中需要申請許可權的列表
*
* @param permissions
* @return
*/
private List<String> getDeniedPermissions(String[] permissions) {
List<String> needRequestPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED ||
ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
needRequestPermissionList.add(permission);
}
}
return needRequestPermissionList;
}
  • 第三步:請求許可權
  /**
* 請求許可權
*
* @param permissions 請求的許可權
* @param requestCode 請求許可權的請求碼
*/
public void requestPermission(String[] permissions, int requestCode) {
this.REQUEST_CODE_PERMISSION = requestCode;
if (checkPermissions(permissions)) {
permissionSuccess(REQUEST_CODE_PERMISSION);
} else {
List<String> needPermissions = getDeniedPermissions(permissions);
ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION);
}
}
  • 第四步:處理許可權請求回撥
  /**
* 系統請求許可權回撥
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_PERMISSION) {
if (verifyPermissions(grantResults)) {
permissionSuccess(REQUEST_CODE_PERMISSION);
} else {
permissionFail(REQUEST_CODE_PERMISSION);
showTipsDialog();
}
}
}
  • 第五步:檢視處理許可權請求回撥使用者是否已經授權
 /**
* 確認所有的許可權是否都已授權
*
* @param grantResults
* @return
*/
private boolean verifyPermissions(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
  • 第六步:授權成功處理函式
  /**
* 獲取許可權成功
*
* @param requestCode
*/
public void permissionSuccess(int requestCode) {
Log.d(TAG, "獲取許可權成功="   requestCode);
}
  • 第七步:授權失敗處理函式與彈出使用者提示

/**
* 許可權獲取失敗
* @param requestCode
*/
public void permissionFail(int requestCode) {
Log.d(TAG, "獲取許可權失敗="   requestCode);
}
/**
* 顯示提示對話方塊
*/
private void showTipsDialog() {
new AlertDialog.Builder(this)
.setTitle("提示資訊")
.setMessage("當前應用缺少必要許可權,該功能暫時無法使用。如若需要,請單擊【確定】按鈕前往設定中心進行許可權授權。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
}).show();
}
  • 第八步:授權失敗給使用者提示後想再次開啟跳到設定app許可權介面
    /**
* 啟動當前應用設定頁面
*/
private void startAppSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:"   getPackageName()));
startActivity(intent);
}

三.完整的MPermissionsActivity程式碼

package cn.bluemobi.dylan.mpermissions;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.NonNull;
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.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yuandl on 2016-11-16.
*/
public class MPermissionsActivity extends AppCompatActivity {
private final String TAG = "MPermissions";
private int REQUEST_CODE_PERMISSION = 0x00099;
/**
* 請求許可權
*
* @param permissions 請求的許可權
* @param requestCode 請求許可權的請求碼
*/
public void requestPermission(String[] permissions, int requestCode) {
this.REQUEST_CODE_PERMISSION = requestCode;
if (checkPermissions(permissions)) {
permissionSuccess(REQUEST_CODE_PERMISSION);
} else {
List<String> needPermissions = getDeniedPermissions(permissions);
ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION);
}
}
/**
* 檢測所有的許可權是否都已授權
*
* @param permissions
* @return
*/
private boolean checkPermissions(String[] permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 獲取許可權集中需要申請許可權的列表
*
* @param permissions
* @return
*/
private List<String> getDeniedPermissions(String[] permissions) {
List<String> needRequestPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED ||
ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
needRequestPermissionList.add(permission);
}
}
return needRequestPermissionList;
}
/**
* 系統請求許可權回撥
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_PERMISSION) {
if (verifyPermissions(grantResults)) {
permissionSuccess(REQUEST_CODE_PERMISSION);
} else {
permissionFail(REQUEST_CODE_PERMISSION);
showTipsDialog();
}
}
}
/**
* 確認所有的許可權是否都已授權
*
* @param grantResults
* @return
*/
private boolean verifyPermissions(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 顯示提示對話方塊
*/
private void showTipsDialog() {
new AlertDialog.Builder(this)
.setTitle("提示資訊")
.setMessage("當前應用缺少必要許可權,該功能暫時無法使用。如若需要,請單擊【確定】按鈕前往設定中心進行許可權授權。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
}).show();
}
/**
* 啟動當前應用設定頁面
*/
private void startAppSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:"   getPackageName()));
startActivity(intent);
}
/**
* 獲取許可權成功
*
* @param requestCode
*/
public void permissionSuccess(int requestCode) {
Log.d(TAG, "獲取許可權成功="   requestCode);
}
/**
* 許可權獲取失敗
* @param requestCode
*/
public void permissionFail(int requestCode) {
Log.d(TAG, "獲取許可權失敗="   requestCode);
}
}

四.用法

  • 佈局檔案activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@ id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="cn.bluemobi.dylan.mpermissions.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Button
android:id="@ id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick1"
android:text="打電話" />
<Button
android:id="@ id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick2"
android:text="寫SD卡" />
<Button
android:id="@ id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick3"
android:text="拍照" />
</LinearLayout>
  • MainActivity中使用:繼承MPermissionsActivity即可
package cn.bluemobi.dylan.mpermissions;
import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends MPermissionsActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 打電話
*
* @param view
*/
public void onClick1(View view) {
requestPermission(new String[]{Manifest.permission.CALL_PHONE}, 0x0001);
}
/**
* 寫SD卡
*
* @param view
*/
public void onClick2(View view) {
requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x0002);
}
/**
* 拍照
*
* @param view
*/
public void onClick3(View view) {
requestPermission(new String[]{Manifest.permission.CAMERA}, 0x0003);
}
/**
* 許可權成功回撥函式
*
* @param requestCode
*/
@Override
public void permissionSuccess(int requestCode) {
super.permissionSuccess(requestCode);
switch (requestCode) {
case 0x0001:
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:13468857714"));
startActivity(intent);
break;
}
}
}

五.GitHub