臨近放假了時間比較充裕,就琢磨着乾點啥,想來想去6.0運行時權限一直沒弄過而且項目也總有一天要升級的,既然這樣,那就趁熱來一發吧
那麼爲了學到原滋原味的6.0權限,官方文檔是第一選擇,這裏附上鍊接https://developer.android.com/training/permissions/index.html
關於6.0如何選擇compileSdkVersion, minSdkVersion 和 targetSdkVersion可以看我另一篇博文
如何選擇compileSdkVersion, minSdkVersion 和 targetSdkVersion
在文檔上可以看到6.0在權限上有幾處改變
- 系統權限分爲兩類
- 普通權限
正常的權限不涉及用戶的隱私風險。如果你的應用程序清單列出了一個正常的權限,系統自動授予許可。 - 危險權限
危險的權限可以讓應用程序訪問用戶的機密數據,如果列出一個危險的權限,用戶必須授權許可
- 普通權限
- 如果設備運行Android 5.1或更低,或應用程序的targetSdk是22或更低:你在清單列表申明的危險權限,用戶授予權限許可是在安裝應用程序時.(測試時候發現部分國產rom的手機在低於6.0的版本依舊是運行時授予確實強大^_^)
如果設備運行Android 6.0或更高版本,並且你的應用程序的targetSdk是23或更高:應用中危險的權限,將在應用程序運行時用戶授予。(我用的6.0系統的華爲v8測試的,如果程序的targetSdk是23或者更高,當需要使用權限的時候,系統並未自己彈起權限請求,需要自己寫代碼請求才行)
這裏列出危險權限
下面介紹api
檢查權限是否獲取
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_CALENDAR);
如果返回值 PackageManager.PERMISSION_GRANTED表示權限已經獲取,可以執行操作.如果返回值 PackageManager.PERMISSION_DENIED表示權限未授予,需要請求權限
是否需要解釋爲什麼請求該權限
ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,Manifest.permission.WRITE_CALENDAR)
在用戶拒絕過該權限並且未勾選不在提示,再次請求該權限的時候shouldShowRequestPermissionRationale方法將會返回true,這個時候可以給用戶一個獲取該權限的解釋,比如彈出一個說明.
請求權限
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
調用該方法後.系統會顯示一個標準的對話框給用戶,應用程序不能配置或者改變對話框的內容,即請求權限彈窗不能自定義.舉個栗子,如果你請求READ_CONTACTS許可,該系統對話框只是說你的應用程序需要訪問設備的聯繫人。一旦用戶同意。那麼同權限組的其他權限,系統自動賦予他們,不在彈窗提示。
此外,權限組的劃分在未來的安卓版本可能會改變,所以每一個需要權限的地方都需要請求權限,即使用戶已經允許另一個同組的權限。
結果回調
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
}
當系統要求用戶授予權限,用戶可以選擇不在詢問或者不在提醒,這種情況下系統不會彈出請求權限彈窗,而是直接回調onRequestPermissionsResult方法並且結果爲PackageManager.PERMISSION_DENIED。
用戶拒絕了權限並且勾選了不在詢問這種情況,可以在onRequestPermissionsResult回調方法中判斷,即返回結果爲PackageManager.PERMISSION_DENIED並且該權限的shouldShowRequestPermissionRationale方法返回值爲false
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if(grantResults[0] == PackageManager.PERMISSION_DENIED &&
!ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[0])){
}
}
因爲這種情況下沒法彈出系統請求權限彈窗,所以我們需要手動的寫一個dialog去引導用戶到設置界面打開權限.
這裏附上文檔中的例子
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
@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
}
}
api是不是很簡單很方便.但是實際項目中我還是使用第三方庫 哈哈哈
關於6.0權限的庫還是很多的..這裏我使用的是google官方提供的 easypermissions
使用比較簡單這裏我稍微講解下.
1.流程圖
2.sample中代碼稍加註釋提示下
public class MainActivity extends AppCompatActivity implements
EasyPermissions.PermissionCallbacks {
private static final String TAG = "MainActivity";
private static final int RC_CAMERA_PERM = 123;
private static final int RC_SETTINGS_SCREEN = 125;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Button click listener that will request one permission.
findViewById(R.id.button_camera).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cameraTask();
}
});
}
//用戶手動修改權限請求回調
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SETTINGS_SCREEN) {
// Do something after user returned from app settings screen, like showing a Toast.
Toast.makeText(this, R.string.returned_from_app_settings_to_activity, Toast.LENGTH_SHORT)
.show();
}
}
@AfterPermissionGranted(RC_CAMERA_PERM)
public void cameraTask() {
//判斷權限是否授予
if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA)) {//已經授予
// Have permission, do the thing!
Toast.makeText(this, "TODO: Camera things", Toast.LENGTH_LONG).show();
} else {//未授予
// Ask for one permission
EasyPermissions.requestPermissions(this, getString(R.string.rationale_camera),
RC_CAMERA_PERM, Manifest.permission.CAMERA);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// EasyPermissions handles the request result.
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);//權限回調傳給EasyPermissions.onRequestPermissionsResult(),他會根據權限獲取成功與否回調onPermissionsGranted()與onPermissionsDenied
}
//獲取權限成功回調
@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
}
//獲取權限失敗回調
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
// 判斷是否拒絕了權限請求並且勾選了不在提示,如果是將會彈出引導手動設置權限的dialog,引導用戶到設置中心手動修改權限
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this, getString(R.string.rationale_ask_again))
.setTitle(getString(R.string.title_settings_dialog))
.setPositiveButton(getString(R.string.setting))
.setNegativeButton(getString(R.string.cancel), null /* click listener */)
.setRequestCode(RC_SETTINGS_SCREEN)
.build()
.show();
}
}
}
到此基本就介紹的差不多啦.有什麼疑問歡迎留言,今天是祖國母親生日的第一天,祝大家國慶快樂