Android如何動態申請應用權限?


2019-10-23

關鍵字: APK申請權限、通過代碼獲取權限、定位權限、相機權限


 

這篇文章大部分的內容都搬自簡書某位大神的博客: https://www.jianshu.com/p/e36f686588d6 。搬運的目的有二:一是方便自己后續查閱,二是添加一些自己的使用經驗。感謝這位簡書大神的奉獻。

 

APK 開發中的權限主要有三種:

1、普通權限;

2、危險權限;

3、特殊權限;

這三種不同類型的權限都是單獨針對APK用的。這些權限的背后代表着一款 APK 的功能完整性。越靠后的權限 Android 系統對其的把控就越嚴格。

 

1、普通權限

 

普通權限就是那些可以直接在 AndroidManifest.xml 中配置一下即可獲得的權限。系統對它們的管理非常寬松。

 

常見的有使用網絡、更改網絡狀態等。

 

2、危險權限

 

危險權限除了要在 AndroidManife.xml 中聲明以外,還得額外通過代碼或用戶主動在系統權限管理設置中開啟。下圖是華為手機中某個應用的部分常用危險權限控制界面:

 

 

危險權限的各類如下表所示

權限組 權限詳情
CALENDAR

READ_CALENDAR

WRITE_CALENDAR

CAMERA CAMERA
CONTACTS

READ_CONTACTS

WRIGE_CONTACTS

GET_ACCOUNTS

LOCATION

ACCESS_FINE_LOCATION

ACCESS_CONARSE_LOCATION

MICROPHONE RECORD_AUDIO
PHONE

READ_PHONE_STATE

CALL_PHONE

READ_CALL_LOG

WRITE_CALL_LOG

ADD_VOICEMAIL

USE_SIP

PROCESS_OUTGOING_CALLS

SENSORS BODY_SENSORS
SMS

SEND_SMS

RECEIVE_SMS

READ_SMS

RECEIVE_WAP_PUSH

RECEIVE_MMS

STORAGE

READ_EXTERNAL_STORAGE

WRITE_EXTERNAL_STORAGE

 

關於危險權限的限制,不同的 ROM 有不同的做法,有的嚴格有的寬松。但在 APK 開發中,為了應用的兼容性,還是很有必要去檢查這些權限的狀態,並在有必要的情況下彈出申請彈窗。

 

1、權限狀態檢查

 
         
import androidx.core.content.ContextCompat;
int perm = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

以上代碼用於檢查當前 APK 是否擁有使用攝像頭的權限。它的返回值是一個整型。這個整型有兩個值:PackageManager.PERMISSION_GRANTED 與 PackageManager.PERMISSION_DENIED ,分別代表着有權限與無權限。通常我們會根據當前權限的狀態來決定是否去申請相關權限。

 

2、申請危險權限

ActivityCompat.requestPermissions(this, new String[]{
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.CAMERA
    }, 0);

當執行了這段代碼以后,會有兩種情況:一種是所申請的權限在當前應用中確實沒有。另一種是所申請的權限在當前應用中已擁有。

 

對於第一種情況,執行以后會發現系統將會彈出如下圖所示的彈窗供用戶選擇:

 

 

對於第二種情況,執行以后系統不會有任何變化,一切就像沒有發生過什么一樣。

 

當權限申請結果出來以后,系統會通過回調 Activity 中的以下方法來回傳結果:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == 0) {
        try {
            for(int i = 0; i < permissions.length; i++) {
                Logger.d(TAG, permissions[i] + ":" + grantResults[i]);
            }

        }catch(Exception e){
            e.printStackTrace();
        }
    }

}

這段代碼就遍歷了所有申請的權限的結果,當然結果值僅會有值為數字 0 的 PackageManager.PERMISSION_GRANTED 以及值為數字 -1 的 PackageManager.PERMISSION_DENIED。

 

3、特殊權限

 

特殊權限主要包括:

1、通知欄;

2、自動啟動;

3、懸浮窗;

4、無障礙輔助。

 

略。

 

 

4、注意事項

 

在申請危險權限時有一些注意事項必須要提一下。

 

由於權限申請結果是回調到 Activity 的 onRequestPermissionsResult 方法中的,所以我們通常都會直接在 Activity 里來做申請操作。

 

當你執行了權限申請代碼以后,即執行了 ActivityCompat.requestPermissions(this, new String[]{}, 0); 以后,無論上面圖片所示的權限彈窗是否彈出,當前 Activity 的狀態都會進入到 onPause() 態。並且在權限申請結果出來以后,Activity 會回到 onResume() 態,即這一申請過程會導致 onPause() 與 onResume() 被執行一次。

 

如果你有在這兩個方法中做一些邏輯操作的話,一定要注意處理一下這種額外的調用。

 

筆者就是因為將權限申請操作放在 onResume() 中做的,導致了這個權限申請一直在無限調用。

 


參考:https://www.jianshu.com/p/e36f686588d6  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM