Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0134418F1C for ; Wed, 13 Jan 2016 18:50:03 +0000 (UTC) Received: (qmail 32293 invoked by uid 500); 13 Jan 2016 18:50:02 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 32261 invoked by uid 500); 13 Jan 2016 18:50:02 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 32251 invoked by uid 99); 13 Jan 2016 18:50:02 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 13 Jan 2016 18:50:02 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B6D5ADFDCF; Wed, 13 Jan 2016 18:50:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rknoll@apache.org To: commits@cordova.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: cordova-plugin-camera git commit: CB-10319 android: Adding reflective helper methods for permission requests Date: Wed, 13 Jan 2016 18:50:02 +0000 (UTC) Repository: cordova-plugin-camera Updated Branches: refs/heads/master e2193631d -> 1d32ea46f CB-10319 android: Adding reflective helper methods for permission requests Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/1d32ea46 Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/1d32ea46 Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/1d32ea46 Branch: refs/heads/master Commit: 1d32ea46f0ebcbf5cbc3d8a255170bf7186533c8 Parents: e219363 Author: riknoll Authored: Mon Jan 4 15:22:35 2016 -0800 Committer: riknoll Committed: Tue Jan 12 17:42:29 2016 -0800 ---------------------------------------------------------------------- plugin.xml | 17 ++-- src/android/CameraLauncher.java | 14 +--- src/android/PermissionHelper.java | 138 +++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/1d32ea46/plugin.xml ---------------------------------------------------------------------- diff --git a/plugin.xml b/plugin.xml index 673761e..3df1e81 100644 --- a/plugin.xml +++ b/plugin.xml @@ -30,10 +30,6 @@ https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git https://issues.apache.org/jira/browse/CB/component/12320645 - - - - @@ -54,12 +50,12 @@ - - + + - + @@ -75,6 +71,7 @@ + @@ -102,7 +99,7 @@ - + @@ -151,11 +148,11 @@ - + - + http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/1d32ea46/src/android/CameraLauncher.java ---------------------------------------------------------------------- diff --git a/src/android/CameraLauncher.java b/src/android/CameraLauncher.java index ff8599b..15e908f 100644 --- a/src/android/CameraLauncher.java +++ b/src/android/CameraLauncher.java @@ -114,12 +114,6 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect private Uri scanMe; // Uri of image to be added to content store private Uri croppedUri; - - protected void getReadPermission(int requestCode) - { - cordova.requestPermission(this, requestCode, Manifest.permission.READ_EXTERNAL_STORAGE); - } - /** * Executes the request and returns PluginResult. * @@ -178,8 +172,8 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect // preserve the original exif data and filename in the modified file that is // created if(this.mediaType == PICTURE && (this.destType == FILE_URI || this.destType == NATIVE_URI) - && fileWillBeModified() && !cordova.hasPermission(permissions[0])) { - getReadPermission(SAVE_TO_ALBUM_SEC); + && fileWillBeModified() && !PermissionHelper.hasPermission(this, permissions[0])) { + PermissionHelper.requestPermission(this, SAVE_TO_ALBUM_SEC, Manifest.permission.READ_EXTERNAL_STORAGE); } else { this.getImage(this.srcType, destType, encodingType); } @@ -238,10 +232,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect * @param returnType Set the type of image to return. */ public void callTakePicture(int returnType, int encodingType) { - if (cordova.hasPermission(permissions[0])) { + if (PermissionHelper.hasPermission(this, permissions[0])) { takePicture(returnType, encodingType); } else { - getReadPermission(TAKE_PIC_SEC); + PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.READ_EXTERNAL_STORAGE); } } http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/1d32ea46/src/android/PermissionHelper.java ---------------------------------------------------------------------- diff --git a/src/android/PermissionHelper.java b/src/android/PermissionHelper.java new file mode 100644 index 0000000..cf4247b --- /dev/null +++ b/src/android/PermissionHelper.java @@ -0,0 +1,138 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +package org.apache.cordova.camera; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; + +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.LOG; + +import android.content.pm.PackageManager; + +/** + * This class provides reflective methods for permission requesting and checking so that plugins + * written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions. + */ +public class PermissionHelper { + private static final String LOG_TAG = "CordovaPermissionHelper"; + + /** + * Requests a "dangerous" permission for the application at runtime. This is a helper method + * alternative to cordovaInterface.requestPermission() that does not require the project to be + * built with cordova-android 5.0.0+ + * + * @param plugin The plugin the permission is being requested for + * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult() + * along with the result of the permission request + * @param permission The permission to be requested + */ + public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) { + PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission}); + } + + /** + * Requests "dangerous" permissions for the application at runtime. This is a helper method + * alternative to cordovaInterface.requestPermissions() that does not require the project to be + * built with cordova-android 5.0.0+ + * + * @param plugin The plugin the permissions are being requested for + * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult() + * along with the result of the permissions request + * @param permissions The permissions to be requested + */ + public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) { + try { + Method requestPermission = CordovaInterface.class.getDeclaredMethod( + "requestPermissions", CordovaPlugin.class, int.class, String[].class); + + // If there is no exception, then this is cordova-android 5.0.0+ + requestPermission.invoke(plugin.cordova, plugin, requestCode, permissions); + } catch (NoSuchMethodException noSuchMethodException) { + // cordova-android version is less than 5.0.0, so permission is implicitly granted + LOG.d(LOG_TAG, "No need to request permissions " + Arrays.toString(permissions)); + + // Notify the plugin that all were granted by using more reflection + deliverPermissionResult(plugin, requestCode, permissions); + } catch (IllegalAccessException illegalAccessException) { + // Should never be caught; this is a public method + LOG.e(LOG_TAG, "IllegalAccessException when requesting permissions " + Arrays.toString(permissions), illegalAccessException); + } catch(InvocationTargetException invocationTargetException) { + // This method does not throw any exceptions, so this should never be caught + LOG.e(LOG_TAG, "invocationTargetException when requesting permissions " + Arrays.toString(permissions), invocationTargetException); + } + } + + /** + * Checks at runtime to see if the application has been granted a permission. This is a helper + * method alternative to cordovaInterface.hasPermission() that does not require the project to + * be built with cordova-android 5.0.0+ + * + * @param plugin The plugin the permission is being checked against + * @param permission The permission to be checked + * + * @return True if the permission has already been granted and false otherwise + */ + public static boolean hasPermission(CordovaPlugin plugin, String permission) { + try { + Method hasPermission = CordovaInterface.class.getDeclaredMethod("hasPermission", String.class); + + // If there is no exception, then this is cordova-android 5.0.0+ + return (Boolean) hasPermission.invoke(plugin.cordova, permission); + } catch (NoSuchMethodException noSuchMethodException) { + // cordova-android version is less than 5.0.0, so permission is implicitly granted + LOG.d(LOG_TAG, "No need to check for permission " + permission); + return true; + } catch (IllegalAccessException illegalAccessException) { + // Should never be caught; this is a public method + LOG.e(LOG_TAG, "IllegalAccessException when checking permission " + permission, illegalAccessException); + } catch(InvocationTargetException invocationTargetException) { + // This method does not throw any exceptions, so this should never be caught + LOG.e(LOG_TAG, "invocationTargetException when checking permission " + permission, invocationTargetException); + } + return false; + } + + private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) { + // Generate the request results + int[] requestResults = new int[permissions.length]; + Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED); + + try { + Method onRequestPermissionResult = CordovaPlugin.class.getDeclaredMethod( + "onRequestPermissionResult", int.class, String[].class, int[].class); + + onRequestPermissionResult.invoke(plugin, requestCode, permissions, requestResults); + } catch (NoSuchMethodException noSuchMethodException) { + // Should never be caught since the plugin must be written for cordova-android 5.0.0+ if it + // made it to this point + LOG.e(LOG_TAG, "NoSuchMethodException when delivering permissions results", noSuchMethodException); + } catch (IllegalAccessException illegalAccessException) { + // Should never be caught; this is a public method + LOG.e(LOG_TAG, "IllegalAccessException when delivering permissions results", illegalAccessException); + } catch(InvocationTargetException invocationTargetException) { + // This method may throw a JSONException. We are just duplicating cordova-android's + // exception handling behavior here; all it does is log the exception in CordovaActivity, + // print the stacktrace, and ignore it + LOG.e(LOG_TAG, "InvocationTargetException when delivering permissions results", invocationTargetException); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org For additional commands, e-mail: commits-help@cordova.apache.org