Android 6.0 超級簡單的權限申請2 (Permission)


代碼地址如下:
http://www.demodashi.com/demo/13506.html

寫在前面

上次寫了一個權限申請的例子Android 6.0 超級簡單的權限申請 (Permission),原理是封裝權限申請的代碼到一個Helper類,然后重寫onRequestPermissionsResult方法處理。這已經是很簡潔的權限申請方法了,但是還不夠,因為這里還需要重寫onRequestPermissionsResult方法。所以研究了一番,再寫了一個例子,不需要重寫onRequestPermissionsResult方法,真正做到一句代碼搞定權限申請。

實現原理

封裝權限申請的相關代碼到一個Helper類中,在申請權限的時候,啟動一個Fragment,但不顯示,在Fragment中申請權限,也在Fragment中處理權限,最后回調給Helper。

實現過程

  • 封裝PermissionHelper類,定義對外開放的方法
/**
 * @param permissions e.g. {@link Manifest.permission#CAMERA}
 * @return true if all granted, false otherwise.
 */
public static boolean isGranted(Activity activity, String... permissions)

/**
 * @param grantedListener run on all permission granted
 * @param deniedListener  run if one permission denied
 */
public static void requestPermissions(Activity activity, 
    OnPermissionGrantedListener grantedListener, 
    OnPermissionDeniedListener deniedListener, 
    String... permissions)
  • 獲取AndroidManifest中注冊的權限
private static List<String> getRegisteredInManifestPermissions(Activity activity) {
    List<String> list = new ArrayList<>();
    try {
        PackageInfo packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
        String[] permissions = packageInfo.requestedPermissions;
        if (permissions != null) {
            list.addAll(Arrays.asList(permissions));
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return list;
}
  • 檢查權限是否已經注冊
for (String permission : permissions) {
    if (!mRegisteredInManifestPermissions.contains(permission)) {
        throw new IllegalArgumentException("the permission \"" + permission + "\" is not registered in AndroidManifest.xml");
    }
}
  • 檢查權限是否已經允許,AndroidM以下的設備直接判斷為允許
public static boolean isGranted(Activity activity, String... permissions) {
    checkPermissions(activity, permissions);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        for (String permission : permissions) {
            if (activity.checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
                return false;
            }
        }
    }
    return true;
}
  • 初始化Fragment並添加到Activity

這里的PermissionHelper直接繼承Fragment了,直接重寫onRequestPermissionsResult處理回調。new Fragment之前先檢查此Activity中是否已經存在一個,如果有則直接使用。

Fragment fragment = activity.getFragmentManager().findFragmentByTag(TAG);
if (fragment == null) {
    fragment = new PermissionHelper();
    FragmentManager fragmentManager = activity.getFragmentManager();
    fragmentManager.beginTransaction().add(fragment, TAG).commitAllowingStateLoss();
    fragmentManager.executePendingTransactions();
}
  • 利用Fragment申請權限
fragment.requestPermissions(permissions, mRequestCode++);
  • 處理onRequestPermissionsResult方法,並把結果正確的回調給用戶
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (mOnGrantedListeners.containsKey(requestCode)) {
        // 這里規定全部權限都通過才算通過
        boolean granted = true;
        // 在Activity A申請權限,然后馬上跳轉到Activity B,則grantResults.length=0
        if (grantResults.length == 0) granted = false;
        for (int result : grantResults) {
            if (result == PackageManager.PERMISSION_DENIED) {
                granted = false;
            }
        }
        if (granted) {
            OnPermissionGrantedListener listener = mOnGrantedListeners.get(requestCode);
            if (listener != null) listener.onGranted();
        } else {
            OnPermissionDeniedListener listener = mOnDeniedListeners.get(requestCode);
            if (listener != null) listener.onDenied();
        }
        mOnGrantedListeners.remove(mRequestCode);
        mOnDeniedListeners.remove(mRequestCode);
    }
}

使用方法

直接在Activity中調用下面代碼既可,雖然很多行,但只是一句代碼哈哈

PermissionHelper.requestPermissions(this, () -> {
    // on granted
    Toast.makeText(MainActivity.this, "onGranted", Toast.LENGTH_SHORT).show();

}, () -> {
    // on denied
    Toast.makeText(MainActivity.this, "onDenied", Toast.LENGTH_SHORT).show();

}, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE);

文件結構圖

演示效果圖

運行代碼可能出現的問題

  • compileSdkVersion 27,可以改成你電腦中存在的SDK版本。

  • 這里用的是 gradle-4.4-all.zip,如果你用的是其它版本,那么可能會下載超級慢,建議改成你電腦中存在的gradle版本,改文件PermissionHelper/gradle/wrapper/gradle-wrapper.properties即可。

  • 其它問題可以直接聯系我。
    Android 6.0 超級簡單的權限申請2 (Permission)

代碼地址如下:
http://www.demodashi.com/demo/13506.html

注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM