mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-08 09:37:21 +08:00
Add blob implementation with WebSocket integration
Summary: This is the first PR from a series of PRs grabbou and me will make to add blob support to React Native. The next PR will include blob support for XMLHttpRequest. I'd like to get this merged with minimal changes to preserve the attribution. My next PR can contain bigger changes. Blobs are used to transfer binary data between server and client. Currently React Native lacks a way to deal with binary data. The only thing that comes close is uploading files through a URI. Current workarounds to transfer binary data includes encoding and decoding them to base64 and and transferring them as string, which is not ideal, since it increases the payload size and the whole payload needs to be sent via the bridge every time changes are made. The PR adds a way to deal with blobs via a new native module. The blob is constructed on the native side and the data never needs to pass through the bridge. Currently the only way to create a blob is to receive a blob from the server via websocket. The PR is largely a direct port of https://github.com/silklabs/silk/tree/master/react-native-blobs by philikon into RN (with changes to integrate with RN), and attributed as such. > **Note:** This is a breaking change for all people running iOS without CocoaPods. You will have to manually add `RCTBlob.xcodeproj` to your `Libraries` and then, add it to Build Phases. Just follow the process of manual linking. We'll also need to document this process in the release notes. Related discussion - https://github.com/facebook/react-native/issues/11103 - `Image` can't show image when `URL.createObjectURL` is used with large images on Android The websocket integration can be tested via a simple server, ```js const fs = require('fs'); const http = require('http'); const WebSocketServer = require('ws').Server; const wss = new WebSocketServer({ server: http.createServer().listen(7232), }); wss.on('connection', (ws) => { ws.on('message', (d) => { console.log(d); }); ws.send(fs.readFileSync('./some-file')); }); ``` Then on the client, ```js var ws = new WebSocket('ws://localhost:7232'); ws.binaryType = 'blob'; ws.onerror = (error) => { console.error(error); }; ws.onmessage = (e) => { console.log(e.data); ws.send(e.data); }; ``` cc brentvatne ide Closes https://github.com/facebook/react-native/pull/11417 Reviewed By: sahrens Differential Revision: D5188484 Pulled By: javache fbshipit-source-id: 6afcbc4d19aa7a27b0dc9d52701ba400e7d7e98f
This commit is contained in:
committed by
Facebook Github Bot
parent
91493f6b9d
commit
ed903099b4
@@ -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"),
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* <p>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<String, byte[]> 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<ReadableMap> 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* <p>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;
|
||||
}
|
||||
}
|
||||
@@ -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<Integer, WebSocket> mWebSocketConnections = new HashMap<>();
|
||||
private final Map<Integer, ContentHandler> 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) {
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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<ModuleSpec> getNativeModules(final ReactApplicationContext context) {
|
||||
return Arrays.asList(
|
||||
new ModuleSpec(AccessibilityInfoModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new AccessibilityInfoModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(AppStateModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new AppStateModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(AsyncStorageModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new AsyncStorageModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(CameraRollManager.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new CameraRollManager(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(ClipboardModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ClipboardModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(DatePickerDialogModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new DatePickerDialogModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(DialogModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new DialogModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(FrescoModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new FrescoModule(context, true, mConfig != null ? mConfig.getFrescoConfig() : null);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(I18nManagerModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new I18nManagerModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(ImageEditingManager.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ImageEditingManager(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(ImageLoaderModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ImageLoaderModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(ImageStoreManager.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ImageStoreManager(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(IntentModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new IntentModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(LocationModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new LocationModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(NativeAnimatedModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new NativeAnimatedModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(NetworkingModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new NetworkingModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(NetInfoModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new NetInfoModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(PermissionsModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new PermissionsModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(ShareModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ShareModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(StatusBarModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new StatusBarModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(TimePickerDialogModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new TimePickerDialogModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(ToastModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ToastModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(VibrationModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new VibrationModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(WebSocketModule.class, new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new WebSocketModule(context);
|
||||
}
|
||||
}));
|
||||
new ModuleSpec(
|
||||
AccessibilityInfoModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new AccessibilityInfoModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
AppStateModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new AppStateModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
BlobModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new BlobModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
AsyncStorageModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new AsyncStorageModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
CameraRollManager.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new CameraRollManager(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
ClipboardModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ClipboardModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
DatePickerDialogModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new DatePickerDialogModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
DialogModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new DialogModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
FrescoModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new FrescoModule(
|
||||
context, true, mConfig != null ? mConfig.getFrescoConfig() : null);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
I18nManagerModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new I18nManagerModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
ImageEditingManager.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ImageEditingManager(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
ImageLoaderModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ImageLoaderModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
ImageStoreManager.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ImageStoreManager(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
IntentModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new IntentModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
LocationModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new LocationModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
NativeAnimatedModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new NativeAnimatedModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
NetworkingModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new NetworkingModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
NetInfoModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new NetInfoModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
PermissionsModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new PermissionsModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
ShareModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ShareModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
StatusBarModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new StatusBarModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
TimePickerDialogModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new TimePickerDialogModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
ToastModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new ToastModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
VibrationModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new VibrationModule(context);
|
||||
}
|
||||
}),
|
||||
new ModuleSpec(
|
||||
WebSocketModule.class,
|
||||
new Provider<NativeModule>() {
|
||||
@Override
|
||||
public NativeModule get() {
|
||||
return new WebSocketModule(context);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user