Repository: cordova-plugin-media Updated Branches: refs/heads/master 5612109b9 -> f0a82b189
CB-10455 android: Adding permission helper to remove cordova-android 5.0.0 constraint Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/commit/f0a82b18 Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/tree/f0a82b18 Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/diff/f0a82b18 Branch: refs/heads/master Commit: f0a82b18958fd5291239854ac56ff2c3ff0873d1 Parents: 5612109 Author: riknoll <[email protected]> Authored: Fri Feb 5 09:57:08 2016 -0800 Committer: riknoll <[email protected]> Committed: Fri Feb 5 09:57:08 2016 -0800 ---------------------------------------------------------------------- plugin.xml | 22 +++--- src/android/AudioHandler.java | 10 +-- src/android/PermissionHelper.java | 138 +++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/f0a82b18/plugin.xml ---------------------------------------------------------------------- diff --git a/plugin.xml b/plugin.xml index c72105e..86744df 100644 --- a/plugin.xml +++ b/plugin.xml @@ -30,19 +30,16 @@ id="cordova-plugin-media" <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-media.git</repo> <issue>https://issues.apache.org/jira/browse/CB/component/12320647</issue> - <engines> - <engine name="cordova-android" version=">=5.0.0-dev" /> - </engines> <dependency id="cordova-plugin-file" version="^4.0.0" /> <js-module src="www/MediaError.js" name="MediaError"> <clobbers target="window.MediaError" /> </js-module> - + <js-module src="www/Media.js" name="Media"> <clobbers target="window.Media" /> </js-module> - + <!-- android --> <platform name="android"> <config-file target="res/xml/config.xml" parent="/*"> @@ -50,19 +47,20 @@ id="cordova-plugin-media" <param name="android-package" value="org.apache.cordova.media.AudioHandler"/> </feature> </config-file> - + <config-file target="AndroidManifest.xml" parent="/*"> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> </config-file> - + <source-file src="src/android/AudioHandler.java" target-dir="src/org/apache/cordova/media" /> <source-file src="src/android/AudioPlayer.java" target-dir="src/org/apache/cordova/media" /> <source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/media" /> + <source-file src="src/android/PermissionHelper.java" target-dir="src/org/apache/cordova/media" /> </platform> - + <!-- amazon-fireos --> <platform name="amazon-fireos"> <config-file target="res/xml/config.xml" parent="/*"> @@ -70,14 +68,14 @@ id="cordova-plugin-media" <param name="android-package" value="org.apache.cordova.media.AudioHandler"/> </feature> </config-file> - + <config-file target="AndroidManifest.xml" parent="/*"> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> </config-file> - + <source-file src="src/android/AudioHandler.java" target-dir="src/org/apache/cordova/media" /> <source-file src="src/android/AudioPlayer.java" target-dir="src/org/apache/cordova/media" /> <source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/media" /> @@ -97,10 +95,10 @@ id="cordova-plugin-media" </platform> <!-- ios --> - <platform name="ios"> + <platform name="ios"> <config-file target="config.xml" parent="/*"> <feature name="Media"> - <param name="ios-package" value="CDVSound" /> + <param name="ios-package" value="CDVSound" /> </feature> </config-file> <header-file src="src/ios/CDVSound.h" /> http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/f0a82b18/src/android/AudioHandler.java ---------------------------------------------------------------------- diff --git a/src/android/AudioHandler.java b/src/android/AudioHandler.java index d5eb65f..3f93c37 100644 --- a/src/android/AudioHandler.java +++ b/src/android/AudioHandler.java @@ -80,13 +80,13 @@ public class AudioHandler extends CordovaPlugin { protected void getWritePermission(int requestCode) { - cordova.requestPermission(this, requestCode, permissions[WRITE_EXTERNAL_STORAGE]); + PermissionHelper.requestPermission(this, requestCode, permissions[WRITE_EXTERNAL_STORAGE]); } protected void getMicPermission(int requestCode) { - cordova.requestPermission(this, requestCode, permissions[RECORD_AUDIO]); + PermissionHelper.requestPermission(this, requestCode, permissions[RECORD_AUDIO]); } @@ -457,11 +457,11 @@ public class AudioHandler extends CordovaPlugin { private void promptForRecord() { - if(cordova.hasPermission(permissions[WRITE_EXTERNAL_STORAGE]) && - cordova.hasPermission(permissions[RECORD_AUDIO])) { + if(PermissionHelper.hasPermission(this, permissions[WRITE_EXTERNAL_STORAGE]) && + PermissionHelper.hasPermission(this, permissions[RECORD_AUDIO])) { this.startRecordingAudio(recordId, FileHelper.stripFileProtocol(fileUriStr)); } - else if(cordova.hasPermission(permissions[RECORD_AUDIO])) + else if(PermissionHelper.hasPermission(this, permissions[RECORD_AUDIO])) { getWritePermission(WRITE_EXTERNAL_STORAGE); } http://git-wip-us.apache.org/repos/asf/cordova-plugin-media/blob/f0a82b18/src/android/PermissionHelper.java ---------------------------------------------------------------------- diff --git a/src/android/PermissionHelper.java b/src/android/PermissionHelper.java new file mode 100644 index 0000000..c559506 --- /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.media; + +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: [email protected] For additional commands, e-mail: [email protected]
