Android 動態權限最全解析

在這裏插入圖片描述
在這裏插入圖片描述

動態權限概述

Android6.0 開始,Google調整了應用的權限申請方案。調整之後將權限分級,分成了普通權限危險權限,普通權限的授權方式跟之前一樣,只需要在Manifest文件中申明即可,危險權限不僅需要在Manifest文件中聲明,還需要在程序中調用官方提供的Api主動申請。

動態權限分類

Android6.0 以後,一共將動態權限分成了9組,每組只要有一個權限申請成功了,就默認整組權限都可以使用了。這九組權限分別如下:

權限組名稱 權限組 權限組權限成員
讀寫聯繫人 group:android.permission-group.CONTACTS permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS
電話 group:android.permission-group.PHONE permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAIL
日曆信息 group:android.permission-group.CALENDAR permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR
相機 group:android.permission-group.CAMERA permission:android.permission.CAMERA
傳感器 group:android.permission-group.SENSORS permission:android.permission.BODY_SENSORS
地理位置 group:android.permission-group.LOCATION permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION
存儲卡 group:android.permission-group.STORAGE permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE
多媒體 group:android.permission-group.MICROPHONE permission:android.permission.RECORD_AUDIO
SMS group:android.permission-group.SMS permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS

動態權限申請方法

方法1:官方API提供的方法

步驟1:檢查是否有權限

由於低於API 23 是不需要使用動態權限申請的,我們需要先判斷一下系統版本,代碼如下是Android 6.0以上的系統還是Android 6.0以下的系統。用ContextCompat類中的checkSelfPermission方法進行是否有權限判斷。

public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
    if (permission == null) {
        throw new IllegalArgumentException("permission is null");
    }

    return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());
}

具體使用方法如下:

if (Build.VERSION.SDK_INT >= 23) {
  if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
              != PackageManager.PERMISSION_GRANTED) {
              //無該權限,需要申請
      }
} else { //低於23 不需要處理

}

步驟2:申請權限

在步驟的的checkSelfPermission方法中如果判斷沒有權限,就需要用到ActivityCompat類中的requestPermissions方法進行動態權限申請,該方法需要傳一個需要申請權限名稱的權限permissions數組。

public static void requestPermissions(final @NonNull Activity activity,
         final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {
}

申請方法如下:先定一個需要申請權限的權限數組PERMISSIONS_STORAGE

private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE",
        "android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);

步驟3:回調函數的處理

由於權限申請是異步的,用戶完成了以後,需要回調函數處理,
Activity中提供了一個回調處理方法onRequestPermissionsResult,只需要重寫該方法即可
case 中的參數REQUEST_EXTERNAL_STORAGE 即步驟2申請權限中定一個的參數

 @Override
 public void onRequestPermissionsResult(int requestCode,
                                        String permissions[], int[] grantResults) {
     switch (requestCode) {
         case REQUEST_EXTERNAL_STORAGE: {
             if (grantResults.length > 0
                     && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                 Toast.makeText(this, "授權成功!", Toast.LENGTH_SHORT).show();
             } else {
                 Toast.makeText(this, "授權被拒絕!", Toast.LENGTH_SHORT).show();
             }
         }

     }
 }

完整代碼

在這裏插入圖片描述

我們以申請SD卡讀寫權限爲例,完整代碼如下:

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= 23) {
            checkPermission();
        }
    }


    private void checkPermission() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission
                    .WRITE_EXTERNAL_STORAGE)) {
                Toast.makeText(this, "請開通相關權限,否則無法正常使用本應用!", Toast.LENGTH_SHORT).show();
            }
            //申請權限
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);

        } else {
            Toast.makeText(this, "已授權成功!", Toast.LENGTH_SHORT).show();
            dothings();
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_EXTERNAL_STORAGE: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    dothings();
                    Toast.makeText(this, "授權成功!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "授權被拒絕!", Toast.LENGTH_SHORT).show();
                }
            }

        }
    }

    public void dothings() {

    }
}

AndroidManifest.xml聲明權限

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

方法2:RxPermission

RxPermission 可以幫助開發者簡化獲取權限的相關處理操作,而且內部也自動幫我們判斷了版本是否需要申請權限。同時結合RxJava可以方便的回調各種結果。
官網:https://github.com/tbruyelle/RxPermissions

引入依賴

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
 
dependencies {
    implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
     implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
}

由於rxpermissions需要用到rxjava,所有rxjava的包也一起引入。

聲明權限

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

申請單個權限

RxPermissions permissions = new RxPermissions(this);
permissions.request(Manifest.permission.CAMERA)
       .subscribe(new Consumer<Boolean>() {
           @Override
           public void accept(Boolean aBoolean)  {
               if (aBoolean ) {
                   Toast.makeText(MainActivity.this, "授權成功!", Toast.LENGTH_SHORT).show();
               }else {
                   Toast.makeText(MainActivity.this, "授權失敗!", Toast.LENGTH_SHORT).show();
               }
           }
       });

申請多個權限

RxPermissions permissions = new RxPermissions(this);  
permissions.request(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE)
  .subscribe(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean)  {
                if (aBoolean ) {
                    Toast.makeText(MainActivity.this, "授權成功!", Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(MainActivity.this, "授權失敗!", Toast.LENGTH_SHORT).show();
                }
            }
        });

方法3:AndPermission

AndPermission跟前面的RxPermission使用方法類似
官網:https://github.com/yanzhenjie/AndPermission

引入依賴

implementation 'com.yanzhenjie:permission:2.0.3'

申請單個或多個權限

 AndPermission.with(this)
            .runtime()
            .permission(Permission.WRITE_EXTERNAL_STORAGE,Permission.CAMERA)
            .onGranted(permissions -> {
                Toast.makeText(MainActivity.this, "授權成功!", Toast.LENGTH_SHORT).show();
            })
            .onDenied(permissions -> {
                Toast.makeText(MainActivity.this, "授權失敗!", Toast.LENGTH_SHORT).show();
            })
            .start();

效果如下:在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章