1. 程式人生 > >android6.0之下apk執行正常,6.0之後突然一直報需要某個許可權且apk崩潰

android6.0之下apk執行正常,6.0之後突然一直報需要某個許可權且apk崩潰

https://developers.google.com/android/guides/permissions

問題描述:一個apk在6.0之下執行正常,但是在6.0上執行一直崩潰,並且提示需要某個許可權,但是該許可權已經在AndroidMainfest.xml中宣告。當apk安裝的時候,彈出一個可以允許和拒絕許可權的彈框,如果在這裡執行該apk使用該許可權,則apk則執行正常,否則繼續崩潰。

猜測及思路:6.0也許引入了一個新的許可權管理機制,apk所需要的許可權可以讓使用者手動允許和拒絕。

                        崩潰的原因是apk所需要的許可權被拒絕了,相應的獲取操作出現了異常。那麼如何在程式碼中檢測該許可權呢?如果檢測到沒有該許可權則不執行相應的daim

android6.0棉花軟糖有一個新的使app安裝和自動更新更加有效的許可權模式。現在的許可權是在執行時請求而不是在apk被安裝之前,使用者可以選擇允許或拒絕某一項特定的許可權。為了實現這個靈活性,你的apk需要確保當用戶允許或拒絕某一項特定的許可權後apk執行正常。

前提:

1.API  level和目標SDK設定在23+

2.確保使用了Support V4:com.android.support:support-v4:23.0.0

3.所需要的的許可權還是需要在AndroidMainfest.xml中正常宣告

<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"
/>

指南:

1.如果你在AndroidMainfest.xml中聲明瞭一個許可權,那麼在呼叫API方法之前,通過ActivityCompat或者ContextCompat的checkSerlfPermission()方法來檢測你是否有相應的請求許可權。如果返回false說明該許可權沒有被使用者允許,你需要通過requestPermissions()方法重新請求這些許可權。返回的結果可以在回撥方法中獲取

if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager
.PERMISSION_GRANTED){// Check Permissions NowActivityCompat.requestPermissions(this,newString[]{Manifest.permission.ACCESS_FINE_LOCATION},
        REQUEST_LOCATION
);}else{// permission has been granted, continue as usualLocation myLocation =LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);}

2.實現請求許可權的回撥

如果你所需要的許可權沒有被使用者允許,requestPermission()方法將會回撥詢問使用者是否允許這些許可權。使用者執行的結果將在回撥onRequestPermissionsResult()中被返回。由於許可權請求可能會被拒絕或者取消,所以你應該實現該回調並在呼叫相應API時進行檢查。下面的程式碼只是檢測了一個單獨的許可權請求,你也可以一次檢測多個許可權請求。

publicvoid onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){if(requestCode == REQUEST_LOCATION){if(grantResults.length ==1&& grantResults[0]==PackageManager.PERMISSION_GRANTED){// We can now safely use the API we requested access toLocation myLocation =LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);}else{// Permission was denied or request was cancelled}}}
3.顯示需要該許可權的原因

如果你的apk的核心功能需要某個許可權,但是該許可權又被使用者拒絕了,在再次請求許可權之前,你需要展示一個額外的說明給使用者。當用戶明白為何需要該許可權時,他們更傾向於允許該許可權。

在這種請求下,你需要先呼叫shouldShowRequestPermissionRationale()方法,然後再呼叫requestPermissions()方法。如果返回true,你需要新建一個介面用於展示為什麼需要該許可權。

if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED){// Check Permissions Nowprivatestaticfinalint REQUEST_LOCATION =2;if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)){// Display UI and wait for user interaction}else{ActivityCompat.requestPermissions(this,newString[]{Manifest.permission.LOCATION_FINE},
    ACCESS_FINE_LOCATION
);}}else{// permission has been granted, continue as usualLocation myLocation =LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);}

4.處理異常

如果你的apk使用了GoogleApiClient,並且呼叫了connect()方法,GooglePlay services會檢測它所需要的每一項許可權。在GooglePlay service8.1及其之後,如果所需許可權中的任何一項缺失,connect()將會返回false。


如果你呼叫connect()失敗,確保你的app正確處理所產生的異常。如果缺失了Google Play service所需要的異常,你可以通過startResolutionForResult()來重新初始化來解決

@Overridepublicvoid onConnectionFailed(ConnectionResult result){if(mResolvingError){// Already attempting to resolve an error.return;}elseif(result.hasResolution()){try{
            mResolvingError
=true;
            result
.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);}catch(SendIntentException e){// There was an error with the resolution intent. Try again.
            mGoogleApiClient
.connect();}}else{// Show dialog using GooglePlayServicesUtil.getErrorDialog()
        showErrorDialog
(result.getErrorCode());
        mResolvingError
=true;}}