/**
   * Handle the result of a permission request, should be called from the calling Activity's {@link
   * android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(int,
   * String[], int[])} method.
   *
   * <p>If any permissions were granted or denied, the Activity will receive the appropriate
   * callbacks through {@link PermissionCallbacks} and methods annotated with {@link
   * AfterPermissionGranted} will be run if appropriate.
   *
   * @param requestCode requestCode argument to permission result callback.
   * @param permissions permissions argument to permission result callback.
   * @param grantResults grantResults argument to permission result callback.
   * @param activity the calling Activity.
   * @throws IllegalArgumentException if the calling Activity does not implement {@link
   *     PermissionCallbacks}.
   */
  public static void onRequestPermissionsResult(
      int requestCode, String[] permissions, int[] grantResults, Activity activity) {

    // Make sure Activity implements callbacks
    if (!(activity instanceof PermissionCallbacks)) {
      throw new IllegalArgumentException("Activity must implement PermissionCallbacks.");
    }
    PermissionCallbacks callbacks = (PermissionCallbacks) activity;

    // Make a collection of granted and denied permissions from the request.
    ArrayList<String> granted = new ArrayList<>();
    ArrayList<String> denied = new ArrayList<>();
    for (int i = 0; i < permissions.length; i++) {
      String perm = permissions[i];
      if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
        granted.add(perm);
      } else {
        denied.add(perm);
      }
    }

    // Report granted permissions, if any.
    if (!granted.isEmpty()) {
      // Notify callbacks
      callbacks.onPermissionsGranted(granted);
    }

    // Report denied permissions, if any.
    if (!denied.isEmpty()) {
      callbacks.onPermissionsDenied(denied);
    }

    // If 100% successful, call annotated methods
    if (!granted.isEmpty() && denied.isEmpty()) {
      runAnnotatedMethods(activity, requestCode);
    }
  }