Vue.js實戰——開發Android Hybird App之權限設置_11

一、目標

    在Html5代碼已經移植至Android工程後,完成Android App開發的基本框架之權限設置部分的代碼設計與開發;

二、步驟

    1、在AndroidManifest.xml中定義需要使用到的權限,如本項目中使用的權限如下:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />

    2、配置以後,需要在代碼中去檢查是否有權限,核心代碼如下:

                int resultPermission = ContextCompat.checkSelfPermission(activity, permission);

    該返回值爲PackageManager.PERMISSION_GRANTED時,表示已經授權,否則需要下一步去申請權限;

    3、申請權限核心代碼:

ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)

    注意:shouldShowRequestPermissionRationale爲異步方法,負責調取一個申請授權的彈窗,如果同時申請多個這種權限的彈窗,則只彈出第一個,後面的彈窗直接跳過。

    4、獲取授權結果,需要基於請求權限的請求碼,在MainActivity中的onRequestPermissionsResult回調方法中去處理;

    5、上面基於第3步,由於多次彈窗被跳過了,則需要調用第3步的申請權限方法,繼續申請下一個權限項,直到所有權限申請完畢;

    6、基於上述邏輯,彙總下核心代碼邏輯(完整代碼見github):

MainActivity中與權限相關的代碼:

package com.justinsoft.activity;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.justinsoft.R;
import com.justinsoft.constant.Constant;
import com.justinsoft.permission.PermissionMgr;
import com.justinsoft.util.LogUtil;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class MainActivity extends AppCompatActivity {
    // 日誌句柄
    private static final String TAG = LogUtil.getClassTag(MainActivity.class);

    private BtWebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 1.打開權限設置
        loadPermission(this);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        Log.i(TAG, "update permission now.");
        PermissionMgr permissionMgr = PermissionMgr.getInstance();
        permissionMgr.updatePermission(this, requestCode, permissions, grantResults);
        if (permissionMgr.hasRequestAllPermission()) {
            refreshHomepage();
        }
    }

    /**
     * 檢查並請求打開權限設置
     *
     * @param activity
     */
    private void loadPermission(Activity activity) {
        Map<Integer, Set<String>> allPermission = new HashMap<Integer, Set<String>>();

        Set<String> locationPermission = new HashSet<String>();
        locationPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
        locationPermission.add(Manifest.permission.ACCESS_COARSE_LOCATION);
        allPermission.put(Constant.LOCATION_PERMISSION_CODE, locationPermission);

        Set<String> audioPermission = new HashSet<String>();
        audioPermission.add(Manifest.permission.RECORD_AUDIO);
        allPermission.put(Constant.RECORD_PERMISSION_CODE, audioPermission);

        Set<String> cameraPermission = new HashSet<String>();
        cameraPermission.add(Manifest.permission.CAMERA);
        allPermission.put(Constant.CAMERA_PERMISSION_CODE, cameraPermission);

        Set<String> storagePermission = new HashSet<String>();
        storagePermission.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        storagePermission.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        allPermission.put(Constant.STORAGE_PERMISSION_CODE, storagePermission);

        PermissionMgr.getInstance().requestPermission(activity, allPermission);
    }
}

抽取的權限管理類PermissionMgr:

package com.justinsoft.permission;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.justinsoft.util.LogUtil;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;

public final class PermissionMgr
{
    // 日誌標記
    private static final String TAG = LogUtil.getClassTag(PermissionMgr.class);
    
    // 權限管理
    private static PermissionMgr permissionMgr;
    
    private static final Lock LOCK = new ReentrantLock();
    
    private Set<Integer> requestedPermissionCode;
    
    private Set<Integer> grantPermissionCode;
    
    private Map<Integer, Set<String>> allPermission;
    
    private PermissionMgr()
    {
        requestedPermissionCode = new HashSet<Integer>();
        grantPermissionCode = new HashSet<Integer>();
    }
    
    public static PermissionMgr getInstance()
    {
        if (null == permissionMgr)
        {
            LOCK.tryLock();
            try
            {
                if (null == permissionMgr)
                {
                    permissionMgr = new PermissionMgr();
                }
                return permissionMgr;
            }
            catch (Exception e)
            {
                Log.e(TAG, "failed to get permission", e);
            }
            finally
            {
                LOCK.unlock();
            }
        }
        return permissionMgr;
    }
    
    /**
     * 請求權限
     *
     * @param activity
     * @param allPermission
     */
    public void requestPermission(Activity activity, Map<Integer, Set<String>> allPermission)
    {
        this.allPermission = allPermission;
        requestLeftPermission(activity, allPermission);
    }
    
    /**
     * 判斷權限請求結束後,是否獲取到權限
     *
     * @param activity
     * @param requestCode
     * @param permissions
     * @param grantResults
     * @return
     */
    public void updatePermission(Activity activity, int requestCode, String permissions[], int[] grantResults)
    {
        Log.i(TAG, "request permission code:" + requestCode);
        Log.i(TAG, "all permission code:" + allPermission.keySet());
        Log.i(TAG, "all permission:" + permissions);
        if (!allPermission.keySet().contains(requestCode))
        {
            Log.i(TAG, "invalid permission");
            return;
        }
        requestedPermissionCode.add(requestCode);
        
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
        {
            // permission was granted, yay! Do the
            // contacts-related task you need to do.
            Log.i(TAG, "grant permission now:" + requestCode);
            grantPermissionCode.add(requestCode);
        }
        else
        {
            // permission denied, boo! Disable the
            // functionality that depends on this permission.
            Log.i(TAG, "no permission now:" + requestCode);
        }
        
        Map<Integer, Set<String>> ungrantPermission = new HashMap<Integer, Set<String>>();
        ungrantPermission.putAll(allPermission);
        ungrantPermission.keySet().removeAll(requestedPermissionCode);
        Log.i(TAG, "Left permission:" + ungrantPermission.keySet());
        requestLeftPermission(activity, ungrantPermission);
    }
    
    /**
     * 是否已經申請了足夠的權限
     *
     * @return
     */
    public boolean hasRequestAllPermission()
    {
        Map<Integer, Set<String>> ungrantPermission = new HashMap<Integer, Set<String>>();
        ungrantPermission.putAll(allPermission);
        ungrantPermission.keySet().removeAll(requestedPermissionCode);
        return ungrantPermission.isEmpty();
    }
    
    /**
     * 請求剩餘權限
     * 
     * @param activity
     * @param allPermission
     */
    private void requestLeftPermission(Activity activity, Map<Integer, Set<String>> allPermission)
    {
        for (Map.Entry<Integer, Set<String>> entry : allPermission.entrySet())
        {
            int grantPermission = -1;
            boolean isLocationPermission = false;
            int requestCode = entry.getKey();
            Set<String> batchPermission = entry.getValue();
            for (String permission : batchPermission)
            {
                int resultPermission = ContextCompat.checkSelfPermission(activity, permission);
                if (resultPermission == PackageManager.PERMISSION_GRANTED)
                {
                    this.requestedPermissionCode.add(requestCode);
                    grantPermission = PackageManager.PERMISSION_GRANTED;
                }
                
                if (permission.equalsIgnoreCase(Manifest.permission.ACCESS_FINE_LOCATION)
                    || permission.equalsIgnoreCase(Manifest.permission.ACCESS_COARSE_LOCATION))
                {
                    isLocationPermission = true;
                }
            }
            
            if (grantPermission != PackageManager.PERMISSION_GRANTED)
            {
                boolean result = shouldPermission(activity, batchPermission);
                if (isLocationPermission)
                {
                    List<String> allProvider = getLocationProvider(activity);
                    if (null == allProvider || allProvider.isEmpty())
                    {
                        result = false;
                    }
                }
                if (!result)
                {
                    Log.i(TAG, "It needs to request permission now.");
                    ActivityCompat.requestPermissions(activity, batchPermission.toArray(new String[] {}), requestCode);
                }
                return;
            }
        }
    }
    
    private boolean shouldPermission(Activity activity, Set<String> batchPermission)
    {
        for (String permission : batchPermission)
        {
            if (!this.requestedPermissionCode.contains(permission))
            {
                if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission))
                {
                    Log.i(TAG, "grant permission:" + permission);
                    return true;
                }
            }
        }
        return false;
    }
    
    private List<String> getLocationProvider(Activity activity)
    {
        LocationManager locationManager = (LocationManager)activity.getSystemService(Activity.LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        List<String> allProviderName = locationManager.getProviders(criteria, true);
        Log.i(TAG, "provider:" + allProviderName);
        return allProviderName;
    }
}

三、總結

    權限申請是Android開發的基本訴求之一,在開發過程中,先是一股腦全申請了彈窗,結果發現只彈了一次就不彈了,後面就想到在Activity中的回調方法onRequestPermissionsResult中繼續申請下一個權限,終於達成一個接一個彈窗的目標;

四、參考資料

[1]https://www.cnblogs.com/Free-Thinker/p/6014765.html

 

上一篇:Vue.js實戰——移植Html5 App爲Android App_10

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章