From ba2fcd39d140b336bd6dbb9cff9b1eea0dcd1bcf Mon Sep 17 00:00:00 2001 From: Andy Street Date: Mon, 4 Jan 2016 12:07:52 -0800 Subject: [PATCH] WebWorkers: Add JSLoader API for loading script from assets with AssetLoader reference Summary: public Adds the ability to load files from assets without threading through an AssetManager. After the bridge is unforked, we should move to passing through an Environment object instead. Reviewed By: lexs Differential Revision: D2779079 fb-gh-sync-id: 82b47ecdf48b724076d87f4879ec40601e21e6bc --- .../react/ReactInstanceManagerImpl.java | 5 +++ .../react/common/ApplicationHolder.java | 36 +++++++++++++++++++ .../src/main/jni/react/jni/JSLoader.cpp | 26 +++++++++++++- .../src/main/jni/react/jni/JSLoader.h | 8 +++++ .../src/main/jni/react/jni/OnLoad.cpp | 1 + 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/ApplicationHolder.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java index d7b375cfb..66ce1a2e8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import android.app.Activity; +import android.app.Application; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; @@ -45,6 +46,7 @@ import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.bridge.queue.CatalystQueueConfigurationSpec; +import com.facebook.react.common.ApplicationHolder; import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.devsupport.DevServerHelper; @@ -199,6 +201,9 @@ import com.facebook.systrace.Systrace; UIImplementationProvider uiImplementationProvider) { initializeSoLoaderIfNecessary(applicationContext); + // TODO(9577825): remove this + ApplicationHolder.setApplication((Application) applicationContext.getApplicationContext()); + mApplicationContext = applicationContext; mJSBundleFile = jsBundleFile; mJSMainModuleName = jsMainModuleName; diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/ApplicationHolder.java b/ReactAndroid/src/main/java/com/facebook/react/common/ApplicationHolder.java new file mode 100644 index 000000000..535b81597 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/common/ApplicationHolder.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.facebook.react.common; + +import android.app.Application; + +import com.facebook.infer.annotation.Assertions; +import com.facebook.proguard.annotations.DoNotStrip; + +/** + * Holds the current Application Object. + * + * TODO(9577825): This is a bad pattern, we should thread through an Environment object instead. + * Remove once bridge is unforked. + */ +@DoNotStrip +@Deprecated +public class ApplicationHolder { + + private static Application sApplication; + + public static void setApplication(Application application) { + sApplication = application; + } + + public static Application getApplication() { + return Assertions.assertNotNull(sApplication); + } +} diff --git a/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp b/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp index 416640a37..db8b4d980 100644 --- a/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp +++ b/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,19 @@ using fbsystrace::FbSystraceSection; namespace facebook { namespace react { +static jclass gApplicationHolderClass; +static jmethodID gGetApplicationMethod; +static jmethodID gGetAssetManagerMethod; + +std::string loadScriptFromAssets(std::string assetName) { + JNIEnv *env = jni::Environment::current(); + jobject application = env->CallStaticObjectMethod( + gApplicationHolderClass, + gGetApplicationMethod); + jobject assetManager = env->CallObjectMethod(application, gGetAssetManagerMethod); + return loadScriptFromAssets(env, assetManager, assetName); +} + std::string loadScriptFromAssets( JNIEnv *env, jobject assetManager, @@ -71,4 +85,14 @@ std::string loadScriptFromFile(std::string fileName) { return ""; } -} } \ No newline at end of file +void registerJSLoaderNatives() { + JNIEnv *env = jni::Environment::current(); + jclass applicationHolderClass = env->FindClass("com/facebook/react/common/ApplicationHolder"); + gApplicationHolderClass = (jclass)env->NewGlobalRef(applicationHolderClass); + gGetApplicationMethod = env->GetStaticMethodID(applicationHolderClass, "getApplication", "()Landroid/app/Application;"); + + jclass appClass = env->FindClass("android/app/Application"); + gGetAssetManagerMethod = env->GetMethodID(appClass, "getAssets", "()Landroid/content/res/AssetManager;"); +} + +} } diff --git a/ReactAndroid/src/main/jni/react/jni/JSLoader.h b/ReactAndroid/src/main/jni/react/jni/JSLoader.h index c7381fe7e..25dab510d 100644 --- a/ReactAndroid/src/main/jni/react/jni/JSLoader.h +++ b/ReactAndroid/src/main/jni/react/jni/JSLoader.h @@ -8,6 +8,12 @@ namespace facebook { namespace react { +/** + * Helper method for loading a JS script from Android assets without + * a reference to an AssetManager. + */ +std::string loadScriptFromAssets(std::string assetName); + /** * Helper method for loading JS script from android asset */ @@ -18,4 +24,6 @@ std::string loadScriptFromAssets(JNIEnv *env, jobject assetManager, std::string */ std::string loadScriptFromFile(std::string fileName); +void registerJSLoaderNatives(); + } } diff --git a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp index 5ef5c28aa..6eb6d523e 100644 --- a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp @@ -780,6 +780,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { NativeArray::registerNatives(); ReadableNativeArray::registerNatives(); WritableNativeArray::registerNatives(); + registerJSLoaderNatives(); registerNatives("com/facebook/react/bridge/NativeMap", { makeNativeMethod("initialize", map::initialize),