From 1bfd267acb8a4f82aa5e1724aee37b4f8747f050 Mon Sep 17 00:00:00 2001 From: Andy Street Date: Wed, 6 Jan 2016 06:29:11 -0800 Subject: [PATCH] Resubmit: [react_native] 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. Resubmit: previous version was reverted due to adsmanager crash Reviewed By: foghina Differential Revision: D2802899 fb-gh-sync-id: 3d850256fc22f7e9eb21fa71f6adb09cacc839c4 --- .../react/ReactInstanceManagerImpl.java | 5 +++ .../react/common/ApplicationHolder.java | 37 +++++++++++++++++++ .../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, 76 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 780cdb123..c9bf17c61 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; @@ -46,6 +47,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; @@ -242,6 +244,9 @@ import com.facebook.systrace.Systrace; NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) { 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..f35d1a18d --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/common/ApplicationHolder.java @@ -0,0 +1,37 @@ +/** + * 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; + } + + @DoNotStrip + 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 07e6549b9..7b66505c4 100644 --- a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp @@ -782,6 +782,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { ReadableNativeArray::registerNatives(); WritableNativeArray::registerNatives(); JNativeRunnable::registerNatives(); + registerJSLoaderNatives(); registerNatives("com/facebook/react/bridge/NativeMap", { makeNativeMethod("initialize", map::initialize),