Vue.js实战——开发Android(安卓)Hybird App之权限设置_11
一、目标
在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
更多相关文章
- Android程序的签名保护及绕过方法
- android悬浮窗及权限
- AOSP: 如何恢复出厂设置?
- Android高手进阶教程(八)之----Android(安卓)Widget开发案例(世
- 跟Android初学者分享几点经验
- Android(安卓)自定义权限 ( )
- android中webview控件和javascript交互实例
- Android:Dagger2系列2 实例解析(更新完毕)
- android分享图片到微信,无需申请APP_ID