PermissionsDispatcher,Android 6.0 運(yùn)行時(shí)權(quán)限

image

運(yùn)行時(shí)權(quán)限

從 Android 6.0(API 級(jí)別 23)開始,用戶開始在應(yīng)用運(yùn)行時(shí)向其授予權(quán)限,而不是在應(yīng)用安裝時(shí)授予。

系統(tǒng)權(quán)限分為兩類:

  • 正常權(quán)限:只需在你應(yīng)用的 Androidmanifest.xml 中列出,安裝時(shí)授權(quán)。
  • 危險(xiǎn)權(quán)限:需要在你應(yīng)用的 Androidmanifest.xml 中列出,并在運(yùn)行時(shí)授權(quán)。

如需了解更多關(guān)于正常權(quán)限與危險(xiǎn)權(quán)限可以參閱這里。

關(guān)于 Android 6.0 運(yùn)行時(shí)權(quán)限的詳細(xì)講解可以看這篇文章官方文檔

運(yùn)行時(shí)權(quán)限的加入增加了用戶隱私的安全,但同時(shí)也給開發(fā)者帶來了一些負(fù)擔(dān),因?yàn)槎嗔藱z查權(quán)限,請(qǐng)求權(quán)限,處理權(quán)限請(qǐng)求響應(yīng)的步驟。

于是就出現(xiàn)了一些框架,用于簡(jiǎn)化運(yùn)行時(shí)權(quán)限的處理,如 PermissionsDispatcher,DexterRxPermissions,easypermissions 等。

這里只用過 easypermissions 和 PermissionsDispatcher,最終選擇了 PermissionsDispatcher,原因是使用人數(shù)最多,api 設(shè)計(jì)簡(jiǎn)單易用,兼容性較好,easypermissions 使用起來相對(duì)麻煩一些。

PermissionsDispatcher

PermissionsDispatcher 提供簡(jiǎn)單的基于注解的 api 處理 Android Marshmallow 下的運(yùn)行時(shí)權(quán)限(非反射方式)。

項(xiàng)目地址:https://github.com/hotchemi/PermissionsDispatcher

一. 集成說明

注意把 ${latest.version} 改為最新版本。

打開命令行,cd 到工程根目錄,執(zhí)行 gradlew -version 或者 gradlew -v 命令查看當(dāng)前工程 gradle 版本。

根據(jù) gradle 版本進(jìn)行如下配置:

Android Gradle Plugin >= 2.2

在 app 模塊下的 build.gradle 添加下面的配置:

dependencies {
  compile 'com.github.hotchemi:permissionsdispatcher:${latest.version}'
  annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:${latest.version}'
}

Android Gradle Plugin < 2.2

在 project-level 下的 build.gradle 添加下面配置:

buildscript {
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

然后,在 app 模塊下的 build.gradle 添加下面配置:

apply plugin: 'android-apt'

dependencies {
  compile 'com.github.hotchemi:permissionsdispatcher:${latest.version}'
  apt 'com.github.hotchemi:permissionsdispatcher-processor:${latest.version}'
}

二. 使用說明

1. 添加注解

注意:注解的方法不能是 private 的。

相關(guān)注解說明

注解 是否必須 描述
@RuntimePermissions ? 注冊(cè)一個(gè) ActivityFragment 用于處理權(quán)限
@NeedsPermission ? 注解一個(gè)方法,說明需要什么權(quán)限(一個(gè)或多個(gè))
@OnShowRationale 注解一個(gè)方法,解釋為什么需要這些權(quán)限
@OnPermissionDenied 注解一個(gè)方法,當(dāng)用戶拒絕授權(quán)時(shí)將調(diào)用該方法
@OnNeverAskAgain 注解一個(gè)方法,當(dāng)用戶選擇了 "不再提醒" 將調(diào)用該方法

示例代碼

@RuntimePermissions 
public class MainActivity extends AppCompatActivity {

    // 單個(gè)權(quán)限
    // @NeedsPermission(Manifest.permission.CAMERA)
    // 多個(gè)權(quán)限
    @NeedsPermission({ Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO })
    void showCamera() {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
                .addToBackStack("camera")
                .commitAllowingStateLoss();
    }
    
    // 向用戶說明為什么需要這些權(quán)限(可選)
    @OnShowRationale(Manifest.permission.CAMERA)
    void showRationaleForCamera(final PermissionRequest request) {
        new AlertDialog.Builder(this)
            .setMessage(R.string.permission_camera_rationale)
            .setPositiveButton(R.string.button_allow, (dialog, button) -> request.proceed())
            .setNegativeButton(R.string.button_deny, (dialog, button) -> request.cancel())
            .show();
    }

    // 用戶拒絕授權(quán)回調(diào)(可選)
    @OnPermissionDenied(Manifest.permission.CAMERA)
    void showDeniedForCamera() {
        Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show();
    }

    // 用戶勾選了“不再提醒”時(shí)調(diào)用(可選)
    @OnNeverAskAgain(Manifest.permission.CAMERA)
    void showNeverAskForCamera() {
        Toast.makeText(this, R.string.permission_camera_neverask, Toast.LENGTH_SHORT).show();
    }
}

2. 調(diào)用自動(dòng)生成的輔助類

注解寫好后,Build ——> Make Module ***,PermissionsDispatcher 會(huì)生成一個(gè) MainActivityPermissionsDispatcher(Activity Name + PermissionsDispatcher),你可以使用它來安全地訪問這些受權(quán)限保護(hù)的方法。

你唯一需要做的一件事是將工作委托給這個(gè)輔助類:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    findViewById(R.id.button_camera).setOnClickListener(v -> {
      // 調(diào)用帶權(quán)限檢查的 showCamera 方法
      MainActivityPermissionsDispatcher.showCameraWithCheck(this);
    });
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    // 代理權(quán)限處理到自動(dòng)生成的方法
    MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}

*PermissionDispatcher.*WithCheck 方法對(duì)你原來的方法進(jìn)行了包裝,包了一層權(quán)限檢查的代碼,你需要做的就是把原來的方法調(diào)用改為 *PermissionDispatcher.*WithCheck。另外,在 onRequestPermissionsResult 中回調(diào) *PermissionsDispatcher.onRequestPermissionsResult 方法。

三. 獲取特殊權(quán)限

兩個(gè)特殊權(quán)限:

  • Manifest.permission.SYSTEM_ALERT_WINDOW:顯示懸浮窗
  • Manifest.permission.WRITE_SETTINGS:讀寫系統(tǒng)設(shè)置

對(duì)于這兩個(gè)權(quán)限,在 Android 下默認(rèn)是需要到 Settings -> Apps 中手動(dòng)授權(quán)的。由于不同 ROM 情況可能還有點(diǎn)不一樣。

PermissionsDispatcher 對(duì)于兩個(gè)特殊權(quán)限也做了兼容處理(Android6.0+),使用方法如上一樣。

如果需要兼容低版本的 Android 系統(tǒng)或者不同 ROM 可以參考這個(gè)開源項(xiàng)目

四. maxSdkVersion

<uses-permission> 有一個(gè) maxSdkVersion 屬性,PermissionsDispatcher 對(duì)它也做了支持。

比如,在 Androidmanifest.xml 中定義了如下權(quán)限:

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

注解中添加 maxSdkVersion

@RuntimePermissions
public class MainActivity extends AppCompatActivity {

    @NeedsPermission(value = Manifest.permission.WRITE_EXTERNAL_STORAGE, maxSdkVersion = 18)
    void getStorage() {
        // ...
    }
    
}

PermissionsDispatcher Plugin

PermissionsDispatcher Plugin 是 PermissionsDispatcher 的輔助插件,支持自動(dòng)生成權(quán)限檢查相關(guān)代碼。

項(xiàng)目地址:https://github.com/shiraji/permissions-dispatcher-plugin

安裝說明:Android Studio 中打開 Setting,Plugins ——> Browse repositories... 搜索 PermissionsDispatcher plugin,點(diǎn) Install 下載安裝,安裝完成后重啟生效。

image
image

使用說明:

  1. 在 Activity/Fragment 中,Generate -> Generate Runtime Permissions...
  2. 選擇權(quán)限并為每個(gè)注解輸入方法名
  3. 點(diǎn)擊 Generate ,完成

使用過程中發(fā)現(xiàn)有兩個(gè)小問題需要注意一下:

  1. 多次生成代碼,onRequestPermissionsResult 方法也會(huì)被自動(dòng)添加多次
  2. 代碼生成后會(huì)提示你是否 rebuild 工程,建議選擇取消,Build ——> Make Module *** 相對(duì)快些
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容