@Before
  public void setUp() {
    PowerMockito.mockStatic(Arguments.class);
    PowerMockito.when(Arguments.createArray())
        .thenAnswer(
            new Answer<Object>() {
              @Override
              public Object answer(InvocationOnMock invocation) throws Throwable {
                return new SimpleArray();
              }
            });
    PowerMockito.when(Arguments.createMap())
        .thenAnswer(
            new Answer<Object>() {
              @Override
              public Object answer(InvocationOnMock invocation) throws Throwable {
                return new SimpleMap();
              }
            });

    mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance();
    mReactContext = new ReactApplicationContext(RuntimeEnvironment.application);
    mReactContext.initializeWithInstance(mCatalystInstanceMock);
    DisplayMetrics displayMetrics = mReactContext.getResources().getDisplayMetrics();
    DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics);

    UIManagerModule uiManagerModuleMock = mock(UIManagerModule.class);
    when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class))
        .thenReturn(uiManagerModuleMock);
  }
  @Override
  public void notificationOpened(String s, JSONObject jsonObject, boolean b) {
    Bundle bundle = new Bundle();
    bundle.putString("message", s);
    bundle.putString("additionalData", jsonObject.toString());
    bundle.putBoolean("isActive", b);

    final Intent intent = new Intent(RNOneSignal.NOTIFICATION_OPENED_INTENT_FILTER);
    intent.putExtras(bundle);

    if (mReactContext.hasActiveCatalystInstance()) {
      mReactContext.sendBroadcast(intent);
      return;
    }

    mReactContext.addLifecycleEventListener(
        new LifecycleEventListener() {
          @Override
          public void onHostResume() {
            mReactContext.sendBroadcast(intent);
            mReactContext.removeLifecycleEventListener(this);
          }

          @Override
          public void onHostPause() {}

          @Override
          public void onHostDestroy() {}
        });
  }
 /**
  * Detach given {@param rootView} from current catalyst instance. It's safe to call this method
  * multiple times on the same {@param rootView} - in that case view will be detached with the
  * first call.
  */
 @Override
 public void detachRootView(ReactRootView rootView) {
   UiThreadUtil.assertOnUiThread();
   if (mAttachedRootViews.remove(rootView)) {
     if (mCurrentReactContext != null && mCurrentReactContext.hasActiveCatalystInstance()) {
       detachViewFromInstance(rootView, mCurrentReactContext.getCatalystInstance());
     }
   }
 }
 private int getResourceDrawableId(String name) {
   try {
     return reactContext
         .getResources()
         .getIdentifier(
             name.toLowerCase().replace("-", "_"), "drawable", reactContext.getPackageName());
   } catch (Exception e) {
     Log.e(REACT_CLASS, "Failure to get drawable id.", e);
     return 0;
   }
 }
 private void moveToBeforeResumeLifecycleState() {
   if (mCurrentReactContext != null) {
     if (mLifecycleState == LifecycleState.BEFORE_CREATE) {
       mCurrentReactContext.onHostResume(mCurrentActivity);
       mCurrentReactContext.onHostPause();
     } else if (mLifecycleState == LifecycleState.RESUMED) {
       mCurrentReactContext.onHostPause();
     }
   }
   mLifecycleState = LifecycleState.BEFORE_RESUME;
 }
 private void moveToBeforeCreateLifecycleState() {
   if (mCurrentReactContext != null) {
     if (mLifecycleState == LifecycleState.RESUMED) {
       mCurrentReactContext.onHostPause();
       mLifecycleState = LifecycleState.BEFORE_RESUME;
     }
     if (mLifecycleState == LifecycleState.BEFORE_RESUME) {
       mCurrentReactContext.onHostDestroy();
     }
   }
   mLifecycleState = LifecycleState.BEFORE_CREATE;
 }
 private void tearDownReactContext(ReactContext reactContext) {
   UiThreadUtil.assertOnUiThread();
   if (mLifecycleState == LifecycleState.RESUMED) {
     reactContext.onPause();
   }
   for (ReactRootView rootView : mAttachedRootViews) {
     detachViewFromInstance(rootView, reactContext.getCatalystInstance());
   }
   reactContext.onDestroy();
   mDevSupportManager.onReactInstanceDestroyed(reactContext);
   mMemoryPressureRouter.onReactInstanceDestroyed();
 }
  @Override
  public void destroy() {
    UiThreadUtil.assertOnUiThread();

    if (mUseDeveloperSupport) {
      mDevSupportManager.setDevSupportEnabled(false);
    }

    moveToBeforeCreateLifecycleState();

    if (mReactContextInitAsyncTask != null) {
      mReactContextInitAsyncTask.cancel(true);
    }

    mMemoryPressureRouter.destroy(mApplicationContext);

    if (mCurrentReactContext != null) {
      mCurrentReactContext.destroy();
      mCurrentReactContext = null;
      mHasStartedCreatingInitialContext = false;
    }
    mCurrentActivity = null;

    ResourceDrawableIdHelper.getInstance().clear();
  }
  private void registerNotificationsRegistration() {
    IntentFilter intentFilter = new IntentFilter("RNPushNotificationRegisteredToken");

    mReactContext.registerReceiver(
        new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            String token = intent.getStringExtra("token");
            WritableMap params = Arguments.createMap();
            params.putString("deviceToken", token);

            sendEvent("remoteNotificationsRegistered", params);
            // We need to start a timer for the broadcaster.
            new Timer()
                .scheduleAtFixedRate(
                    new TimerTask() {
                      @Override
                      public void run() {
                        mReactContext.sendBroadcast(
                            new Intent("com.google.android.intent.action.GTALK_HEARTBEAT"));
                        mReactContext.sendBroadcast(
                            new Intent("com.google.android.intent.action.MCS_HEARTBEAT"));
                      }
                    },
                    0,
                    2 * 60 * 1000); // We ping GCM every 2 minutes.
          }
        },
        intentFilter);
  }
 private void toggleElementInspector() {
   if (mCurrentReactContext != null) {
     mCurrentReactContext
         .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
         .emit("toggleElementInspector", null);
   }
 }
  @ReactMethod
  public void requestPermissions(String senderID) {
    Intent GCMService = new Intent(mReactContext, RNPushNotificationRegistrationService.class);

    GCMService.putExtra("senderID", senderID);
    mReactContext.startService(GCMService);
  }
  private void sendMapError(String message, String type) {
    WritableMap error = Arguments.createMap();
    error.putString("message", message);
    error.putString("type", type);

    reactContext
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit("mapError", error);
  }
 private void moveToResumedLifecycleState(boolean force) {
   if (mCurrentReactContext != null) {
     // we currently don't have an onCreate callback so we call onResume for both transitions
     if (force
         || mLifecycleState == LifecycleState.BEFORE_RESUME
         || mLifecycleState == LifecycleState.BEFORE_CREATE) {
       mCurrentReactContext.onHostResume(mCurrentActivity);
     }
   }
   mLifecycleState = LifecycleState.RESUMED;
 }
  /**
   * Attach given {@param rootView} to a catalyst instance manager and start JS application using JS
   * module provided by {@link ReactRootView#getJSModuleName}. If the react context is currently
   * being (re)-created, or if react context has not been created yet, the JS application associated
   * with the provided root view will be started asynchronously, i.e this method won't block. This
   * view will then be tracked by this manager and in case of catalyst instance restart it will be
   * re-attached.
   */
  @Override
  public void attachMeasuredRootView(ReactRootView rootView) {
    UiThreadUtil.assertOnUiThread();
    mAttachedRootViews.add(rootView);

    // If react context is being created in the background, JS application will be started
    // automatically when creation completes, as root view is part of the attached root view list.
    if (mReactContextInitAsyncTask == null && mCurrentReactContext != null) {
      attachMeasuredRootViewToInstance(rootView, mCurrentReactContext.getCatalystInstance());
    }
  }
  private void registerNotificationsReceiveNotification() {
    IntentFilter intentFilter = new IntentFilter("RNPushNotificationReceiveNotification");

    mReactContext.registerReceiver(
        new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            notifyNotification(intent.getBundleExtra("notification"));
          }
        },
        intentFilter);
  }
  private MarkerOptions createMarker(ReadableMap markerJson) {
    MarkerOptions options = new MarkerOptions();
    options.position(
        new LatLng(
            markerJson.getMap("coordinates").getDouble("lat"),
            markerJson.getMap("coordinates").getDouble("lng")));

    if (markerJson.hasKey("title")) {
      options.title(markerJson.getString("title"));
    }
    if (markerJson.hasKey("color")) {
      options.icon(BitmapDescriptorFactory.defaultMarker((float) markerJson.getDouble("color")));
    }
    if (markerJson.hasKey("snippet")) {
      options.snippet(markerJson.getString("snippet"));
    }
    if (markerJson.hasKey("icon")) {
      String varName = "";
      ReadableType iconType = markerJson.getType("icon");
      if (iconType.compareTo(ReadableType.Map) >= 0) {
        ReadableMap icon = markerJson.getMap("icon");
        try {
          int resId = getResourceDrawableId(icon.getString("uri"));
          Bitmap image = BitmapFactory.decodeResource(reactContext.getResources(), resId);

          options.icon(
              BitmapDescriptorFactory.fromBitmap(
                  Bitmap.createScaledBitmap(
                      image, icon.getInt("width"), icon.getInt("height"), true)));
        } catch (Exception e) {
          varName = icon.getString("uri");
        }
      } else if (iconType.compareTo(ReadableType.String) >= 0) {
        varName = markerJson.getString("icon");
      }
      if (!varName.equals("")) {
        // Changing marker icon to use resource
        int resourceValue = getResourceDrawableId(varName);
        Log.i(REACT_CLASS, varName + markerJson.toString());
        options.icon(BitmapDescriptorFactory.fromResource(resourceValue));
      }
    }
    if (markerJson.hasKey("anchor")) {
      ReadableArray anchor = markerJson.getArray("anchor");
      options.anchor((float) anchor.getDouble(0), (float) anchor.getDouble(1));
    }
    return options;
  }
  /**
   * Use this method when the activity resumes to enable invoking the back button directly from JS.
   *
   * <p>This method retains an instance to provided mDefaultBackButtonImpl. Thus it's important to
   * pass from the activity instance that owns this particular instance of {@link
   * ReactInstanceManagerImpl}, so that once this instance receive {@link #onDestroy} event it will
   * clear the reference to that defaultBackButtonImpl.
   *
   * @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
   *     this instance of {@link ReactInstanceManagerImpl}.
   */
  @Override
  public void onResume(Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
    UiThreadUtil.assertOnUiThread();

    mLifecycleState = LifecycleState.RESUMED;

    mDefaultBackButtonImpl = defaultBackButtonImpl;
    if (mUseDeveloperSupport) {
      mDevSupportManager.setDevSupportEnabled(true);
    }

    mCurrentActivity = activity;
    if (mCurrentReactContext != null) {
      mCurrentReactContext.onResume(activity);
    }
  }
  @Override
  public void onPause() {
    UiThreadUtil.assertOnUiThread();

    mLifecycleState = LifecycleState.BEFORE_RESUME;

    mDefaultBackButtonImpl = null;
    if (mUseDeveloperSupport) {
      mDevSupportManager.setDevSupportEnabled(false);
    }

    mCurrentActivity = null;
    if (mCurrentReactContext != null) {
      mCurrentReactContext.onPause();
    }
  }
  @Override
  public void onNewIntent(Intent intent) {
    if (mCurrentReactContext == null) {
      FLog.w(ReactConstants.TAG, "Instance detached from instance manager");
    } else {
      String action = intent.getAction();
      Uri uri = intent.getData();

      if (Intent.ACTION_VIEW.equals(action) && uri != null) {
        DeviceEventManagerModule deviceEventManagerModule =
            Assertions.assertNotNull(mCurrentReactContext)
                .getNativeModule(DeviceEventManagerModule.class);
        deviceEventManagerModule.emitNewIntentReceived(uri);
      }

      mCurrentReactContext.onNewIntent(mCurrentActivity, intent);
    }
  }
  @Override
  public void onDestroy() {
    UiThreadUtil.assertOnUiThread();

    if (mReactContextInitAsyncTask != null) {
      mReactContextInitAsyncTask.cancel(true);
    }

    mMemoryPressureRouter.destroy(mApplicationContext);
    if (mUseDeveloperSupport) {
      mDevSupportManager.setDevSupportEnabled(false);
    }

    if (mCurrentReactContext != null) {
      mCurrentReactContext.onDestroy();
      mCurrentReactContext = null;
      mHasStartedCreatingInitialContext = false;
    }
    mCurrentActivity = null;
  }
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (mCurrentReactContext != null) {
     mCurrentReactContext.onActivityResult(requestCode, resultCode, data);
   }
 }
 private void sendEvent(String eventName, Object params) {
   mReactContext
       .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
       .emit(eventName, params);
 }
 public void onReceiveNativeEvent(String value) {
   WritableMap event = Arguments.createMap();
   event.putString("message", value);
   ReactContext reactContext = (ReactContext) getContext();
   reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(getId(), "topChange", event);
 }
 private void sendEvent(String eventName, @Nullable WritableMap params) {
   reactContext.getJSModule(RCTNativeAppEventEmitter.class).emit(eventName, params);
 }