運行時權限申請開發(fā)精要

主要參考Hongyang大神的這篇文章
//Android 6.0 運行時權限處理完全解析
http://blog.csdn.net/lmj623565791/article/details/50709663

概念

Android 6.0 (API level 23) 引入了運行時權限這個機制, 在之前的Android版本中, 開發(fā)者在AndroidManifest.xml中聲明所有的權限, 用戶在安裝apk時進行確認是否同意, 只有在同意后才能成功安裝應用, 這就造成了一些權限濫用的問題, 比如很多app會聲明去訪問手機聯(lián)系人, 位置定位等用戶敏感信息的權限. 而實際上, 這些app本不應該去具有這些權限.
針對這種情況, Android 6.0 把權限劃分為普通權限和危險權限, 對于普通權限, 比如訪問網(wǎng)絡, 和之前的機制是一樣的. 對于危險權限, 一方面要求開發(fā)者在AndroidManifest.xml中進行聲明, 讓用戶在安裝應用時進行確認, 另一方面, 在app運行時, 當用到特定功能時, 比如要獲取用戶的位置信息, Android 系統(tǒng)還會再次談出一個對話框詢問用戶是否同意這一行為, 這也就是運行時權限這個名字的來源.

代碼框架

MainActivity.java
以獲取位置數(shù)據(jù)為例, 正常的代碼流程是:

private static final int PERMISSION_REQUEST_LOCATION = 0;


    private void getGPSInfo() {
//檢查是否用戶之前是否同意過這個運行時權限
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//之前沒有同意過這個對話框的話, requestPermissions()會觸發(fā)系統(tǒng)以異步的方式彈出一個對話框進行確認, 回調(diào)在onRequestPermissionsResult()中.
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                    PERMISSION_REQUEST_LOCATION);
        } else {
//之前同意過這個對話框的話, 下一步去實際獲取位置數(shù)據(jù).
            getCityByGpsInfo();
        }

    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        JLog.i();
        if (requestCode == PERMISSION_REQUEST_LOCATION) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//用戶在系統(tǒng)對話框中選擇同意的話, 下一步去實際獲取位置數(shù)據(jù).
                getCityByGpsInfo();
            } else {
                // Permission Denied
                Toast.makeText(MainActivity.this, "location Permission Denied", Toast.LENGTH_SHORT).show();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

//去實際獲取用戶的位置數(shù)據(jù)
    private void getCityByGpsInfo() {
        double latitude = 0.0;
        double longitude = 0.0;

        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        Location gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        JLog.i("gpsLocation: " + gpsLocation);
        if (gpsLocation != null) {
            latitude = gpsLocation.getLatitude();
            longitude = gpsLocation.getLongitude();
        } else {
            Location networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            JLog.i("networkLocation: " + networkLocation);
            if (networkLocation != null) {
                latitude = networkLocation.getLatitude();
                longitude = networkLocation.getLongitude();

            } else {
                JLog.i("gps和network都沒有獲取到位置信息.");
                return;
            }

        }
    }
機型適配的問題
  1. 在Android 6.0 以下的手機上, 因為沒有運行時權限這個機制, 執(zhí)行ActivityCompat.checkSelfPermission() 都會返回0, 也就是PackageManager.PERMISSION_GRANTED.
  2. 在國內(nèi)的某些機型上, 比如Oppo Android 6.0以上的手機, 它把運行時權限這個機制進行了修改. 執(zhí)行ActivityCompat.checkSelfPermission()會立刻返回0, 把系統(tǒng)的運行時權限彈框移到了真正獲取位置數(shù)據(jù)的API內(nèi)部, 也就是在locationManager.getLastKnownLocation()內(nèi)部, 提供了一個默認彈窗, 并且是以阻塞UI的方式. 如果用戶選擇拒絕的話, 這個API返回null. 如果用戶選擇同意的話, 下次再調(diào)用locationManager.getLastKnownLocation() API的時候也就不會再次彈窗讓用戶進行確認了.

---DONE.---

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容