摘要:和以前在安裝的是就申請(qǐng)了權(quán)限不同,在,也就之后加入了動(dòng)態(tài)權(quán)限。對(duì)于一些敏感的權(quán)限,決定權(quán)交還給了用戶,不再是強(qiáng)制申請(qǐng)了。還有辦法可以補(bǔ)救一下,就是跳轉(zhuǎn)到設(shè)置頁(yè)面,讓用戶手動(dòng)開啟權(quán)限。網(wǎng)上有個(gè)一個(gè)流行的開源庫(kù),采用注解來快速實(shí)現(xiàn)以上的邏輯。
和以前在安裝 APP 的是就申請(qǐng)了權(quán)限不同,Google 在 API 23,也就 6.0 之后加入了動(dòng)態(tài)權(quán)限。對(duì)于一些敏感的權(quán)限,決定權(quán)交還給了用戶,不再是強(qiáng)制申請(qǐng)了。因?yàn)檫@個(gè)原因,如果 APP 需要支持 6.0 以上的系統(tǒng),就需要進(jìn)行一下適配,否則 APP 就會(huì)崩潰。
比如,下面撥打電話.。已經(jīng)在在 AndroidManifest.xml 中申明權(quán)限了
這是撥打電話的代碼實(shí)現(xiàn)
private void callPhone() { Intent intent = new Intent(Intent.ACTION_CALL); Uri data = Uri.parse("tel:" + "12312341234"); intent.setData(data); startActivity(intent); }
但是程序如果是在 Android 6.0 的設(shè)備中運(yùn)行的話,一運(yùn)行就崩潰了,報(bào)錯(cuò)信息如下
java.lang.SecurityException: Permission Denial: ... 后面的信息省略
那么要怎么才能適配呢?
動(dòng)態(tài)權(quán)限有哪些?首先要先知道動(dòng)態(tài)權(quán)限有哪些?
Andriod 中的動(dòng)態(tài)權(quán)限是按組來分的,下面的表格來自官網(wǎng)
每個(gè)組中的權(quán)限不用全部申請(qǐng),申請(qǐng)了其中一個(gè),組中其他權(quán)限也就一起申請(qǐng)到了。
怎么申請(qǐng)動(dòng)態(tài)權(quán)限?有個(gè)前提,我們的 Activity 比如 MainActivity 不再是繼承于 Acticity 了,而是繼承于 AppCompatActivity,因?yàn)閯?dòng)態(tài)權(quán)限的一些方法是只有 AppCompatActivity 才有的。
首先是檢測(cè)是否已經(jīng)賦予了權(quán)限,可以調(diào)用 ContextCompat.checkSelfPermission(Context, permissionName) 方法,通過方法的返回值來判斷
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) { // 已經(jīng)賦予權(quán)限,直接調(diào)用撥打電話的代碼 callPhone(); } else { // 沒有賦予權(quán)限,那就去申請(qǐng)權(quán)限 }
要申請(qǐng)權(quán)限可以使用 requestPermissions (Activity activity, String[] permissions, int requestCode) 進(jìn)行申請(qǐng)
private static final int REQUEST_CALL_PHONE = 456; ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL_PHONE);
于是在界面上就會(huì)彈出一個(gè)請(qǐng)求撥打電話權(quán)限的對(duì)話框(這個(gè)對(duì)話框是系統(tǒng)彈出來的,樣式不可修改)
不管用戶選擇同意還是拒絕,都會(huì)在 onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 方法中接收到信息
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_CALL_PHONE: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 權(quán)限請(qǐng)求成功 callPhone(); } else { // 用戶拒絕了 showTipDialog(); } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void showTipDialog() { new AlertDialog.Builder(this) .setMessage("該程序需要電話權(quán)限,否則無法正常運(yùn)行") .setPositiveButton(android.R.string.ok, null) .create() .show(); }
如果用戶選擇”同意“,就可以調(diào)用撥打電話的按鈕,同時(shí)這個(gè)對(duì)話框之后都不會(huì)出現(xiàn)了。
如果用戶拒絕了,那就無法調(diào)用撥打電話的代碼了。為了用戶體驗(yàn),可以彈出一個(gè)對(duì)話框,告知用戶我需要這個(gè)權(quán)限,沒有這個(gè)權(quán)限程序無法正常運(yùn)行
用戶看到了這個(gè)信息,于是再次點(diǎn)擊“撥打電話”的按鈕,程序又進(jìn)行了權(quán)限檢查,彈出申請(qǐng)權(quán)限的對(duì)話框,這時(shí)候的對(duì)話框的和之前第一次進(jìn)行權(quán)限申請(qǐng)時(shí)彈出的對(duì)話框的樣式不同,多出了一個(gè)“不再提醒”的勾選項(xiàng)
如果用戶勾選“不再詢問”,對(duì)話框是這樣的
意味著用戶永遠(yuǎn)地拒絕撥打電話的權(quán)限,同時(shí)這個(gè)對(duì)話框不會(huì)再?gòu)棾鰜砹耍@就造成程序無法正常運(yùn)行。還有辦法可以補(bǔ)救一下,就是跳轉(zhuǎn)到設(shè)置頁(yè)面,讓用戶手動(dòng)開啟權(quán)限。Anroid 提供了一個(gè)方法 ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE) 可以用來判斷是否選擇了“不再提示”
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_CALL_PHONE: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 權(quán)限請(qǐng)求成功 callPhone(); } else { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) { // 用戶選擇了“拒絕” showTipDialog(); } else { // 用戶勾選了“不再提示” goToSetting(); } } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void goToSetting() { new AlertDialog.Builder(this) .setMessage("該程序需要電話權(quán)限,否則無法正常運(yùn)行") .setPositiveButton("去打開權(quán)限", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } }) .create() .show(); }完整代碼
public class MainActivity extends AppCompatActivity { private static final int REQUEST_CALL_PHONE = 456; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_capture).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { callPhoneWithCheck(); } }); } private void callPhone() { Intent intent = new Intent(Intent.ACTION_CALL); Uri data = Uri.parse("tel:" + "12312341234"); intent.setData(data); startActivity(intent); } private void callPhoneWithCheck() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) { // 已經(jīng)賦予權(quán)限 callPhone(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL_PHONE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_CALL_PHONE: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 權(quán)限請(qǐng)求成功 callPhone(); } else { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) { // 用戶選擇了“拒絕” showTipDialog(); } else { // 用戶勾選了“不再提示” goToSetting(); } } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void goToSetting() { new AlertDialog.Builder(this) .setMessage("該程序需要電話權(quán)限,否則無法正常運(yùn)行") .setPositiveButton("去打開權(quán)限", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } }) .create() .show(); } private void showTipDialog() { new AlertDialog.Builder(this) .setMessage("該程序需要電話權(quán)限,否則無法正常運(yùn)行") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL_PHONE); } }) .create() .show(); } }開源庫(kù)
為了申請(qǐng)一個(gè)撥打電話的權(quán)限,要寫好多代碼。網(wǎng)上有個(gè)一個(gè)流行的開源庫(kù) PermissionsDispatcher,采用注解來快速實(shí)現(xiàn)以上的邏輯。用法很簡(jiǎn)單,就是需要注意到是,寫完代碼是需要編譯一下 project,這樣才能生成相應(yīng)的代碼。
參考來源http://blog.csdn.net/zhangqinghuazhangzhe/article/details/52801202
http://www.jianshu.com/p/d6b3e16cc1d9
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1110/3670.html
http://www.jianshu.com/p/b4a8b3d4f587
http://blog.csdn.net/quan356270259/article/details/50876272
http://blog.csdn.net/u010483016/article/details/50401605
http://www.jianshu.com/p/e1ab1a179fbb#
http://blog.csdn.net/u011200604/article/details/52874599
http://blog.csdn.net/yangqingqo/article/details/48371123
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70503.html
閱讀 2112·2023-04-26 00:41
閱讀 1142·2021-09-24 10:34
閱讀 3573·2021-09-23 11:21
閱讀 4031·2021-09-22 15:06
閱讀 1557·2019-08-30 15:55
閱讀 897·2019-08-30 15:54
閱讀 1829·2019-08-30 15:48
閱讀 550·2019-08-29 13:58