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;}}