@Override protected void addEventEmitters( final ThemedReactContext reactContext, final RCTSwipeRefreshLayout view) { view.setOnEvTouchListener( new RCTSwipeRefreshLayout.OnEvTouchListener() { @Override public void onSwipe(int movement) { reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new TouchEvent(view.getId(), SystemClock.nanoTime(), movement)); } @Override public void onSwipeRefresh() { reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new TouchUpEvent(view.getId(), SystemClock.nanoTime())); } }); }
/** * Get the current position. This can return almost immediately if the location is cached or * request an update, which might take a while. * * @param options map containing optional arguments: timeout (millis), maximumAge (millis) and * highAccuracy (boolean) */ @ReactMethod public void getCurrentPosition( ReadableMap options, final Callback success, Callback error) { LocationOptions locationOptions = LocationOptions.fromReactMap(options); try { LocationManager locationManager = (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE); String provider = getValidProvider(locationManager, locationOptions.highAccuracy); if (provider == null) { error.invoke(PositionError.buildError( PositionError.PERMISSION_DENIED, "No location provider available.")); return; } Location location = locationManager.getLastKnownLocation(provider); if (location != null && SystemClock.currentTimeMillis() - location.getTime() < locationOptions.maximumAge) { success.invoke(locationToMap(location)); return; } new SingleUpdateRequest(locationManager, provider, locationOptions.timeout, success, error) .invoke(); } catch (SecurityException e) { throwLocationPermissionMissing(e); } }
@Override public void onSelectionChanged(int start, int end) { // Android will call us back for both the SELECTION_START span and SELECTION_END span in text // To prevent double calling back into js we cache the result of the previous call and only // forward it on if we have new values if (mPreviousSelectionStart != start || mPreviousSelectionEnd != end) { mEventDispatcher.dispatchEvent( new ReactTextInputSelectionEvent( mReactEditText.getId(), SystemClock.nanoTime(), start, end ) ); mPreviousSelectionStart = start; mPreviousSelectionEnd = end; } }
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); ((ReactContext) getContext()).getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(ScrollEvent.obtain( getId(), SystemClock.nanoTime(), ScrollEventType.SCROLL, 0, /* offsetX = 0, horizontal scrolling only */ calculateAbsoluteOffset(), getWidth(), ((ReactListAdapter) getAdapter()).getTotalChildrenHeight(), getWidth(), getHeight())); }
@Override public void onReceivedError( WebView webView, int errorCode, String description, String failingUrl) { super.onReceivedError(webView, errorCode, description, failingUrl); mLastLoadFailed = true; // In case of an error JS side expect to get a finish event first, and then get an error event // Android WebView does it in the opposite way, so we need to simulate that behavior emitFinishEvent(webView, failingUrl); WritableMap eventData = createWebViewEvent(webView, failingUrl); eventData.putDouble("code", errorCode); eventData.putString("description", description); dispatchEvent( webView, new TopLoadingErrorEvent(webView.getId(), SystemClock.nanoTime(), eventData)); }
@Override public void onPageScrollStateChanged(int state) { String pageScrollState; switch (state) { case SCROLL_STATE_IDLE: pageScrollState = "idle"; break; case SCROLL_STATE_DRAGGING: pageScrollState = "dragging"; break; case SCROLL_STATE_SETTLING: pageScrollState = "settling"; break; default: throw new IllegalStateException("Unsupported pageScrollState"); } mEventDispatcher.dispatchEvent( new PageScrollStateChangedEvent(getId(), SystemClock.nanoTime(), pageScrollState)); }
@Override protected void addEventEmitters(final ThemedReactContext reactContext, final ReactToolbar view) { final EventDispatcher mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); view.setNavigationOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mEventDispatcher.dispatchEvent( new ToolbarClickEvent(view.getId(), SystemClock.nanoTime(), -1)); } }); view.setOnMenuItemClickListener( new ReactToolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { mEventDispatcher.dispatchEvent( new ToolbarClickEvent( view.getId(), SystemClock.nanoTime(), menuItem.getOrder())); return true; } }); }
private static void emitScrollEvent(ViewGroup scrollView, ScrollEventType scrollEventType) { View contentView = scrollView.getChildAt(0); if (contentView == null) { return; } ReactContext reactContext = (ReactContext) scrollView.getContext(); reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent( ScrollEvent.obtain( scrollView.getId(), SystemClock.nanoTime(), scrollEventType, scrollView.getScrollX(), scrollView.getScrollY(), contentView.getWidth(), contentView.getHeight(), scrollView.getWidth(), scrollView.getHeight())); }
private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher eventDispatcher) { // This means the gesture has already ended, via some other CANCEL or UP event. This is not // expected to happen very often as it would mean some child View has decided to intercept the // touch stream and start a native gesture only upon receiving the UP/CANCEL event. if (mTargetTag == -1) { FLog.w( ReactConstants.TAG, "Can't cancel already finished gesture. Is a child View trying to start a gesture from " + "an UP/CANCEL event?"); return; } Assertions.assertCondition( !mChildIsHandlingNativeGesture, "Expected to not have already sent a cancel for this gesture"); Assertions.assertNotNull(eventDispatcher).dispatchEvent( TouchEvent.obtain( mTargetTag, SystemClock.nanoTime(), TouchEventType.CANCEL, androidEvent, mTargetCoordinates[0], mTargetCoordinates[1])); }
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnScrollDispatchHelper.onScrollChanged(l, t)) { getReactContext().getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(ScrollEvent.obtain( getId(), ScrollEventType.SCROLL, 0, /* offsetX = 0, horizontal scrolling only */ computeVerticalScrollOffset(), mOnScrollDispatchHelper.getXFlingVelocity(), mOnScrollDispatchHelper.getYFlingVelocity(), getWidth(), computeVerticalScrollRange(), getWidth(), getHeight())); } final int firstIndex = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition(); final int lastIndex = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition(); if (firstIndex != mFirstVisibleIndex || lastIndex != mLastVisibleIndex) { getReactContext().getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new VisibleItemsChangeEvent( getId(), SystemClock.nanoTime(), firstIndex, lastIndex)); mFirstVisibleIndex = firstIndex; mLastVisibleIndex = lastIndex; } }
@Override protected void addEventEmitters( final ThemedReactContext reactContext, final RCTLazyLoadView view) { view.setOnEvChangeListener( new OnEvChangeListener() { @Override public void onWindowVisibilityChange( boolean hiddenState) { reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new WindowVisibilityChangeEvent(view.getId(), SystemClock.nanoTime(), hiddenState)); } }); }
@Override public void run() { if (mCancelled) { return; } long frameTimeMillis = mFrameStartTime / 1000000; long timeSinceBoot = SystemClock.uptimeMillis(); long frameTimeElapsed = timeSinceBoot - frameTimeMillis; long time = SystemClock.currentTimeMillis(); long absoluteFrameStartTime = time - frameTimeElapsed; if (FRAME_DURATION_MS - (float) frameTimeElapsed < IDLE_CALLBACK_FRAME_DEADLINE_MS) { return; } mIdleCallbackContextsToCall.clear(); synchronized (mIdleCallbackGuard) { mIdleCallbackContextsToCall.addAll(mSendIdleEventsExecutorTokens); } for (ExecutorToken context : mIdleCallbackContextsToCall) { getReactApplicationContext().getJSModule(context, JSTimersExecution.class) .callIdleCallbacks(absoluteFrameStartTime); } mCurrentIdleCallbackRunnable = null; }
private void stepChoreographerFrame() { ChoreographerCompat.FrameCallback callback = mPostFrameCallbackHandler.getAndResetFrameCallback(); ChoreographerCompat.FrameCallback idleCallback = mIdlePostFrameCallbackHandler.getAndResetFrameCallback(); mCurrentTimeNs += FRAME_TIME_NS; when(SystemClock.uptimeMillis()).thenReturn(mCurrentTimeNs / 1000000); if (callback != null) { callback.doFrame(mCurrentTimeNs); } if (idleCallback != null) { idleCallback.doFrame(mCurrentTimeNs); } }
@Test public void testIdleCallback() { mTiming.onHostResume(); mTiming.setSendIdleEvents(mExecutorTokenMock, true); stepChoreographerFrame(); verify(mJSTimersMock).callIdleCallbacks(SystemClock.currentTimeMillis()); }
/** * Get the current position. This can return almost immediately if the location is cached or * request an update, which might take a while. * * @param options map containing optional arguments: timeout (millis), maximumAge (millis) and * highAccuracy (boolean) */ @ReactMethod public void getCurrentPosition( ReadableMap options, final Callback success, Callback error) { LocationOptions locationOptions = LocationOptions.fromReactMap(options); try { LocationManager locationManager = (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE); String provider = getValidProvider(locationManager, locationOptions.highAccuracy); if (provider == null) { emitError(PositionError.PERMISSION_DENIED, "No location provider available."); return; } Location location = locationManager.getLastKnownLocation(provider); if (location != null && SystemClock.currentTimeMillis() - location.getTime() < locationOptions.maximumAge) { success.invoke(locationToMap(location)); return; } new SingleUpdateRequest(locationManager, provider, locationOptions.timeout, success, error) .invoke(); } catch (SecurityException e) { throwLocationPermissionMissing(e); } }
@Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { ReactContext reactContext = (ReactContext) buttonView.getContext(); reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent( new ReactSwitchEvent( buttonView.getId(), SystemClock.nanoTime(), isChecked)); }
private void onTotalChildrenHeightChange(int newTotalChildrenHeight) { if (mSendContentSizeChangeEvents) { ((ReactContext) getContext()).getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new ContentSizeChangeEvent( getId(), SystemClock.nanoTime(), getWidth(), newTotalChildrenHeight)); } }
@Override protected void addEventEmitters( final ThemedReactContext reactContext, final ReactSwipeRefreshLayout view) { view.setOnRefreshListener( new OnRefreshListener() { @Override public void onRefresh() { reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher() .dispatchEvent(new RefreshEvent(view.getId(), SystemClock.nanoTime())); } }); }
@Override public void onPageStarted(WebView webView, String url, Bitmap favicon) { super.onPageStarted(webView, url, favicon); mLastLoadFailed = false; dispatchEvent( webView, new TopLoadingStartEvent( webView.getId(), SystemClock.nanoTime(), createWebViewEvent(webView, url))); }
@Override public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { super.doUpdateVisitedHistory(webView, url, isReload); dispatchEvent( webView, new TopLoadingStartEvent( webView.getId(), SystemClock.nanoTime(), createWebViewEvent(webView, url))); }
private void emitFinishEvent(WebView webView, String url) { dispatchEvent( webView, new TopLoadingFinishEvent( webView.getId(), SystemClock.nanoTime(), createWebViewEvent(webView, url))); }
@Override public void onPageSelected(int position) { if (!mIsCurrentItemFromJs) { mEventDispatcher.dispatchEvent( new PageSelectedEvent(getId(), SystemClock.nanoTime(), position)); } }
/** * Get the current position. This can return almost immediately if the location is cached or * request an update, which might take a while. * * @param options map containing optional arguments: timeout (millis), maximumAge (millis) and * highAccuracy (boolean) */ @ReactMethod public void getCurrentPosition( ReadableMap options, final Callback success, Callback error) { LocationOptions locationOptions = LocationOptions.fromReactMap(options); try { LocationManager locationManager = (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE); String provider = getValidProvider(locationManager, locationOptions.highAccuracy); if (provider == null) { error.invoke("No available location provider."); return; } Location location = locationManager.getLastKnownLocation(provider); if (location != null && SystemClock.currentTimeMillis() - location.getTime() < locationOptions.maximumAge) { success.invoke(locationToMap(location)); return; } new SingleUpdateRequest(locationManager, provider, locationOptions.timeout, success, error) .invoke(); } catch (SecurityException e) { throwLocationPermissionMissing(e); } }
@ReactMethod public void createTimer( ExecutorToken executorToken, final int callbackID, final int duration, final double jsSchedulingTime, final boolean repeat) { // Adjust for the amount of time it took for native to receive the timer registration call long adjustedDuration = (long) Math.max( 0, jsSchedulingTime - SystemClock.currentTimeMillis() + duration); if (duration == 0 && !repeat) { WritableArray timerToCall = Arguments.createArray(); timerToCall.pushInt(callbackID); getReactApplicationContext().getJSModule(executorToken, JSTimersExecution.class) .callTimers(timerToCall); return; } long initialTargetTime = SystemClock.nanoTime() / 1000000 + adjustedDuration; Timer timer = new Timer(executorToken, callbackID, initialTargetTime, duration, repeat); synchronized (mTimerGuard) { mTimers.add(timer); SparseArray<Timer> timersForContext = mTimerIdsToTimers.get(executorToken); if (timersForContext == null) { timersForContext = new SparseArray<>(); mTimerIdsToTimers.put(executorToken, timersForContext); } timersForContext.put(callbackID, timer); } }