diff --git a/framework/src/org/apache/cordova/CallbackMap.java b/framework/src/org/apache/cordova/CallbackMap.java new file mode 100644 index 00000000..050daa01 --- /dev/null +++ b/framework/src/org/apache/cordova/CallbackMap.java @@ -0,0 +1,65 @@ +/* + 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; + +import android.util.Pair; +import android.util.SparseArray; + +/** + * Provides a collection that maps unique request codes to CordovaPlugins and Integers. + * Used to ensure that when plugins make requests for runtime permissions, those requests do not + * collide with requests from other plugins that use the same request code value. + */ +public class CallbackMap { + private int currentCallbackId = 0; + private SparseArray> callbacks; + + public CallbackMap() { + this.callbacks = new SparseArray>(); + } + + /** + * Stores a CordovaPlugin and request code and returns a new unique request code to use + * in a permission request. + * + * @param receiver The plugin that is making the request + * @param requestCode The original request code used by the plugin + * @return A unique request code that can be used to retrieve this callback + * with getAndRemoveCallback() + */ + public synchronized int registerCallback(CordovaPlugin receiver, int requestCode) { + int mappedId = this.currentCallbackId++; + callbacks.put(mappedId, new Pair(receiver, requestCode)); + return mappedId; + } + + /** + * Retrieves and removes a callback stored in the map using the mapped request code + * obtained from registerCallback() + * + * @param mappedId The request code obtained from registerCallback() + * @return The CordovaPlugin and orignal request code that correspond to the + * given mappedCode + */ + public synchronized Pair getAndRemoveCallback(int mappedId) { + Pair callback = callbacks.get(mappedId); + callbacks.remove(mappedId); + return callback; + } +} diff --git a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java index d1420b6b..db94e660 100644 --- a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java +++ b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java @@ -25,6 +25,7 @@ import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.util.Log; +import android.util.Pair; import org.json.JSONException; import org.json.JSONObject; @@ -42,8 +43,8 @@ public class CordovaInterfaceImpl implements CordovaInterface { protected PluginManager pluginManager; protected ActivityResultHolder savedResult; + protected CallbackMap permissionResultCallbacks; protected CordovaPlugin activityResultCallback; - protected CordovaPlugin permissionResultCallback; protected String initCallbackService; protected int activityResultRequestCode; protected boolean activityWasDestroyed = false; @@ -56,6 +57,7 @@ public class CordovaInterfaceImpl implements CordovaInterface { public CordovaInterfaceImpl(Activity activity, ExecutorService threadPool) { this.activity = activity; this.threadPool = threadPool; + this.permissionResultCallbacks = new CallbackMap(); } @Override @@ -208,24 +210,21 @@ public class CordovaInterfaceImpl implements CordovaInterface { */ public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException { - if(permissionResultCallback != null) - { - permissionResultCallback.onRequestPermissionResult(requestCode, permissions, grantResults); - permissionResultCallback = null; + Pair callback = permissionResultCallbacks.getAndRemoveCallback(requestCode); + if(callback != null) { + callback.first.onRequestPermissionResult(callback.second, permissions, grantResults); } } public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) { - permissionResultCallback = plugin; String[] permissions = new String [1]; permissions[0] = permission; - getActivity().requestPermissions(permissions, requestCode); + requestPermissions(plugin, requestCode, permissions); } - public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) - { - permissionResultCallback = plugin; - getActivity().requestPermissions(permissions, requestCode); + public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) { + int mappedRequestCode = permissionResultCallbacks.registerCallback(plugin, requestCode); + getActivity().requestPermissions(permissions, mappedRequestCode); } public boolean hasPermission(String permission)