From 788e2775f60fb16fb88186c915e242013fc9a0d9 Mon Sep 17 00:00:00 2001 From: Alexander Blom Date: Wed, 2 Nov 2016 12:18:20 -0700 Subject: [PATCH] Add Java JNI bindings Reviewed By: mhorowitz Differential Revision: D4021520 fbshipit-source-id: dbaf2ebb7fa48f4efe6cf47a97c39bb079dda8d0 --- .../com/facebook/react/bridge/Inspector.java | 81 +++++++++++++++++ ReactAndroid/src/main/jni/xreact/jni/BUCK | 2 + .../src/main/jni/xreact/jni/JInspector.cpp | 90 +++++++++++++++++++ .../src/main/jni/xreact/jni/JInspector.h | 61 +++++++++++++ .../src/main/jni/xreact/jni/OnLoad.cpp | 7 ++ 5 files changed, 241 insertions(+) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/Inspector.java create mode 100644 ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp create mode 100644 ReactAndroid/src/main/jni/xreact/jni/JInspector.h diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/Inspector.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/Inspector.java new file mode 100644 index 000000000..9d117c806 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/Inspector.java @@ -0,0 +1,81 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +package com.facebook.react.bridge; + +import java.util.Arrays; +import java.util.List; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class Inspector { + static { + ReactBridge.staticInit(); + } + + private final HybridData mHybridData; + + public static List getPages() { + return Arrays.asList(instance().getPagesNative()); + } + + public static LocalConnection connect(int pageId, RemoteConnection remote) { + return instance().connectNative(pageId, remote); + } + + private static native Inspector instance(); + + private native Page[] getPagesNative(); + + private native LocalConnection connectNative(int pageId, RemoteConnection remote); + + private Inspector(HybridData hybridData) { + mHybridData = hybridData; + } + + @DoNotStrip + public static class Page { + private final int mId; + private final String mTitle; + + public int getId() { + return mId; + } + + public String getTitle() { + return mTitle; + } + + @Override + public String toString() { + return "Page{" + + "mId=" + mId + + ", mTitle='" + mTitle + '\'' + + '}'; + } + + private Page(int id, String title) { + mId = id; + mTitle = title; + } + } + + @DoNotStrip + public interface RemoteConnection { + void onMessage(String message); + void onDisconnect(); + } + + @DoNotStrip + public static class LocalConnection { + private final HybridData mHybridData; + + public native void sendMessage(String message); + public native void disconnect(); + + private LocalConnection(HybridData hybridData) { + mHybridData = hybridData; + } + } +} diff --git a/ReactAndroid/src/main/jni/xreact/jni/BUCK b/ReactAndroid/src/main/jni/xreact/jni/BUCK index dc7601464..020aa13c4 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/BUCK +++ b/ReactAndroid/src/main/jni/xreact/jni/BUCK @@ -27,6 +27,7 @@ cxx_library( '//xplat/fbsystrace:fbsystrace', react_native_xplat_target('cxxreact:bridge'), react_native_xplat_target('cxxreact:module'), + react_native_xplat_target('inspector:inspector'), ], srcs = glob(['*.cpp']), xcode_public_headers_symlinks = True, @@ -35,6 +36,7 @@ cxx_library( preprocessor_flags = [ '-DLOG_TAG="ReactNativeJNI"', '-DWITH_FBSYSTRACE=1', + '-DWITH_INSPECTOR=1', ], compiler_flags = [ '-Wall', diff --git a/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp b/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp new file mode 100644 index 000000000..4146fc0fd --- /dev/null +++ b/ReactAndroid/src/main/jni/xreact/jni/JInspector.cpp @@ -0,0 +1,90 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "JInspector.h" + +namespace facebook { +namespace react { + +namespace { + +class RemoteConnection : public Inspector::RemoteConnection { +public: + RemoteConnection(jni::alias_ref connection) + : connection_(jni::make_global(connection)) {} + + void onMessage(std::string message) override { + connection_->onMessage(message); + } + + void onDisconnect() override { + connection_->onDisconnect(); + } +private: + jni::global_ref connection_; +}; + +} + +jni::local_ref JPage::create(int id, const std::string& title) { + static auto constructor = javaClassStatic()->getConstructor)>(); + return javaClassStatic()->newObject(constructor, id, jni::make_jstring(title)); +} + +void JRemoteConnection::onMessage(const std::string& message) const { + static auto method = javaClassStatic()->getMethod)>("onMessage"); + method(self(), jni::make_jstring(message)); +} + +void JRemoteConnection::onDisconnect() const { + static auto method = javaClassStatic()->getMethod("onDisconnect"); + method(self()); +} + +JLocalConnection::JLocalConnection(std::unique_ptr connection) + : connection_(std::move(connection)) {} + +void JLocalConnection::sendMessage(std::string message) { + connection_->sendMessage(std::move(message)); +} + +void JLocalConnection::disconnect() { + connection_->disconnect(); +} + +void JLocalConnection::registerNatives() { + javaClassStatic()->registerNatives({ + makeNativeMethod("sendMessage", JLocalConnection::sendMessage), + makeNativeMethod("disconnect", JLocalConnection::disconnect), + }); +} + +jni::global_ref JInspector::instance(jni::alias_ref) { + static auto instance = jni::make_global(newObjectCxxArgs(&Inspector::instance())); + return instance; +} + +jni::local_ref> JInspector::getPages() { + std::vector pages = inspector_->getPages(); + auto array = jni::JArrayClass::newArray(pages.size()); + for (size_t i = 0; i < pages.size(); i++) { + (*array)[i] = JPage::create(pages[i].id, pages[i].title); + } + return array; +} + +jni::local_ref JInspector::connect(int pageId, jni::alias_ref remote) { + auto localConnection = inspector_->connect(pageId, folly::make_unique(std::move(remote))); + return JLocalConnection::newObjectCxxArgs(std::move(localConnection)); +} + +void JInspector::registerNatives() { + JLocalConnection::registerNatives(); + javaClassStatic()->registerNatives({ + makeNativeMethod("instance", JInspector::instance), + makeNativeMethod("getPagesNative", JInspector::getPages), + makeNativeMethod("connectNative", JInspector::connect), + }); +} + +} +} diff --git a/ReactAndroid/src/main/jni/xreact/jni/JInspector.h b/ReactAndroid/src/main/jni/xreact/jni/JInspector.h new file mode 100644 index 000000000..3335deccb --- /dev/null +++ b/ReactAndroid/src/main/jni/xreact/jni/JInspector.h @@ -0,0 +1,61 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include + +#include +#include + +namespace facebook { +namespace react { + +class JPage : public jni::JavaClass { +public: + static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/Inspector$Page;"; + + static jni::local_ref create(int id, const std::string& title); +}; + +class JRemoteConnection : public jni::JavaClass { +public: + static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/Inspector$RemoteConnection;"; + + void onMessage(const std::string& message) const; + void onDisconnect() const; +}; + +class JLocalConnection : public jni::HybridClass { +public: + static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/Inspector$LocalConnection;"; + + JLocalConnection(std::unique_ptr connection); + + void sendMessage(std::string message); + void disconnect(); + + static void registerNatives(); +private: + std::unique_ptr connection_; +}; + +class JInspector : public jni::HybridClass { +public: + static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/Inspector;"; + + static jni::global_ref instance(jni::alias_ref); + + jni::local_ref> getPages(); + jni::local_ref connect(int pageId, jni::alias_ref remote); + + static void registerNatives(); +private: + friend HybridBase; + + JInspector(Inspector* inspector) : inspector_(inspector) {} + + Inspector* inspector_; +}; + +} +} diff --git a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp index 1e5411bbf..84f017558 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/OnLoad.cpp @@ -16,6 +16,10 @@ #include "WebWorkers.h" #include "JCallback.h" +#ifdef WITH_INSPECTOR +#include "JInspector.h" +#endif + #include "WritableNativeMap.h" #include "WritableNativeArray.h" @@ -181,6 +185,9 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { ModuleRegistryHolder::registerNatives(); CxxModuleWrapper::registerNatives(); JCallbackImpl::registerNatives(); + #ifdef WITH_INSPECTOR + JInspector::registerNatives(); + #endif registerJSLoaderNatives(); NativeArray::registerNatives();