Android Device Motion Events

I’m creating an augmented reality app that relies on the DeviceMotion API in DangerZone. This works perfectly in IOS but when attempting to use in Android I receive an “Expected to run on UI thread!” error. I did not see in the docs that DeviceMotion was only meant for IOS, but that appears to be the case?

Is there another way to get these events for Android? (I realize I can calculate pitch and roll from the Accelerometer events, but azimuth is another matter). I’d prefer not to detach to ExpoKit if I can help it. Any help would be appreciated!

Hi @estesjl - DeviceMotion should work on both iOS and Android. Could you provide more details about the error you’re seeing (e.g. stacktrace), and maybe share the code that’s producing it?

Code itself is pretty simple. Your basic call to DeviceMotion, and it works perfectly on IOS. However Android ignores these lines. If I put a console log inside the listener, it is never triggered. I only receive an error when I trigger a back action on unmount. I’m using version 25 of the SDK, everything is updated. My hunch is that it is somehow trying to run tasks in the background when it shouldn’t (such as the similar issue here:, though I don’t know why this would be.

Here’s a picture of the error, and the code is below it. Let me know if there’s anything else that could be helpful.


  componentDidMount() {
    // Lock screen orientation to Portrait to avoid distortion on reorientation
    // Establish listener for device motion events, including orientation
      Expo.DangerZone.DeviceMotion.addListener((data) => {
        yaw = data.rotation.alpha;
        pitch = data.rotation.beta;
        roll = data.rotation.gamma;
        // Actions to be done on any change in screen orientation
        if (this.state.orientation !== data.orientation) {
        this.setState({ rotation: data.rotation, orientation: data.orientation });

Hey @estesjl - thanks for the code. I’ve reproduced the issue you described about not seeing the listener triggered, and also your crash by calling DeviceMotion.removeAllListeners(). @sjchmiela - can you help?

Update: I ended up resolving this by using the Expo code in inside my own React Native module. I edited to look like the following:

package host.exp.exponent;

import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;

import java.util.Arrays;
import java.util.List;

// Needed for `react-native link`
 import com.facebook.react.ReactApplication;
import com.sensormanager.SensorManagerPackage;

public class MainApplication extends ExpoApplication implements ReactApplication {

  public boolean isDebug() {
    return BuildConfig.DEBUG;

  // Needed for `react-native link`
  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            // Add your own packages here!
            // TODO: add native modules!

            // Needed for `react-native link`
//            new MainReactPackage(),
            new SensorManagerPackage(),

  public String gcmSenderId() {
    return getString(R.string.gcm_defaultSenderId);

  public boolean shouldUseInternetKernel() {
    return BuildVariantConstants.USE_INTERNET_KERNEL;

  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;

    protected List<ReactPackage> getPackages() {
      return MainApplication.this.getPackages();

On top of this, I had to revert back to gradle version 2.2.3 from 3.0.1. I did this so I could run a buildToolsversion at 23.0.1, which is the most recent version that appears to work with module linking in my code.

created an issue to track this

I have the same issue.
Worked around it by setting the update interval really high instead of removing the listener.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.