Android 在程序運(yùn)行時(shí)申請(qǐng)權(quán)限的實(shí)例講解
這里我們以撥打電話申請(qǐng)權(quán)限來(lái)寫(xiě)個(gè)小例子,也就是CALL_PHONE,因?yàn)閾艽螂娫挄?huì)涉及用戶手機(jī)的資費(fèi)問(wèn)題,因而被列為了危險(xiǎn)權(quán)限,在Android6.0系統(tǒng)出現(xiàn)之前,撥打電話功能的實(shí)現(xiàn)其實(shí)非常簡(jiǎn)單,修改activity_mainxml中的代碼,如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.runtimepermissiontest.MainActivity"> <Button android:id="@+id/make_call" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Make Call" android:textAllCaps="false"/> </android.support.constraint.ConstraintLayout>
我們?cè)诓季治募兄欢x了一個(gè)按鈕,當(dāng)點(diǎn)擊按鈕時(shí)就會(huì)去觸發(fā)撥打電話的邏輯,接著修改MainActivity中的代碼,如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button makeCall = findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10000"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
});
}
}
可以看到,在按鈕的點(diǎn)擊事件中,我們構(gòu)建了一個(gè)隱式Intent,Intent的action指定為Intent.ACTION_CALL,這是一個(gè)系統(tǒng)內(nèi)置的打電話的動(dòng)作,然后在data部分指定了協(xié)議是tel,號(hào)碼是10000,表示打開(kāi)撥號(hào)界面,這個(gè)是不需要聲明權(quán)限的,而Intent.ACTION_CALL則可以直接撥打電話,因此必須申明權(quán)限,另外為了防止程序崩潰,我們將所有操作都放在了異常捕獲代碼塊當(dāng)中。
那么接下來(lái)修改AndroidManifest.xml文件,在其中聲明如下權(quán)限:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.runtimepermissiontest"> <uses-permission android:name="android.permission.CALL_PHONE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
這樣我們就將撥打電話的功能實(shí)現(xiàn)了,并且在低于Android6.0系統(tǒng)的手機(jī)上都是可以正常運(yùn)行的,但是如果我們?cè)?.0或者更高版本系統(tǒng)的手機(jī)上運(yùn)行,點(diǎn)擊Make Call按鈕就沒(méi)有任何效果,這時(shí)觀察logcat中的日志,會(huì)報(bào)如下錯(cuò)誤:

錯(cuò)誤信息中提示我們Permission Denial,可以看出,是由于權(quán)限被禁止所導(dǎo)致的,因?yàn)?.0及以上系統(tǒng)在使用危險(xiǎn)權(quán)限時(shí)都必須進(jìn)行運(yùn)行時(shí)權(quán)限處理。
那么下面我們就來(lái)嘗試修復(fù)這個(gè)問(wèn)題,修改MainActivity中的代碼,如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button makeCall = findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1);
}else {
call();
}
}
});
}
private void call(){
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10000"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
call();
}else {
Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
}
上面的代碼將運(yùn)行權(quán)限的完成流程都覆蓋了,下面我們來(lái)具體解析一下,說(shuō)白了,運(yùn)行時(shí)權(quán)限的核心就是在程序運(yùn)行過(guò)程中由用戶授權(quán)我們?nèi)?zhí)行某些危險(xiǎn)操作,程序是不可以擅自做主去執(zhí)行這些危險(xiǎn)操作的,因此,第一步就是要去判斷用戶是不是已經(jīng)給過(guò)我們授權(quán)了,借助的是ContextCompat.checkSelfPermission()方法,checkSelfPermission()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是Context,這個(gè)沒(méi)什么好說(shuō)的,第二個(gè)參數(shù)是具體的權(quán)限名,比如打電話的權(quán)限名就是Manifest.permission.CALL_PHONE,然后使用方法的返回值和packageManager.PERMISSION_CRANTED做比較,相等就說(shuō)明用戶已經(jīng)授權(quán),不等就表示用戶沒(méi)有授權(quán)。
如果已經(jīng)授權(quán)的話就簡(jiǎn)單了,直接去執(zhí)行撥打電話的邏輯操作就可以了,這里我們把撥打電話的邏輯封裝到call()方法中,如果沒(méi)有授權(quán)的話,則需要調(diào)用ActivityCompat.requestPermissions()方法來(lái)向用戶申請(qǐng)授權(quán),requestPermissions()方法接收3個(gè)參數(shù),第一個(gè)參數(shù)要求是Activity的實(shí)例,第二個(gè)參數(shù)是一個(gè)String數(shù)組,我們把要申請(qǐng)的權(quán)限名放在數(shù)組中即可,第三個(gè)參數(shù)是請(qǐng)求碼,只要是唯一值就可以了,這里傳入1。
調(diào)用完了requestPermissions()方法之后,系統(tǒng)會(huì)彈出一個(gè)申請(qǐng)權(quán)限的對(duì)話框,然后用戶可以選擇同意或拒絕我們的權(quán)限申請(qǐng),不論是哪種結(jié)果,最終都會(huì)回調(diào)到onRequestPermissionsResult()方法中,而授權(quán)的結(jié)果則封裝在grantResults參數(shù)當(dāng)中,這里我們只需要判斷一下最后的授權(quán)結(jié)果,如果用戶同意的話就調(diào)用call()方法來(lái)?yè)艽螂娫?,如果用戶拒絕的話我們只能放棄操作,并且彈出一條失敗提示。
現(xiàn)在重新運(yùn)行一下程序,并點(diǎn)擊Make Call按鈕,效果如圖:
由于用戶還沒(méi)有授權(quán)過(guò)我們撥打電話權(quán)限,因此第一次運(yùn)行會(huì)彈出這樣一個(gè)權(quán)限申請(qǐng)的對(duì)話框,用戶可以選擇同意或者拒絕,比如說(shuō)這里點(diǎn)擊了DENY,結(jié)果如圖:

由于用戶沒(méi)有同意授權(quán),我們只能彈出一個(gè)操作失敗的提示,下面我們?cè)俅吸c(diǎn)擊Make Call,任然會(huì)彈出權(quán)限申請(qǐng)的對(duì)話框,這次點(diǎn)擊ALLOW,結(jié)果如圖:

可以看到,這次我們就成功進(jìn)入到撥打電話界面了,并且由于用戶已經(jīng)完成了授權(quán)操作,之后再點(diǎn)擊Make Call按鈕就不會(huì)再?gòu)棾鰴?quán)限申請(qǐng)對(duì)話框了,而是可以直接撥打電話,那可能你會(huì)擔(dān)心,萬(wàn)一以后我又后悔了怎么辦?沒(méi)有關(guān)系,用戶隨時(shí)都可以將授予程序的危險(xiǎn)權(quán)限進(jìn)行關(guān)系,進(jìn)入Settings-->Apps-->RuntimePermissiontTest-->Permissions,界面如圖:

在這里我們就可以對(duì)任何授予過(guò)的危險(xiǎn)權(quán)限進(jìn)行關(guān)閉了。
以上這篇Android 在程序運(yùn)行時(shí)申請(qǐng)權(quán)限的實(shí)例講解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Android超清晰6.0權(quán)限申請(qǐng)AndPermission
- android 6.0 寫(xiě)入SD卡的權(quán)限申請(qǐng)實(shí)例講解
- Android手動(dòng)檢查并申請(qǐng)權(quán)限方法
- Android 6.0 藍(lán)牙搜索不到設(shè)備原因,MIUI權(quán)限申請(qǐng)機(jī)制方法
- android6.0權(quán)限動(dòng)態(tài)申請(qǐng)框架permissiondispatcher的方法
- React-Native之Android(6.0及以上)權(quán)限申請(qǐng)?jiān)斀?/a>
- Android 6.0動(dòng)態(tài)權(quán)限申請(qǐng)教程
- Android 如何實(shí)現(xiàn)動(dòng)態(tài)申請(qǐng)權(quán)限
相關(guān)文章
android編程之下拉刷新實(shí)現(xiàn)方法分析
這篇文章主要介紹了android編程之下拉刷新實(shí)現(xiàn)方法,以實(shí)例形式詳細(xì)分析了Android編程中針對(duì)ListView下拉刷新的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Android實(shí)現(xiàn)通話自動(dòng)錄音
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)通話自動(dòng)錄音,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
Android BroadcastReceiver接收收到短信的廣播
這篇文章主要為大家詳細(xì)介紹了Android BroadcastReceiver接收收到短信的廣播,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
Android實(shí)現(xiàn)類(lèi)似ios滑動(dòng)按鈕
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)類(lèi)似ios滑動(dòng)按鈕,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
詳解Android中OkHttp3的例子和在子線程更新UI線程的方法
本篇文章主要介紹了詳解Android中OkHttp3的例子和在子線程更新UI線程的方法 ,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05
Android事件分發(fā)機(jī)制(上) ViewGroup的事件分發(fā)
這篇文章主要為大家詳細(xì)介紹了Android ViewGroup的事件分發(fā)機(jī)制上篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android 中使用ExpandableListView 實(shí)現(xiàn)分組的實(shí)例
這篇文章主要介紹了Android 中使用ExpandableListView 實(shí)現(xiàn)分組的實(shí)例的相關(guān)資料,這里提供實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-12-12
Java中的final關(guān)鍵字詳解及實(shí)例
這篇文章主要介紹了Java中的final關(guān)鍵字詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-01-01

