我們的app一般都會需要緩存和一些圖片的存儲,當(dāng)然我們的目錄可以是自己的私有目錄,getExternalCacheDir
或者getCacheDir
是不需要權(quán)限的,但是如果需要在sd卡下存儲呢,此時(shí)需要WRITE_EXTERNAL_STORAGE
權(quán)限.實(shí)際上WRITE_EXTERNAL_STORAGE
權(quán)限對于我們開發(fā)者來說是一個(gè)基礎(chǔ)權(quán)限,一些IO操作都會用到,但是在6.0中屬于危險(xiǎn)權(quán)限,是需要?jiǎng)討B(tài)申請的(在manifest
聲明無效)
由于緩存很可能在進(jìn)入app的時(shí)候就需要,所以應(yīng)用啟動(dòng)后需要盡快獲取到該權(quán)限,否則可能引起崩潰(6.0機(jī)型).
這里采用的方案是在MainActivity
(或者啟動(dòng)頁)申請這項(xiàng)權(quán)限,盡量讓用戶授權(quán)
處理WRITE_EXTERNAL_STORAGE權(quán)限
如果對6.0運(yùn)行時(shí)權(quán)限還不太了解的,可以參考我的上一篇文章Android6.0運(yùn)行時(shí)權(quán)限解決方案
- 效果圖
- 代碼:
直接在MainActivity
的onCreate
中申請權(quán)限,以下為申請存儲權(quán)限的模板
/*<=======================================全局基礎(chǔ)權(quán)限申請=================================================>*/
/**
* 申請全局都需要的權(quán)限,如讀寫權(quán)限,這些權(quán)限是進(jìn)入app就需要的,拒絕則警告用戶程序可能會崩潰
*/
private void initGlobalPer() {
MainActivityPermissionsDispatcher.sucessWithCheck(this);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);//將回調(diào)交給代理類處理
}
@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void sucess() {//權(quán)限申請成功
}
@OnShowRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void showRationaleForCamera(PermissionRequest request) {
showRationaleDialog("為了達(dá)到更好的用戶體驗(yàn),我們會進(jìn)行緩存及文件存儲操作,需要您授予相關(guān)的存儲權(quán)限!\n請您放心,該權(quán)限為正常使用權(quán)限,不會涉及到您的隱私!\n稍后請點(diǎn)擊彈出框的允許按鈕", request);
}
@OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void onCameraDenied() {//被拒絕
IToast.show("您拒絕了權(quán)限,可能會導(dǎo)致該應(yīng)用內(nèi)部發(fā)生錯(cuò)誤,請盡快授權(quán)");
}
@OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void onCameraNeverAskAgain() {//被拒絕并且勾選了不再提醒
if (!IoHelper.getIoDontAsk()) AskForPermission();
}
/**
* 再用戶拒絕過一次之后,告知用戶具體需要權(quán)限的原因
*
* @param messageResId
* @param request
*/
private void showRationaleDialog(String messageResId, final PermissionRequest request) {
new AlertDialog.Builder(this)
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(@NonNull DialogInterface dialog, int which) {
request.proceed();//請求權(quán)限
}
})
.setTitle("請求權(quán)限")
.setCancelable(false)
.setMessage(messageResId)
.show();
}
/**
* 被拒絕并且不再提醒,提示用戶去設(shè)置界面重新打開權(quán)限
*/
private void AskForPermission() {
new AlertDialog.Builder(this)
.setTitle("缺少基礎(chǔ)存儲權(quán)限")
.setMessage("當(dāng)前應(yīng)用缺少存儲權(quán)限,請去設(shè)置界面授權(quán).\n授權(quán)之后按兩次返回鍵可回到該應(yīng)用哦")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
IToast.show("您拒絕了權(quán)限,可能會導(dǎo)致該應(yīng)用內(nèi)部發(fā)生錯(cuò)誤,請盡快授權(quán)");
}
})
.setNeutralButton("不在提醒", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
IoHelper.putIoDontAsk(true);
IToast.show("將不再提醒請求基礎(chǔ)權(quán)限,建議盡快授權(quán)");
}
}).setPositiveButton("設(shè)置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName())); // 根據(jù)包名打開對應(yīng)的設(shè)置界面
startActivity(intent);
}
}).create().show();
}
/*<========================================================================================>*/
- 在
MainActivity
中獲取到存儲權(quán)限,可以很好的避免因?yàn)榫彺娴茸x寫權(quán)限問題引起的崩潰.
關(guān)于作者
- 簡 書:uncochen
- github:ChenZhen
- 新浪微博:@Chen丶振
- Email:18620156376@163.com