";
@@ -2716,6 +2720,7 @@
3D7AA9C51E548CDB001955CF /* NSDataBigString.h in Headers */,
5960C1BA1F0804A00066FD5B /* RCTLayoutAnimationGroup.h in Headers */,
13134C991E296B2A00B9F3CB /* RCTCxxMethod.h in Headers */,
+ 3D0E378D1F1CC58F00DCAC9F /* RCTWebSocketObserver.h in Headers */,
3D302F471DF828F800D6DDAE /* RCTPlatform.h in Headers */,
13134C951E296B2A00B9F3CB /* RCTObjcExecutor.h in Headers */,
590D7BFE1EBD458B00D8A370 /* RCTShadowView+Layout.h in Headers */,
@@ -2741,6 +2746,7 @@
3D302F2E1DF828F800D6DDAE /* RCTBridgeDelegate.h in Headers */,
3D302F2F1DF828F800D6DDAE /* RCTBridgeMethod.h in Headers */,
130E3D8A1E6A083600ACE484 /* RCTDevSettings.h in Headers */,
+ 3D0E378E1F1CC59100DCAC9F /* RCTWebSocketModule.h in Headers */,
3D302F301DF828F800D6DDAE /* RCTBridgeModule.h in Headers */,
3D302F311DF828F800D6DDAE /* RCTBundleURLProvider.h in Headers */,
3D302F321DF828F800D6DDAE /* RCTConvert.h in Headers */,
@@ -2777,7 +2783,6 @@
3D302F4D1DF828F800D6DDAE /* RCTURLRequestDelegate.h in Headers */,
3D302F4E1DF828F800D6DDAE /* RCTURLRequestHandler.h in Headers */,
3D302F4F1DF828F800D6DDAE /* RCTUtils.h in Headers */,
- 3D302F501DF828F800D6DDAE /* RCTWebSocketObserverProtocol.h in Headers */,
3D302F541DF828F800D6DDAE /* RCTJSCSamplingProfiler.h in Headers */,
3D302F551DF828F800D6DDAE /* RCTAccessibilityManager.h in Headers */,
3D302F561DF828F800D6DDAE /* RCTAlertManager.h in Headers */,
@@ -3060,12 +3065,12 @@
3D80DA421DF820620028D040 /* RCTURLRequestDelegate.h in Headers */,
3D80DA431DF820620028D040 /* RCTURLRequestHandler.h in Headers */,
3D80DA441DF820620028D040 /* RCTUtils.h in Headers */,
- 3D80DA451DF820620028D040 /* RCTWebSocketObserverProtocol.h in Headers */,
13134C981E296B2A00B9F3CB /* RCTCxxMethod.h in Headers */,
3D80DA491DF820620028D040 /* RCTJSCSamplingProfiler.h in Headers */,
3D80DA4A1DF820620028D040 /* RCTAccessibilityManager.h in Headers */,
3D80DA4B1DF820620028D040 /* RCTAlertManager.h in Headers */,
3D80DA4C1DF820620028D040 /* RCTAppState.h in Headers */,
+ 3D0E378C1F1CC58C00DCAC9F /* RCTWebSocketObserver.h in Headers */,
3D80DA4D1DF820620028D040 /* RCTAsyncLocalStorage.h in Headers */,
3D80DA4E1DF820620028D040 /* RCTClipboard.h in Headers */,
3D80DA4F1DF820620028D040 /* RCTDevLoadingView.h in Headers */,
@@ -3092,6 +3097,7 @@
C6194AB01EF156280034D062 /* RCTPackagerConnectionConfig.h in Headers */,
CF2731C01E7B8DE40044CA4F /* RCTDeviceInfo.h in Headers */,
3D80DA611DF820620028D040 /* RCTAnimationType.h in Headers */,
+ 3D0E378A1F1CC40000DCAC9F /* RCTWebSocketModule.h in Headers */,
3D80DA621DF820620028D040 /* RCTAutoInsetsProtocol.h in Headers */,
3D80DA631DF820620028D040 /* RCTBorderDrawing.h in Headers */,
3D80DA641DF820620028D040 /* RCTBorderStyle.h in Headers */,
diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK
new file mode 100644
index 00000000000..936f5e5719d
--- /dev/null
+++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK
@@ -0,0 +1,22 @@
+include_defs("//ReactAndroid/DEFS")
+
+android_library(
+ name = "blob",
+ srcs = glob(["**/*.java"]),
+ visibility = [
+ "PUBLIC",
+ ],
+ deps = [
+ react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"),
+ react_native_dep("third-party/android/support-annotations:android-support-annotations"),
+ react_native_dep("third-party/android/support/v4:lib-support-v4"),
+ react_native_dep("third-party/java/infer-annotations:infer-annotations"),
+ react_native_dep("third-party/java/jsr-305:jsr-305"),
+ react_native_dep("third-party/java/okio:okio"),
+ react_native_target("java/com/facebook/react:react"),
+ react_native_target("java/com/facebook/react/bridge:bridge"),
+ react_native_target("java/com/facebook/react/common:common"),
+ react_native_target("java/com/facebook/react/module/annotations:annotations"),
+ react_native_target("java/com/facebook/react/modules/websocket:websocket"),
+ ],
+)
diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.java
new file mode 100644
index 00000000000..e213bb749dd
--- /dev/null
+++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.java
@@ -0,0 +1,180 @@
+/**
+ * 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.modules.blob;
+
+import android.content.res.Resources;
+import android.net.Uri;
+import android.support.annotation.Nullable;
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.bridge.ReadableMap;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.common.MapBuilder;
+import com.facebook.react.module.annotations.ReactModule;
+import com.facebook.react.modules.websocket.WebSocketModule;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import okio.ByteString;
+
+@ReactModule(name = BlobModule.NAME)
+public class BlobModule extends ReactContextBaseJavaModule {
+
+ protected static final String NAME = "BlobModule";
+
+ private final Map mBlobs = new HashMap<>();
+
+ protected final WebSocketModule.ContentHandler mContentHandler =
+ new WebSocketModule.ContentHandler() {
+ @Override
+ public void onMessage(String text, WritableMap params) {
+ params.putString("data", text);
+ }
+
+ @Override
+ public void onMessage(ByteString bytes, WritableMap params) {
+ byte[] data = bytes.toByteArray();
+
+ WritableMap blob = Arguments.createMap();
+
+ blob.putString("blobId", store(data));
+ blob.putInt("offset", 0);
+ blob.putInt("size", data.length);
+
+ params.putMap("data", blob);
+ params.putString("type", "blob");
+ }
+ };
+
+ public BlobModule(ReactApplicationContext reactContext) {
+ super(reactContext);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ @Nullable
+ public Map getConstants() {
+ // The application can register BlobProvider as a ContentProvider so that blobs are resolvable.
+ // If it does, it needs to tell us what authority was used via this string resource.
+ Resources resources = getReactApplicationContext().getResources();
+ String packageName = getReactApplicationContext().getPackageName();
+ int resourceId = resources.getIdentifier("blob_provider_authority", "string", packageName);
+ if (resourceId == 0) {
+ return null;
+ }
+
+ return MapBuilder.of(
+ "BLOB_URI_SCHEME", "content", "BLOB_URI_HOST", resources.getString(resourceId));
+ }
+
+ public String store(byte[] data) {
+ String blobId = UUID.randomUUID().toString();
+ store(data, blobId);
+ return blobId;
+ }
+
+ public void store(byte[] data, String blobId) {
+ mBlobs.put(blobId, data);
+ }
+
+ public void remove(String blobId) {
+ mBlobs.remove(blobId);
+ }
+
+ @Nullable
+ public byte[] resolve(Uri uri) {
+ String blobId = uri.getLastPathSegment();
+ int offset = 0;
+ int size = -1;
+ String offsetParam = uri.getQueryParameter("offset");
+ if (offsetParam != null) {
+ offset = Integer.parseInt(offsetParam, 10);
+ }
+ String sizeParam = uri.getQueryParameter("size");
+ if (sizeParam != null) {
+ size = Integer.parseInt(sizeParam, 10);
+ }
+ return resolve(blobId, offset, size);
+ }
+
+ @Nullable
+ public byte[] resolve(String blobId, int offset, int size) {
+ byte[] data = mBlobs.get(blobId);
+ if (data == null) {
+ return null;
+ }
+ if (size == -1) {
+ size = data.length - offset;
+ }
+ if (offset > 0) {
+ data = Arrays.copyOfRange(data, offset, offset + size);
+ }
+ return data;
+ }
+
+ @Nullable
+ public byte[] resolve(ReadableMap blob) {
+ return resolve(blob.getString("blobId"), blob.getInt("offset"), blob.getInt("size"));
+ }
+
+ private WebSocketModule getWebSocketModule() {
+ return getReactApplicationContext().getNativeModule(WebSocketModule.class);
+ }
+
+ @ReactMethod
+ public void enableBlobSupport(final int id) {
+ getWebSocketModule().setContentHandler(id, mContentHandler);
+ }
+
+ @ReactMethod
+ public void disableBlobSupport(final int id) {
+ getWebSocketModule().setContentHandler(id, null);
+ }
+
+ @ReactMethod
+ public void sendBlob(ReadableMap blob, int id) {
+ byte[] data = resolve(blob.getString("blobId"), blob.getInt("offset"), blob.getInt("size"));
+
+ if (data != null) {
+ getWebSocketModule().sendBinary(ByteString.of(data), id);
+ } else {
+ getWebSocketModule().sendBinary((ByteString) null, id);
+ }
+ }
+
+ @ReactMethod
+ public void createFromParts(ReadableArray parts, String blobId) {
+ int totalBlobSize = 0;
+ ArrayList partList = new ArrayList<>(parts.size());
+ for (int i = 0; i < parts.size(); i++) {
+ ReadableMap part = parts.getMap(i);
+ totalBlobSize += part.getInt("size");
+ partList.add(i, part);
+ }
+ ByteBuffer buffer = ByteBuffer.allocate(totalBlobSize);
+ for (ReadableMap part : partList) {
+ buffer.put(resolve(part));
+ }
+ store(buffer.array(), blobId);
+ }
+
+ @ReactMethod
+ public void release(String blobId) {
+ remove(blobId);
+ }
+}
diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobProvider.java b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobProvider.java
new file mode 100644
index 00000000000..2404f2dbab1
--- /dev/null
+++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobProvider.java
@@ -0,0 +1,99 @@
+/**
+ * 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.modules.blob;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.Nullable;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.bridge.ReactContext;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public final class BlobProvider extends ContentProvider {
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public @Nullable Cursor query(
+ Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public @Nullable String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public @Nullable Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ if (!mode.equals("r")) {
+ throw new FileNotFoundException("Cannot open " + uri.toString() + " in mode '" + mode + "'");
+ }
+
+ BlobModule blobModule = null;
+ Context context = getContext().getApplicationContext();
+ if (context instanceof ReactApplication) {
+ ReactNativeHost host = ((ReactApplication) context).getReactNativeHost();
+ ReactContext reactContext = host.getReactInstanceManager().getCurrentReactContext();
+ blobModule = reactContext.getNativeModule(BlobModule.class);
+ }
+
+ if (blobModule == null) {
+ throw new RuntimeException("No blob module associated with BlobProvider");
+ }
+
+ byte[] data = blobModule.resolve(uri);
+ if (data == null) {
+ throw new FileNotFoundException("Cannot open " + uri.toString() + ", blob not found.");
+ }
+
+ ParcelFileDescriptor[] pipe;
+ try {
+ pipe = ParcelFileDescriptor.createPipe();
+ } catch (IOException exception) {
+ return null;
+ }
+ ParcelFileDescriptor readSide = pipe[0];
+ ParcelFileDescriptor writeSide = pipe[1];
+
+ OutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(writeSide);
+ try {
+ outputStream.write(data);
+ outputStream.close();
+ } catch (IOException exception) {
+ return null;
+ }
+
+ return readSide;
+ }
+}
diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java
index 8f95b674f0b..17df446110b 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java
@@ -9,16 +9,6 @@
package com.facebook.react.modules.websocket;
-import javax.annotation.Nullable;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
@@ -34,7 +24,14 @@ import com.facebook.react.common.ReactConstants;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.modules.network.ForwardingCookieHandler;
-
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@@ -43,9 +40,16 @@ import okhttp3.WebSocketListener;
import okio.ByteString;
@ReactModule(name = "WebSocketModule", hasConstants = false)
-public class WebSocketModule extends ReactContextBaseJavaModule {
+public final class WebSocketModule extends ReactContextBaseJavaModule {
+
+ public interface ContentHandler {
+ void onMessage(String text, WritableMap params);
+
+ void onMessage(ByteString byteString, WritableMap params);
+ }
private final Map mWebSocketConnections = new HashMap<>();
+ private final Map mContentHandlers = new HashMap<>();
private ReactContext mReactContext;
private ForwardingCookieHandler mCookieHandler;
@@ -67,6 +71,14 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
return "WebSocketModule";
}
+ public void setContentHandler(final int id, final ContentHandler contentHandler) {
+ if (contentHandler != null) {
+ mContentHandlers.put(id, contentHandler);
+ } else {
+ mContentHandlers.remove(id);
+ }
+ }
+
@ReactMethod
public void connect(
final String url,
@@ -79,9 +91,7 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
.build();
- Request.Builder builder = new Request.Builder()
- .tag(id)
- .url(url);
+ Request.Builder builder = new Request.Builder().tag(id).url(url);
String cookie = getCookie(url);
if (cookie != null) {
@@ -124,49 +134,65 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
}
}
- client.newWebSocket(builder.build(), new WebSocketListener() {
+ client.newWebSocket(
+ builder.build(),
+ new WebSocketListener() {
- @Override
- public void onOpen(WebSocket webSocket, Response response) {
- mWebSocketConnections.put(id, webSocket);
- WritableMap params = Arguments.createMap();
- params.putInt("id", id);
- sendEvent("websocketOpen", params);
- }
+ @Override
+ public void onOpen(WebSocket webSocket, Response response) {
+ mWebSocketConnections.put(id, webSocket);
+ WritableMap params = Arguments.createMap();
+ params.putInt("id", id);
+ sendEvent("websocketOpen", params);
+ }
- @Override
- public void onClosed(WebSocket webSocket, int code, String reason) {
- WritableMap params = Arguments.createMap();
- params.putInt("id", id);
- params.putInt("code", code);
- params.putString("reason", reason);
- sendEvent("websocketClosed", params);
- }
+ @Override
+ public void onClosed(WebSocket webSocket, int code, String reason) {
+ WritableMap params = Arguments.createMap();
+ params.putInt("id", id);
+ params.putInt("code", code);
+ params.putString("reason", reason);
+ sendEvent("websocketClosed", params);
+ }
- @Override
- public void onFailure(WebSocket webSocket, Throwable t, Response response) {
- notifyWebSocketFailed(id, t.getMessage());
- }
+ @Override
+ public void onFailure(WebSocket webSocket, Throwable t, Response response) {
+ notifyWebSocketFailed(id, t.getMessage());
+ }
- @Override
- public void onMessage(WebSocket webSocket, String text) {
- WritableMap params = Arguments.createMap();
- params.putInt("id", id);
- params.putString("data", text);
- params.putString("type", "text");
- sendEvent("websocketMessage", params);
- }
+ @Override
+ public void onMessage(WebSocket webSocket, String text) {
+ WritableMap params = Arguments.createMap();
+ params.putInt("id", id);
+ params.putString("type", "text");
- @Override
- public void onMessage(WebSocket webSocket, ByteString bytes) {
- String text = bytes.base64();
- WritableMap params = Arguments.createMap();
- params.putInt("id", id);
- params.putString("data", text);
- params.putString("type", "binary");
- sendEvent("websocketMessage", params);
- }
- });
+ ContentHandler contentHandler = mContentHandlers.get(id);
+ if (contentHandler != null) {
+ contentHandler.onMessage(text, params);
+ } else {
+ params.putString("data", text);
+ }
+ sendEvent("websocketMessage", params);
+ }
+
+ @Override
+ public void onMessage(WebSocket webSocket, ByteString bytes) {
+ WritableMap params = Arguments.createMap();
+ params.putInt("id", id);
+ params.putString("type", "binary");
+
+ ContentHandler contentHandler = mContentHandlers.get(id);
+ if (contentHandler != null) {
+ contentHandler.onMessage(bytes, params);
+ } else {
+ String text = bytes.base64();
+
+ params.putString("data", text);
+ }
+
+ sendEvent("websocketMessage", params);
+ }
+ });
// Trigger shutdown of the dispatcher's executor so this process can exit cleanly
client.dispatcher().executorService().shutdown();
@@ -183,6 +209,7 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
try {
client.close(code, reason);
mWebSocketConnections.remove(id);
+ mContentHandlers.remove(id);
} catch (Exception e) {
FLog.e(
ReactConstants.TAG,
@@ -219,6 +246,19 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
}
}
+ public void sendBinary(ByteString byteString, int id) {
+ WebSocket client = mWebSocketConnections.get(id);
+ if (client == null) {
+ // This is a programmer error
+ throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id);
+ }
+ try {
+ client.send(byteString);
+ } catch (Exception e) {
+ notifyWebSocketFailed(id, e.getMessage());
+ }
+ }
+
@ReactMethod
public void ping(int id) {
WebSocket client = mWebSocketConnections.get(id);
@@ -243,10 +283,9 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
/**
* Get the default HTTP(S) origin for a specific WebSocket URI
*
- * @param String uri
+ * @param uri
* @return A string of the endpoint converted to HTTP protocol (http[s]://host[:port])
*/
-
private static String getDefaultOrigin(String uri) {
try {
String defaultOrigin;
@@ -280,7 +319,7 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
/**
* Get the cookie for a specific domain
*
- * @param String uri
+ * @param uri
* @return The cookie header or null if none is set
*/
private String getCookie(String uri) {
diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
index d6688926cc7..fdd003be9c9 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
+++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
@@ -23,6 +23,7 @@ android_library(
react_native_target("java/com/facebook/react/module/model:model"),
react_native_target("java/com/facebook/react/modules/accessibilityinfo:accessibilityinfo"),
react_native_target("java/com/facebook/react/modules/appstate:appstate"),
+ react_native_target("java/com/facebook/react/modules/blob:blob"),
react_native_target("java/com/facebook/react/modules/camera:camera"),
react_native_target("java/com/facebook/react/modules/clipboard:clipboard"),
react_native_target("java/com/facebook/react/modules/core:core"),
diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
index 1d2e839ecae..c4a32965d3d 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
@@ -13,7 +13,6 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.facebook.react.LazyReactPackage;
import com.facebook.react.animated.NativeAnimatedModule;
-import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.ModuleSpec;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
@@ -30,6 +29,7 @@ import com.facebook.react.flat.RCTVirtualTextManager;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.modules.accessibilityinfo.AccessibilityInfoModule;
import com.facebook.react.modules.appstate.AppStateModule;
+import com.facebook.react.modules.blob.BlobModule;
import com.facebook.react.modules.camera.CameraRollManager;
import com.facebook.react.modules.camera.ImageEditingManager;
import com.facebook.react.modules.camera.ImageStoreManager;
@@ -74,12 +74,10 @@ import com.facebook.react.views.toolbar.ReactToolbarManager;
import com.facebook.react.views.view.ReactViewManager;
import com.facebook.react.views.viewpager.ReactViewPagerManager;
import com.facebook.react.views.webview.ReactWebViewManager;
-
-import javax.inject.Provider;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
+import javax.inject.Provider;
/**
* Package defining basic modules and view managers.
@@ -101,150 +99,207 @@ public class MainReactPackage extends LazyReactPackage {
@Override
public List getNativeModules(final ReactApplicationContext context) {
return Arrays.asList(
- new ModuleSpec(AccessibilityInfoModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new AccessibilityInfoModule(context);
- }
- }),
- new ModuleSpec(AppStateModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new AppStateModule(context);
- }
- }),
- new ModuleSpec(AsyncStorageModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new AsyncStorageModule(context);
- }
- }),
- new ModuleSpec(CameraRollManager.class, new Provider() {
- @Override
- public NativeModule get() {
- return new CameraRollManager(context);
- }
- }),
- new ModuleSpec(ClipboardModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new ClipboardModule(context);
- }
- }),
- new ModuleSpec(DatePickerDialogModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new DatePickerDialogModule(context);
- }
- }),
- new ModuleSpec(DialogModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new DialogModule(context);
- }
- }),
- new ModuleSpec(FrescoModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new FrescoModule(context, true, mConfig != null ? mConfig.getFrescoConfig() : null);
- }
- }),
- new ModuleSpec(I18nManagerModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new I18nManagerModule(context);
- }
- }),
- new ModuleSpec(ImageEditingManager.class, new Provider() {
- @Override
- public NativeModule get() {
- return new ImageEditingManager(context);
- }
- }),
- new ModuleSpec(ImageLoaderModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new ImageLoaderModule(context);
- }
- }),
- new ModuleSpec(ImageStoreManager.class, new Provider() {
- @Override
- public NativeModule get() {
- return new ImageStoreManager(context);
- }
- }),
- new ModuleSpec(IntentModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new IntentModule(context);
- }
- }),
- new ModuleSpec(LocationModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new LocationModule(context);
- }
- }),
- new ModuleSpec(NativeAnimatedModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new NativeAnimatedModule(context);
- }
- }),
- new ModuleSpec(NetworkingModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new NetworkingModule(context);
- }
- }),
- new ModuleSpec(NetInfoModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new NetInfoModule(context);
- }
- }),
- new ModuleSpec(PermissionsModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new PermissionsModule(context);
- }
- }),
- new ModuleSpec(ShareModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new ShareModule(context);
- }
- }),
- new ModuleSpec(StatusBarModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new StatusBarModule(context);
- }
- }),
- new ModuleSpec(TimePickerDialogModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new TimePickerDialogModule(context);
- }
- }),
- new ModuleSpec(ToastModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new ToastModule(context);
- }
- }),
- new ModuleSpec(VibrationModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new VibrationModule(context);
- }
- }),
- new ModuleSpec(WebSocketModule.class, new Provider() {
- @Override
- public NativeModule get() {
- return new WebSocketModule(context);
- }
- }));
+ new ModuleSpec(
+ AccessibilityInfoModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new AccessibilityInfoModule(context);
+ }
+ }),
+ new ModuleSpec(
+ AppStateModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new AppStateModule(context);
+ }
+ }),
+ new ModuleSpec(
+ BlobModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new BlobModule(context);
+ }
+ }),
+ new ModuleSpec(
+ AsyncStorageModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new AsyncStorageModule(context);
+ }
+ }),
+ new ModuleSpec(
+ CameraRollManager.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new CameraRollManager(context);
+ }
+ }),
+ new ModuleSpec(
+ ClipboardModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new ClipboardModule(context);
+ }
+ }),
+ new ModuleSpec(
+ DatePickerDialogModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new DatePickerDialogModule(context);
+ }
+ }),
+ new ModuleSpec(
+ DialogModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new DialogModule(context);
+ }
+ }),
+ new ModuleSpec(
+ FrescoModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new FrescoModule(
+ context, true, mConfig != null ? mConfig.getFrescoConfig() : null);
+ }
+ }),
+ new ModuleSpec(
+ I18nManagerModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new I18nManagerModule(context);
+ }
+ }),
+ new ModuleSpec(
+ ImageEditingManager.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new ImageEditingManager(context);
+ }
+ }),
+ new ModuleSpec(
+ ImageLoaderModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new ImageLoaderModule(context);
+ }
+ }),
+ new ModuleSpec(
+ ImageStoreManager.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new ImageStoreManager(context);
+ }
+ }),
+ new ModuleSpec(
+ IntentModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new IntentModule(context);
+ }
+ }),
+ new ModuleSpec(
+ LocationModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new LocationModule(context);
+ }
+ }),
+ new ModuleSpec(
+ NativeAnimatedModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new NativeAnimatedModule(context);
+ }
+ }),
+ new ModuleSpec(
+ NetworkingModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new NetworkingModule(context);
+ }
+ }),
+ new ModuleSpec(
+ NetInfoModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new NetInfoModule(context);
+ }
+ }),
+ new ModuleSpec(
+ PermissionsModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new PermissionsModule(context);
+ }
+ }),
+ new ModuleSpec(
+ ShareModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new ShareModule(context);
+ }
+ }),
+ new ModuleSpec(
+ StatusBarModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new StatusBarModule(context);
+ }
+ }),
+ new ModuleSpec(
+ TimePickerDialogModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new TimePickerDialogModule(context);
+ }
+ }),
+ new ModuleSpec(
+ ToastModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new ToastModule(context);
+ }
+ }),
+ new ModuleSpec(
+ VibrationModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new VibrationModule(context);
+ }
+ }),
+ new ModuleSpec(
+ WebSocketModule.class,
+ new Provider() {
+ @Override
+ public NativeModule get() {
+ return new WebSocketModule(context);
+ }
+ }));
}
@Override
diff --git a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj
index e4471789dbd..e0c1aa68859 100644
--- a/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj
+++ b/local-cli/templates/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj
@@ -36,6 +36,7 @@
2DCD954D1E0B4F2C00145EB5 /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; };
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
+ ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -228,6 +229,13 @@
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
+ ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 358F4ED71D1E81A9004DF814;
+ remoteInfo = RCTBlob;
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
@@ -255,6 +263,7 @@
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; };
+ ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -270,6 +279,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */,
+ 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
@@ -411,6 +422,7 @@
3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,
3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,
3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,
+ 3DAD3EA31DF850E9000B6D8A /* libReact-tvOS.a */,
);
name = Products;
sourceTree = "";
@@ -439,6 +451,7 @@
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
+ ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */,
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
@@ -483,6 +496,14 @@
name = Products;
sourceTree = "";
};
+ ADBDB9201DFEBF0600ED6528 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -602,6 +623,10 @@
ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */;
ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
},
+ {
+ ProductGroup = ADBDB9201DFEBF0600ED6528 /* Products */;
+ ProjectRef = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */;
+ },
{
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -748,10 +773,10 @@
remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
- 3DAD3EA31DF850E9000B6D8A /* libReact.a */ = {
+ 3DAD3EA31DF850E9000B6D8A /* libReact-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
- path = libReact.a;
+ path = "libReact-tvOS.a";
remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@@ -825,6 +850,13 @@
remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTBlob.a;
+ remoteRef = ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */