expo: ExpoKit (Android) Cannot Link Native Modules

We’ve recently detached from Expo to ExpoKit to give us the ability to use native modules and external react-native libraries that are not supported by Expo. For iOS the detachment process has been smooth but on Android I have yet to be able to link a single module. I’ve traced the issue down to the MainApplication.java currently ExpoKit has the MainReactPackage commented out with the comment “Needed for react-native link”. Because this MainReactPackage() is commented out we are getting the following errors when running ‘react-native link’ on Android. java.lang.IllegalStateException: Application instance isn't a react-application.

I’ve since switched my MainApplication.java as follows.


import com.facebook.react.ReactPackage;

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

// Needed for `react-native link`
import com.facebook.react.shell.MainReactPackage;

public class MainApplication extends MultiDexApplication {

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

        // Needed for `react-native link`
         new MainReactPackage()
    );
  }
}

But now get the following error on start up. image

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 20 (9 by maintainers)

Commits related to this issue

Most upvoted comments

@brentvatne - Sorry for leaving this out here for so long. I was able to solve this issue by using the following code. It works by implementing the ReactApplication interface in MainApplication as a normal react-native init project would have it setup. I would love to know if @jesseruder as I wouldn’t consider myself too comfortable with Java code. But this will work for now


import android.support.multidex.MultiDexApplication;


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

import com.wix.reactnativenotifications.RNNotificationsPackage;

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

public class MainApplication extends MultiDexApplication implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
              //new MainReactPackage(),
      );
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            // Add your own packages here!
            // TODO: add cool native modules

            // Needed for `react-native link`
            // new MainReactPackage()
            new RNNotificationsPackage(MainApplication.this)
    );
  }

}

@brentvatne thanks for the reply! After diving deeper into the subject it appears that the package I am trying to implement (https://github.com/wix/react-native-notifications/blob/master/docs/installation.md) expects the application as an argument. Because the main activity does not implement the ReactApplication interface as mentioned by the comments:

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

the error java.lang.IllegalStateException: Application instance isn't a react-application is being thrown. I am going to keep plugging away and see if I can get this to work and I will report back. If anyone has any suggestions let me know!

@chochihim - Sorry for the late reply been out for the holidays. The issue was during a POC to get push notifications to work and we have since moved on w/o implementing the code above. With that said we plan to make push notifications a feature in the coming weeks which will re-open this issue for us. I’ll be sure to keep you updated on my findings.

@chochihim Sure,

public class MainActivity extends ExponentActivity {

  @Override
  public String publishedUrl() {
    return "exp://exp.host/@.../testproject1";
  }

  @Override
  public String developmentUrl() {
    return ExponentBuildConstants.DEVELOPMENT_URL;
  }

  @Override
  public List<String> sdkVersions() {
    return new ArrayList<>(Arrays.asList("23.0.0"));
  }

  @Override
  public List<ReactPackage> reactPackages() {
    return ((MainApplication) getApplication()).getPackages();
  }

  @Override
  public boolean isDebug() {
    return BuildConfig.DEBUG;
  }

  @Override
  public Bundle initialProps(Bundle expBundle) {
    // Add extra initialProps here
    return expBundle;
  }
}
public class MainApplication extends MultiDexApplication {

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

        // Needed for `react-native link`
        // new MainReactPackage(),
            new RNIapPackage()
    );
  }
}

I’ve a similar problem about expokit. After detached 2 different library I tried to link. But NativeModules always empty. Here is my first code;

package host.exp.exponent;


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.wix.reactnativenotifications.RNNotificationsPackage;
import com.reactlibrary.RNIapPackage;
import com.facebook.react.shell.MainReactPackage;

public class MainApplication extends ExpoApplication {

  @Override
  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 RNNotificationsPackage(MainApplication.this),
            new RNIapPackage()
    );
  }

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

  @Override
  public boolean shouldUseInternetKernel() {
    return BuildVariantConstants.USE_INTERNET_KERNEL;
  }
}

Then I tried like this;

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.wix.reactnativenotifications.RNNotificationsPackage;
import com.reactlibrary.RNIapPackage;
import com.facebook.react.shell.MainReactPackage;

public class MainApplication extends ExpoApplication implements ReactApplication {

    @Override
    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 RNNotificationsPackage(MainApplication.this),
                new RNIapPackage()
        );
    }

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

    @Override
    public boolean shouldUseInternetKernel() {
        return BuildVariantConstants.USE_INTERNET_KERNEL;
    }

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

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

Testing in js;

import React, { Component } from 'react';
import {
    StyleSheet, View, Text, Button, NativeModules
} from 'react-native'
import { NavigationActions } from 'react-navigation'

import BaseComponent from '../base/BaseComponent'

console.log('NativeModules', NativeModules.RNIapModule, NativeModules.WixRNNotifications)

That prints NativeModules1418 undefined undefined By the way I created a new project with ‘react-native init’. That works very well. What am I missing? Please help.

My package.json;

{
  "name": "Test1",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-native-scripts": "1.8.1",
    "jest-expo": "24.0.0",
    "react-test-renderer": "16.0.0"
  },
  "main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
  "scripts": {
    "start": "react-native-scripts start",
    "eject": "react-native-scripts eject",
    "android": "react-native-scripts android",
    "ios": "react-native-scripts ios",
    "test": "node node_modules/jest/bin/jest.js --watch"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "expo": "^24.0.0",
    "react": "16.0.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-24.0.0.tar.gz",
    "react-native-easy-toast": "^1.0.9",
    "react-native-iap": "^0.1.10",
    "react-native-notifications": "^1.1.17",
    "react-native-scrollable-tab-view": "^0.8.0",
    "react-native-tab-navigator": "^0.3.4",
    "react-navigation": "^1.0.0-beta.21"
  }
}

Hi there!

I investigated this and suspect that the detach template is out of date in SDK23, sorry for the hassle. I haven’t confirmed this with our Android lead yet, but I was able to get a project running with a third party native module by not including the MainReactPackage() in getPackages(), as follows:

package com.lol.lool;

import android.support.multidex.MultiDexApplication;

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.facebook.react.shell.MainReactPackage;
import com.github.xinthink.rnmk.ReactMaterialKitPackage;

public class MainApplication extends MultiDexApplication {

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

        // Needed for `react-native link`
        // new MainReactPackage(),
        new ReactMaterialKitPackage()
    );
  }
}

@jesseruder can provide more context when he has time. Let me know if this works for you.