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

 

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