android 权限申请 自动获取权限

@TargetApi(23)
	private void requestPermissions() {
		PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {
			@Override
			public void onGranted() {
//				Toast.makeText(MainActivity.this, "All permissions have been granted", Toast.LENGTH_SHORT).show();
			}

			@Override
			public void onDenied(String permission) {
				//Toast.makeText(MainActivity.this, "Permission " + permission + " has been denied", Toast.LENGTH_SHORT).show();
			}
		});
	}

public class PermissionsManager {

  private static final String TAG = PermissionsManager.class.getSimpleName();

  private final Set<String> mPendingRequests = new HashSet<String>(1);
  private final Set<String> mPermissions = new HashSet<String>(1);
  private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<WeakReference<PermissionsResultAction>>(1);

  private static PermissionsManager mInstance = null;

  public static PermissionsManager getInstance() {
    if (mInstance == null) {
      mInstance = new PermissionsManager();
    }
    return mInstance;
  }

  private PermissionsManager() {
    initializePermissionsMap();
  }

  /**
   * This method uses reflection to read all the permissions in the Manifest class.
   * This is necessary because some permissions do not exist on older versions of Android,
   * since they do not exist, they will be denied when you check whether you have permission
   * which is problematic since a new permission is often added where there was no previous
   * permission required. We initialize a Set of available permissions and check the set
   * when checking if we have permission since we want to know when we are denied a permission
   * because it doesn't exist yet.
   */
  private synchronized void initializePermissionsMap() {
    Field[] fields = Manifest.permission.class.getFields();
    for (Field field : fields) {
      String name = null;
      try {
        name = (String) field.get("");
      } catch (IllegalAccessException e) {
        Log.e(TAG, "Could not access field", e);
      }
      mPermissions.add(name);
    }
  }

  /**
   * This method retrieves all the permissions declared in the application's manifest.
   * It returns a non null array of permisions that can be declared.
   *
   * @param activity the Activity necessary to check what permissions we have.
   * @return a non null array of permissions that are declared in the application manifest.
   */
  @NonNull
  private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
    PackageInfo packageInfo = null;
    List<String> list = new ArrayList<String>(1);
    try {
      Log.d(TAG, activity.getPackageName());
      packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
    } catch (PackageManager.NameNotFoundException e) {
      Log.e(TAG, "A problem occurred when retrieving permissions", e);
    }
    if (packageInfo != null) {
      String[] permissions = packageInfo.requestedPermissions;
      if (permissions != null) {
        for (String perm : permissions) {
          Log.d(TAG, "Manifest contained permission: " + perm);
          list.add(perm);
        }
      }
    }
    return list.toArray(new String[list.size()]);
  }

  /**
   * This method adds the {@link PermissionsResultAction} to the current list
   * of pending actions that will be completed when the permissions are
   * received. The list of permissions passed to this method are registered
   * in the PermissionsResultAction object so that it will be notified of changes
   * made to these permissions.
   *
   * @param permissions the required permissions for the action to be executed.
   * @param action      the action to add to the current list of pending actions.
   */
  private synchronized void addPendingAction(@NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    if (action == null) {
      return;
    }
    action.registerPermissions(permissions);
    mPendingActions.add(new WeakReference<PermissionsResultAction>(action));
  }

  /**
   * This method removes a pending action from the list of pending actions.
   * It is used for cases where the permission has already been granted, so
   * you immediately wish to remove the pending action from the queue and
   * execute the action.
   *
   * @param action the action to remove
   */
  private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
    for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
        iterator.hasNext(); ) {
      WeakReference<PermissionsResultAction> weakRef = iterator.next();
      if (weakRef.get() == action || weakRef.get() == null) {
        iterator.remove();
      }
    }
  }

  /**
   * This static method can be used to check whether or not you have a specific permission.
   * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}
   * and will simply return a boolean whether or not you have the permission. If you pass
   * in a null Context object, it will return false as otherwise it cannot check the permission.
   * However, the Activity parameter is nullable so that you can pass in a reference that you
   * are not always sure will be valid or not (e.g. getActivity() from Fragment).
   *
   * @param context    the Context necessary to check the permission
   * @param permission the permission to check
   * @return true if you have been granted the permission, false otherwise
   */
  @SuppressWarnings("unused")
  public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {
    return context != null && (ActivityCompat.checkSelfPermission(context, permission)
        == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));
  }

  /**
   * This static method can be used to check whether or not you have several specific permissions.
   * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}
   * for each permission and will simply return a boolean whether or not you have all the permissions.
   * If you pass in a null Context object, it will return false as otherwise it cannot check the
   * permission. However, the Activity parameter is nullable so that you can pass in a reference
   * that you are not always sure will be valid or not (e.g. getActivity() from Fragment).
   *
   * @param context     the Context necessary to check the permission
   * @param permissions the permissions to check
   * @return true if you have been granted all the permissions, false otherwise
   */
  @SuppressWarnings("unused")
  public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {
    if (context == null) {
      return false;
    }
    boolean hasAllPermissions = true;
    for (String perm : permissions) {
      hasAllPermissions &= hasPermission(context, perm);
    }
    return hasAllPermissions;
  }

  /**
   * This method will request all the permissions declared in your application manifest
   * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable
   * all permissions to be requested at one shot. The PermissionsResultAction is used to notify
   * you of the user allowing or denying each permission. The Activity and PermissionsResultAction
   * parameters are both annotated Nullable, but this method will not work if the Activity
   * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case
   * that you call this from a Fragment where {@link Fragment#getActivity()} could yield
   * null. Additionally, you will not receive any notification of permissions being granted
   * if you provide a null PermissionsResultAction.
   *
   * @param activity the Activity necessary to request and check permissions.
   * @param action   the PermissionsResultAction used to notify you of permissions being accepted.
   */
  @SuppressWarnings("unused")
  public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,
      final @Nullable PermissionsResultAction action) {
    if (activity == null) {
      return;
    }
    String[] perms = getManifestPermissions(activity);
    requestPermissionsIfNecessaryForResult(activity, perms, action);
  }

  /**
   * This method should be used to execute a {@link PermissionsResultAction} for the array
   * of permissions passed to this method. This method will request the permissions if
   * they need to be requested (i.e. we don't have permission yet) and will add the
   * PermissionsResultAction to the queue to be notified of permissions being granted or
   * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
   * The Activity variable is nullable, but if it is null, the method will fail to execute.
   * This is only nullable as a courtesy for Fragments where getActivity() may yeild null
   * if the Fragment is not currently added to its parent Activity.
   *
   * @param activity    the activity necessary to request the permissions.
   * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
   * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
   */
  @SuppressWarnings("unused")
  public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    if (activity == null) {
      return;
    }
    addPendingAction(permissions, action);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      doPermissionWorkBeforeAndroidM(activity, permissions, action);
    } else {
      List<String> permList = getPermissionsListToRequest(activity, permissions, action);
      if (permList.isEmpty()) {
        //if there is no permission to request, there is no reason to keep the action int the list
        removePendingAction(action);
      } else {
        String[] permsToRequest = permList.toArray(new String[permList.size()]);
        mPendingRequests.addAll(permList);
        ActivityCompat.requestPermissions(activity, permsToRequest, 1);
      }
    }
  }

  /**
   * This method should be used to execute a {@link PermissionsResultAction} for the array
   * of permissions passed to this method. This method will request the permissions if
   * they need to be requested (i.e. we don't have permission yet) and will add the
   * PermissionsResultAction to the queue to be notified of permissions being granted or
   * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
   * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method
   * will fail to work as the activity reference is necessary to check for permissions.
   *
   * @param fragment    the fragment necessary to request the permissions.
   * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
   * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
   */
  @SuppressWarnings("unused")
  public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    Activity activity = fragment.getActivity();
    if (activity == null) {
      return;
    }
    addPendingAction(permissions, action);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      doPermissionWorkBeforeAndroidM(activity, permissions, action);
    } else {
      List<String> permList = getPermissionsListToRequest(activity, permissions, action);
      if (permList.isEmpty()) {
        //if there is no permission to request, there is no reason to keep the action int the list
        removePendingAction(action);
      } else {
        String[] permsToRequest = permList.toArray(new String[permList.size()]);
        mPendingRequests.addAll(permList);
        fragment.requestPermissions(permsToRequest, 1);
      }
    }
  }

  /**
   * This method notifies the PermissionsManager that the permissions have change. If you are making
   * the permissions requests using an Activity, then this method should be called from the
   * Activity callback onRequestPermissionsResult() with the variables passed to that method. If
   * you are passing a Fragment to make the permissions request, then you should call this in
   * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.
   * It will notify all the pending PermissionsResultAction objects currently
   * in the queue, and will remove the permissions request from the list of pending requests.
   *
   * @param permissions the permissions that have changed.
   * @param results     the values for each permission.
   */
  @SuppressWarnings("unused")
  public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
    int size = permissions.length;
    if (results.length < size) {
      size = results.length;
    }
    Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
    while (iterator.hasNext()) {
      PermissionsResultAction action = iterator.next().get();
      for (int n = 0; n < size; n++) {
        if (action == null || action.onResult(permissions[n], results[n])) {
          iterator.remove();
          break;
        }
      }
    }
    for (int n = 0; n < size; n++) {
      mPendingRequests.remove(permissions[n]);
    }
  }

  /**
   * When request permissions on devices before Android M (Android 6.0, API Level 23)
   * Do the granted or denied work directly according to the permission status
   *
   * @param activity    the activity to check permissions
   * @param permissions the permissions names
   * @param action      the callback work object, containing what we what to do after
   *                    permission check
   */
  private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    for (String perm : permissions) {
      if (action != null) {
        if (!mPermissions.contains(perm)) {
          action.onResult(perm, Permissions.NOT_FOUND);
        } else if (ActivityCompat.checkSelfPermission(activity, perm)
            != PackageManager.PERMISSION_GRANTED) {
          action.onResult(perm, Permissions.DENIED);
        } else {
          action.onResult(perm, Permissions.GRANTED);
        }
      }
    }
  }

  /**
   * Filter the permissions list:
   * If a permission is not granted, add it to the result list
   * if a permission is granted, do the granted work, do not add it to the result list
   *
   * @param activity    the activity to check permissions
   * @param permissions all the permissions names
   * @param action      the callback work object, containing what we what to do after
   *                    permission check
   * @return a list of permissions names that are not granted yet
   */
  @NonNull
  private List<String> getPermissionsListToRequest(@NonNull Activity activity,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    List<String> permList = new ArrayList<String>(permissions.length);
    for (String perm : permissions) {
      if (!mPermissions.contains(perm)) {
        if (action != null) {
          action.onResult(perm, Permissions.NOT_FOUND);
        }
      } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {
        if (!mPendingRequests.contains(perm)) {
          permList.add(perm);
        }
      } else {
        if (action != null) {
          action.onResult(perm, Permissions.GRANTED);
        }
      }
    }
    return permList;
  }

}


@Override
	public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
			@NonNull int[] grantResults) {
		PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值