Android: external.getPluginAsync + get private field

This commit is contained in:
Adam Nathan 2016-02-14 11:17:57 -08:00
Родитель b4df5899f7
Коммит 79a74a2bb8
7 изменённых файлов: 72 добавлений и 17 удалений

Просмотреть файл

@ -89,6 +89,20 @@ public class Utils {
}
}
public static Object getPrivateField(Class c, Object instance, String fieldName) {
try {
Field f = c.getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(instance);
}
catch (NoSuchFieldException ex) {
throw new RuntimeException(c.getSimpleName() + " does not have a " + fieldName + " field");
}
catch (IllegalAccessException ex) {
throw new RuntimeException(c.getSimpleName() + "'s " + fieldName + " field is inaccessible");
}
}
public static void setField(Class c, Object instance, String fieldName, Object fieldValue) {
try {
Field f = c.getField(fieldName);

Просмотреть файл

@ -33,6 +33,7 @@ public class IncomingMessages {
public static final int MSG_GETINSTANCE = 8;
public static final int MSG_NAVIGATE = 9;
public static final int MSG_FIELDSET = 10;
public static final int MSG_PRIVATEFIELDGET = 11;
// Holds the content during a navigation
public static View frameContent;
@ -103,6 +104,9 @@ public class IncomingMessages {
else if (fullTypeName.equals("HostWebView")) {
return webView.getView();
}
else if (fullTypeName.equals("PluginManager")) {
return webView.getPluginManager();
}
throw new RuntimeException(fullTypeName + " is not a valid choice for getting an existing instance");
}
@ -233,6 +237,13 @@ public class IncomingMessages {
return Utils.getField(instance.getClass(), instance, fieldName);
}
public static Object privateFieldGet(JSONArray message) throws JSONException
{
Object instance = Handle.deserialize(message.getJSONObject(1));
String fieldName = message.getString(2);
return Utils.getPrivateField(instance.getClass(), instance, fieldName);
}
public static Object staticFieldGet(JSONArray message) throws JSONException
{
String fullTypeName = message.getString(1);

Просмотреть файл

@ -271,6 +271,10 @@ public class NativeHost extends CordovaPlugin {
case IncomingMessages.MSG_FIELDSET:
IncomingMessages.fieldSet(message);
break;
case IncomingMessages.MSG_PRIVATEFIELDGET:
returnValue = IncomingMessages.privateFieldGet(message);
hasReturnValue = true;
break;
default:
throw new RuntimeException("Unknown message type: " + messageType);
}

Просмотреть файл

@ -31,7 +31,8 @@ MessageType = {
StaticFieldGet: 7,
GetInstance: 8,
Navigate: 9,
FieldSet: 10
FieldSet: 10,
PrivateFieldGet: 11
};
function onInitializeFailed(error) {
@ -133,6 +134,8 @@ function debugPrintMessage(messageArray) {
s = "Navigate";
else if (s == MessageType.FieldSet)
s = "FieldSet";
else if (s == MessageType.PrivateFieldGet)
s = "PrivateFieldGet";
else
s = "UNKNOWN";
}
@ -230,6 +233,10 @@ ToNative.queueStaticFieldGetMessage = function (className, fieldName) {
queueMessage([MessageType.StaticFieldGet, className, fieldName]);
};
ToNative.queuePrivateFieldGetMessage = function (instance, fieldName) {
queueMessage([MessageType.PrivateFieldGet, instance.handle, fieldName]);
};
ToNative.queueSetMessage = function (instance, propertyName, propertyValue) {
// Marshal a NativeObject by sending its handle
if (propertyValue instanceof ace.NativeObject)

Просмотреть файл

@ -7,17 +7,15 @@
// Interacts with external native UI, perhaps from other plugins.
//
module.exports = {
getCurrentModalContent: function () {
return new ace.KnownNativeObject("CurrentModalContent");
},
setCurrentModalContent: function (content) {
var root = new ace.KnownNativeObject("CurrentModalRoot");
if (ace.platform == "iOS") {
ace.NativeObject.invoke("UIViewHelper", "replaceContentIn:with:", root, content);
getPluginAsync: function (serviceName, onSuccess) {
if (ace.platform == "Android") {
var pm = new ace.KnownNativeObject("PluginManager");
pm.invoke("getPlugin", serviceName, function(instance) {
onSuccess(instance);
});
}
else {
throw new Error("Not supported on the current platform.");
throw new Error("Not yet supported on the current platform.");
}
}
};

Просмотреть файл

@ -20,5 +20,14 @@ module.exports = {
this.getNavigationController().invoke("presentedViewController", function (viewController) {
onSuccess(viewController);
});
},
getCurrentModalContent: function () {
return new ace.KnownNativeObject("CurrentModalContent");
},
setCurrentModalContent: function (content) {
var root = new ace.KnownNativeObject("CurrentModalRoot");
ace.NativeObject.invoke("UIViewHelper", "replaceContentIn:with:", root, content);
}
};

Просмотреть файл

@ -52,7 +52,7 @@ function unwrapResult(result) {
}
}
function fieldHelper(instance, className, fieldName, onSuccess, onError) {
function fieldHelper(instance, isPrivate, className, fieldName, onSuccess, onError) {
if (!fieldName) {
throw new Error("You must specify a field");
}
@ -68,11 +68,18 @@ function fieldHelper(instance, className, fieldName, onSuccess, onError) {
ace.ToNative.sendPendingMessages();
// Now queue this single message
if (instance)
ace.ToNative.queueFieldGetMessage(instance, fieldName);
else
if (instance) {
if (isPrivate) {
ace.ToNative.queuePrivateFieldGetMessage(instance, fieldName);
}
else {
ace.ToNative.queueFieldGetMessage(instance, fieldName);
}
}
else {
ace.ToNative.queueStaticFieldGetMessage(className, fieldName);
}
// Send this out as a batch of one, with the passed-in callbacks
ace.ToNative.sendPendingMessages(function (result) { onSuccess(unwrapResult(result)) }, onError);
}
@ -182,12 +189,17 @@ NativeObject.prototype.invalidate = function (propertyName, propertyValue) {
// Get the value of an instance (or static) field
NativeObject.prototype.getField = function (fieldName, onSuccess, onError) {
fieldHelper(this, null, fieldName, onSuccess, onError);
fieldHelper(this, false, null, fieldName, onSuccess, onError);
};
// Get the value of a static field
NativeObject.getField = function (className, fieldName, onSuccess, onError) {
fieldHelper(null, className, fieldName, onSuccess, onError);
fieldHelper(null, false, className, fieldName, onSuccess, onError);
};
// Get the value of a private instance (or static) field
NativeObject.prototype.getPrivateField = function (fieldName, onSuccess, onError) {
fieldHelper(this, true, null, fieldName, onSuccess, onError);
};
// Set the value of an instance (or static) field