+ * Certain versions of Android (Jellybean-KitKat) have a bug where when dismissed, the + * {@link DatePickerDialog} still calls the OnDateSetListener. This class works around that issue. + *
+ * + *+ * See: Issue 34833 + *
+ */ +public class DismissableDatePickerDialog extends DatePickerDialog { + + public DismissableDatePickerDialog( + Context context, + @Nullable OnDateSetListener callback, + int year, + int monthOfYear, + int dayOfMonth) { + super(context, callback, year, monthOfYear, dayOfMonth); + } + + public DismissableDatePickerDialog( + Context context, + int theme, + @Nullable OnDateSetListener callback, + int year, + int monthOfYear, + int dayOfMonth) { + super(context, theme, callback, year, monthOfYear, dayOfMonth); + } + + @Override + protected void onStop() { + // do *not* call super.onStop() on KitKat on lower, as that would erroneously call the + // OnDateSetListener when the dialog is dismissed, or call it twice when "OK" is pressed. + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + super.onStop(); + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/SupportDatePickerDialogFragment.java b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/SupportDatePickerDialogFragment.java new file mode 100644 index 00000000000000..d935d58d84d542 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/SupportDatePickerDialogFragment.java @@ -0,0 +1,51 @@ +/** + * 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.datepicker; + +import javax.annotation.Nullable; + +import android.annotation.SuppressLint; +import android.app.DatePickerDialog.OnDateSetListener; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; + +@SuppressLint("ValidFragment") +public class SupportDatePickerDialogFragment extends DialogFragment { + + @Nullable + private OnDateSetListener mOnDateSetListener; + @Nullable + private OnDismissListener mOnDismissListener; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Bundle args = getArguments(); + return DatePickerDialogFragment.createDialog(args, getActivity(), mOnDateSetListener); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + if (mOnDismissListener != null) { + mOnDismissListener.onDismiss(dialog); + } + } + + /*package*/ void setOnDateSetListener(@Nullable OnDateSetListener onDateSetListener) { + mOnDateSetListener = onDateSetListener; + } + + /*package*/ void setOnDismissListener(@Nullable OnDismissListener onDismissListener) { + mOnDismissListener = onDismissListener; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java index ce4681264193da..8f57f570ea7337 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java @@ -13,8 +13,8 @@ import android.content.Intent; import android.net.Uri; -import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -36,10 +36,10 @@ public String getName() { /** * Return the URL the activity was started with * - * @param callback a callback which is called with the initial URL + * @param promise a promise which is resolved with the initial URL */ @ReactMethod - public void getInitialURL(Callback callback) { + public void getInitialURL(Promise promise) { try { Activity currentActivity = getCurrentActivity(); String initialURL = null; @@ -54,10 +54,10 @@ public void getInitialURL(Callback callback) { } } - callback.invoke(initialURL); + promise.resolve(initialURL); } catch (Exception e) { - throw new JSApplicationIllegalArgumentException( - "Could not get the initial URL : " + e.getMessage()); + promise.reject(new JSApplicationIllegalArgumentException( + "Could not get the initial URL : " + e.getMessage())); } } @@ -70,9 +70,10 @@ public void getInitialURL(Callback callback) { * @param url the URL to open */ @ReactMethod - public void openURL(String url) { + public void openURL(String url, Promise promise) { if (url == null || url.isEmpty()) { - throw new JSApplicationIllegalArgumentException("Invalid URL: " + url); + promise.reject(new JSApplicationIllegalArgumentException("Invalid URL: " + url)); + return; } try { @@ -85,9 +86,11 @@ public void openURL(String url) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getReactApplicationContext().startActivity(intent); } + + promise.resolve(true); } catch (Exception e) { - throw new JSApplicationIllegalArgumentException( - "Could not open URL '" + url + "': " + e.getMessage()); + promise.reject(new JSApplicationIllegalArgumentException( + "Could not open URL '" + url + "': " + e.getMessage())); } } @@ -95,12 +98,13 @@ public void openURL(String url) { * Determine whether or not an installed app can handle a given URL. * * @param url the URL to open - * @param callback a callback that is always called with a boolean argument + * @param promise a promise that is always resolved with a boolean argument */ @ReactMethod - public void canOpenURL(String url, Callback callback) { + public void canOpenURL(String url, Promise promise) { if (url == null || url.isEmpty()) { - throw new JSApplicationIllegalArgumentException("Invalid URL: " + url); + promise.reject(new JSApplicationIllegalArgumentException("Invalid URL: " + url)); + return; } try { @@ -110,10 +114,10 @@ public void canOpenURL(String url, Callback callback) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); boolean canOpen = intent.resolveActivity(getReactApplicationContext().getPackageManager()) != null; - callback.invoke(canOpen); + promise.resolve(canOpen); } catch (Exception e) { - throw new JSApplicationIllegalArgumentException( - "Could not check if URL '" + url + "' can be opened: " + e.getMessage()); + promise.reject(new JSApplicationIllegalArgumentException( + "Could not check if URL '" + url + "' can be opened: " + e.getMessage())); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java index bff80bf26b222c..463ad17c4d591b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/netinfo/NetInfoModule.java @@ -106,10 +106,14 @@ private void registerReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); getReactApplicationContext().registerReceiver(mConnectivityBroadcastReceiver, filter); + mConnectivityBroadcastReceiver.setRegistered(true); } private void unregisterReceiver() { - getReactApplicationContext().unregisterReceiver(mConnectivityBroadcastReceiver); + if (mConnectivityBroadcastReceiver.isRegistered()) { + getReactApplicationContext().unregisterReceiver(mConnectivityBroadcastReceiver); + mConnectivityBroadcastReceiver.setRegistered(false); + } } private void updateAndSendConnectionType() { @@ -155,6 +159,17 @@ private WritableMap createConnectivityEventMap() { */ private class ConnectivityBroadcastReceiver extends BroadcastReceiver { + //TODO: Remove registered check when source of crash is found. t9846865 + private boolean isRegistered = false; + + public void setRegistered(boolean registered) { + isRegistered = registered; + } + + public boolean isRegistered() { + return isRegistered; + } + @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 9374683b9d8efd..50cd58a08da0c0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -132,7 +132,15 @@ public void sendRequest( requestBuilder.tag(requestId); } - mClient.setConnectTimeout(timeout, TimeUnit.MILLISECONDS); + OkHttpClient client = mClient; + // If the current timeout does not equal the passed in timeout, we need to clone the existing + // client and set the timeout explicitly on the clone. This is cheap as everything else is + // shared under the hood. + // See https://github.com/square/okhttp/wiki/Recipes#per-call-configuration for more information + if (timeout != mClient.getConnectTimeout()) { + client = mClient.clone(); + client.setReadTimeout(timeout, TimeUnit.MILLISECONDS); + } Headers requestHeaders = extractHeaders(headers, data); if (requestHeaders == null) { @@ -193,7 +201,7 @@ public void sendRequest( requestBuilder.method(method, null); } - mClient.newCall(requestBuilder.build()).enqueue( + client.newCall(requestBuilder.build()).enqueue( new Callback() { @Override public void onFailure(Request request, IOException e) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK new file mode 100644 index 00000000000000..1b7d3eac350cb1 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK @@ -0,0 +1,20 @@ +include_defs('//ReactAndroid/DEFS') + +android_library( + name = 'timepicker', + srcs = glob(['**/*.java']), + deps = [ + react_native_target('java/com/facebook/react/bridge:bridge'), + react_native_target('java/com/facebook/react/common:common'), + 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'), + ], + visibility = [ + 'PUBLIC', + ], +) + +project_config( + src_target = ':timepicker', +) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/DismissableTimePickerDialog.java b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/DismissableTimePickerDialog.java new file mode 100644 index 00000000000000..3baf4c92416643 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/DismissableTimePickerDialog.java @@ -0,0 +1,58 @@ +/** + * 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.timepicker; + +import javax.annotation.Nullable; + +import android.app.TimePickerDialog; +import android.content.Context; +import android.os.Build; + +/** + *+ * Certain versions of Android (Jellybean-KitKat) have a bug where when dismissed, the + * {@link TimePickerDialog} still calls the OnTimeSetListener. This class works around that issue + * by *not* calling super.onStop on KitKat on lower, as that would erroneously call the + * OnTimeSetListener when the dialog is dismissed, or call it twice when "OK" is pressed. + *
+ * + *+ * See: Issue 34833 + *
+ */ +public class DismissableTimePickerDialog extends TimePickerDialog { + + public DismissableTimePickerDialog( + Context context, + @Nullable OnTimeSetListener callback, + int hourOfDay, + int minute, + boolean is24HourView) { + super(context, callback, hourOfDay, minute, is24HourView); + } + + public DismissableTimePickerDialog( + Context context, + int theme, + @Nullable OnTimeSetListener callback, + int hourOfDay, + int minute, + boolean is24HourView) { + super(context, theme, callback, hourOfDay, minute, is24HourView); + } + + @Override + protected void onStop() { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + super.onStop(); + } + } + +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/SupportTimePickerDialogFragment.java b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/SupportTimePickerDialogFragment.java new file mode 100644 index 00000000000000..d745984a1d42bd --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/SupportTimePickerDialogFragment.java @@ -0,0 +1,50 @@ +/** + * 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.timepicker; + +import javax.annotation.Nullable; + +import android.app.Dialog; +import android.app.TimePickerDialog.OnTimeSetListener; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; + +@SuppressWarnings("ValidFragment") +public class SupportTimePickerDialogFragment extends DialogFragment { + + @Nullable + private OnTimeSetListener mOnTimeSetListener; + @Nullable + private OnDismissListener mOnDismissListener; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Bundle args = getArguments(); + return TimePickerDialogFragment.createDialog(args, getActivity(), mOnTimeSetListener); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + if (mOnDismissListener != null) { + mOnDismissListener.onDismiss(dialog); + } + } + + public void setOnDismissListener(@Nullable OnDismissListener onDismissListener) { + mOnDismissListener = onDismissListener; + } + + public void setOnTimeSetListener(@Nullable OnTimeSetListener onTimeSetListener) { + mOnTimeSetListener = onTimeSetListener; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogFragment.java b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogFragment.java new file mode 100644 index 00000000000000..64005ae1a8452a --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogFragment.java @@ -0,0 +1,78 @@ +/** + * 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.timepicker; + +import javax.annotation.Nullable; + +import java.util.Calendar; + +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.TimePickerDialog.OnTimeSetListener; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.os.Bundle; +import android.text.format.DateFormat; + +@SuppressWarnings("ValidFragment") +public class TimePickerDialogFragment extends DialogFragment { + + @Nullable + private OnTimeSetListener mOnTimeSetListener; + @Nullable + private OnDismissListener mOnDismissListener; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Bundle args = getArguments(); + return createDialog(args, getActivity(), mOnTimeSetListener); + } + + /*package*/ static Dialog createDialog( + Bundle args, Context activityContext, @Nullable OnTimeSetListener onTimeSetListener + ) { + final Calendar now = Calendar.getInstance(); + int hour = now.get(Calendar.HOUR_OF_DAY); + int minute = now.get(Calendar.MINUTE); + boolean is24hour = DateFormat.is24HourFormat(activityContext); + + if (args != null) { + hour = args.getInt(TimePickerDialogModule.ARG_HOUR, now.get(Calendar.HOUR_OF_DAY)); + minute = args.getInt(TimePickerDialogModule.ARG_MINUTE, now.get(Calendar.MINUTE)); + is24hour = args.getBoolean( + TimePickerDialogModule.ARG_IS24HOUR, + DateFormat.is24HourFormat(activityContext)); + } + + return new DismissableTimePickerDialog( + activityContext, + onTimeSetListener, + hour, + minute, + is24hour); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + if (mOnDismissListener != null) { + mOnDismissListener.onDismiss(dialog); + } + } + + public void setOnDismissListener(@Nullable OnDismissListener onDismissListener) { + mOnDismissListener = onDismissListener; + } + + public void setOnTimeSetListener(@Nullable OnTimeSetListener onTimeSetListener) { + mOnTimeSetListener = onTimeSetListener; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogModule.java new file mode 100644 index 00000000000000..7d627b5833a548 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogModule.java @@ -0,0 +1,153 @@ +/** + * 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.timepicker; + +import javax.annotation.Nullable; + +import java.util.Map; + +import android.app.Activity; +import android.app.DialogFragment; +import android.app.FragmentManager; +import android.app.TimePickerDialog.OnTimeSetListener; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.os.Bundle; +import android.widget.TimePicker; + +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.common.annotations.VisibleForTesting; + +/** + * {@link NativeModule} that allows JS to show a native time picker dialog and get called back when + * the user selects a time. + */ +public class TimePickerDialogModule extends ReactContextBaseJavaModule { + + @VisibleForTesting + public static final String FRAGMENT_TAG = "TimePickerAndroid"; + + private static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY"; + + /* package */ static final String ARG_HOUR = "hour"; + /* package */ static final String ARG_MINUTE = "minute"; + /* package */ static final String ARG_IS24HOUR = "is24Hour"; + /* package */ static final String ACTION_TIME_SET = "timeSetAction"; + /* package */ static final String ACTION_DISMISSED = "dismissedAction"; + + public TimePickerDialogModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public String getName() { + return "TimePickerAndroid"; + } + + private class TimePickerDialogListener implements OnTimeSetListener, OnDismissListener { + + private final Promise mPromise; + private boolean mPromiseResolved = false; + + public TimePickerDialogListener(Promise promise) { + mPromise = promise; + } + + @Override + public void onTimeSet(TimePicker view, int hour, int minute) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + WritableMap result = new WritableNativeMap(); + result.putString("action", ACTION_TIME_SET); + result.putInt("hour", hour); + result.putInt("minute", minute); + mPromise.resolve(result); + mPromiseResolved = true; + } + } + + @Override + public void onDismiss(DialogInterface dialog) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + WritableMap result = new WritableNativeMap(); + result.putString("action", ACTION_DISMISSED); + mPromise.resolve(result); + mPromiseResolved = true; + } + } + } + + @ReactMethod + public void open(@Nullable final ReadableMap options, Promise promise) { + + Activity activity = getCurrentActivity(); + if (activity == null) { + promise.reject( + ERROR_NO_ACTIVITY, + "Tried to open a TimePicker dialog while not attached to an Activity"); + return; + } + // We want to support both android.app.Activity and the pre-Honeycomb FragmentActivity + // (for apps that use it for legacy reasons). This unfortunately leads to some code duplication. + if (activity instanceof android.support.v4.app.FragmentActivity) { + android.support.v4.app.FragmentManager fragmentManager = + ((android.support.v4.app.FragmentActivity) activity).getSupportFragmentManager(); + android.support.v4.app.DialogFragment oldFragment = + (android.support.v4.app.DialogFragment)fragmentManager.findFragmentByTag(FRAGMENT_TAG); + if (oldFragment != null) { + oldFragment.dismiss(); + } + SupportTimePickerDialogFragment fragment = new SupportTimePickerDialogFragment(); + if (options != null) { + Bundle args = createFragmentArguments(options); + fragment.setArguments(args); + } + TimePickerDialogListener listener = new TimePickerDialogListener(promise); + fragment.setOnDismissListener(listener); + fragment.setOnTimeSetListener(listener); + fragment.show(fragmentManager, FRAGMENT_TAG); + } else { + FragmentManager fragmentManager = activity.getFragmentManager(); + DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG); + if (oldFragment != null) { + oldFragment.dismiss(); + } + TimePickerDialogFragment fragment = new TimePickerDialogFragment(); + if (options != null) { + final Bundle args = createFragmentArguments(options); + fragment.setArguments(args); + } + TimePickerDialogListener listener = new TimePickerDialogListener(promise); + fragment.setOnDismissListener(listener); + fragment.setOnTimeSetListener(listener); + fragment.show(fragmentManager, FRAGMENT_TAG); + } + } + + private Bundle createFragmentArguments(ReadableMap options) { + final Bundle args = new Bundle(); + if (options.hasKey(ARG_HOUR) && !options.isNull(ARG_HOUR)) { + args.putInt(ARG_HOUR, options.getInt(ARG_HOUR)); + } + if (options.hasKey(ARG_MINUTE) && !options.isNull(ARG_MINUTE)) { + args.putInt(ARG_MINUTE, options.getInt(ARG_MINUTE)); + } + if (options.hasKey(ARG_IS24HOUR) && !options.isNull(ARG_IS24HOUR)) { + args.putBoolean(ARG_IS24HOUR, options.getBoolean(ARG_IS24HOUR)); + } + return args; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK index 193749ddf23a4a..8af3f1421e67d6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK @@ -28,6 +28,7 @@ android_library( 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'), + react_native_target('java/com/facebook/react/modules/datepicker:datepicker'), react_native_target('java/com/facebook/react/modules/debug:debug'), react_native_target('java/com/facebook/react/modules/dialog:dialog'), react_native_target('java/com/facebook/react/modules/fresco:fresco'), @@ -36,6 +37,7 @@ android_library( react_native_target('java/com/facebook/react/modules/netinfo:netinfo'), react_native_target('java/com/facebook/react/modules/network:network'), react_native_target('java/com/facebook/react/modules/storage:storage'), + react_native_target('java/com/facebook/react/modules/timepicker:timepicker'), react_native_target('java/com/facebook/react/modules/toast:toast'), react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/modules/websocket:websocket'), 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 fa3e97e10b5e18..9933b41d517ca7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -17,16 +17,21 @@ import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.modules.appstate.AppStateModule; import com.facebook.react.modules.camera.CameraRollManager; +import com.facebook.react.modules.camera.ImageEditingManager; +import com.facebook.react.modules.camera.ImageStoreManager; +import com.facebook.react.modules.clipboard.ClipboardModule; import com.facebook.react.modules.dialog.DialogModule; +import com.facebook.react.modules.datepicker.DatePickerDialogModule; import com.facebook.react.modules.fresco.FrescoModule; import com.facebook.react.modules.intent.IntentModule; import com.facebook.react.modules.location.LocationModule; import com.facebook.react.modules.netinfo.NetInfoModule; import com.facebook.react.modules.network.NetworkingModule; import com.facebook.react.modules.storage.AsyncStorageModule; +import com.facebook.react.modules.timepicker.TimePickerDialogModule; import com.facebook.react.modules.toast.ToastModule; -import com.facebook.react.modules.appstate.AppStateModule; import com.facebook.react.modules.websocket.WebSocketModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.art.ARTRenderableViewManager; @@ -50,7 +55,6 @@ import com.facebook.react.views.viewpager.ReactViewPagerManager; import com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager; import com.facebook.react.views.webview.ReactWebViewManager; -import com.facebook.react.modules.clipboard.ClipboardModule; /** * Package defining basic modules and view managers. @@ -64,12 +68,16 @@ public List
+ |
+ + + Edit on GitHub + + | +
Powered by appetize.io
+Powered by appetize.io
-