在Html5代码已经移植至Android工程后,完成Android App开发的基本框架之权限设置部分的代码设计与开发;
1、在AndroidManifest.xml中定义需要使用到的权限,如本项目中使用的权限如下:
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> allPermission = new HashMap>();
Set locationPermission = new HashSet();
locationPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
locationPermission.add(Manifest.permission.ACCESS_COARSE_LOCATION);
allPermission.put(Constant.LOCATION_PERMISSION_CODE, locationPermission);
Set audioPermission = new HashSet();
audioPermission.add(Manifest.permission.RECORD_AUDIO);
allPermission.put(Constant.RECORD_PERMISSION_CODE, audioPermission);
Set cameraPermission = new HashSet();
cameraPermission.add(Manifest.permission.CAMERA);
allPermission.put(Constant.CAMERA_PERMISSION_CODE, cameraPermission);
Set storagePermission = new HashSet();
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 requestedPermissionCode;
private Set grantPermissionCode;
private Map> allPermission;
private PermissionMgr()
{
requestedPermissionCode = new HashSet();
grantPermissionCode = new HashSet();
}
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> 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> ungrantPermission = new HashMap>();
ungrantPermission.putAll(allPermission);
ungrantPermission.keySet().removeAll(requestedPermissionCode);
Log.i(TAG, "Left permission:" + ungrantPermission.keySet());
requestLeftPermission(activity, ungrantPermission);
}
/**
* 是否已经申请了足够的权限
*
* @return
*/
public boolean hasRequestAllPermission()
{
Map> ungrantPermission = new HashMap>();
ungrantPermission.putAll(allPermission);
ungrantPermission.keySet().removeAll(requestedPermissionCode);
return ungrantPermission.isEmpty();
}
/**
* 请求剩余权限
*
* @param activity
* @param allPermission
*/
private void requestLeftPermission(Activity activity, Map> allPermission)
{
for (Map.Entry> entry : allPermission.entrySet())
{
int grantPermission = -1;
boolean isLocationPermission = false;
int requestCode = entry.getKey();
Set 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 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 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 getLocationProvider(Activity activity)
{
LocationManager locationManager = (LocationManager)activity.getSystemService(Activity.LOCATION_SERVICE);
Criteria criteria = new Criteria();
List 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 下一篇:Vue.js实战——开发Android Hybird App之Webview基础配置_12