Adding React Native to an existing Android App

After my recent adventures with ReactJS, I have been thinking of playing around a bit with React Native. I have looked at it before and even gave a talk on a previous version of it at a previous AndroidPhilly event.  Instead of trying a new React Native app, I figured it might be a good idea to maybe try it on an Android app I am already developing (more on that later). Instagram recently wrote an interesting article on adding React Native to their existing app so I was glad there was a migration path for native apps that didn’t involve starting a React Native app from scratch.

Let go

laptop

The React Native site has a fairly good walkthrough on adding RN to a native app. I did as instructed (I think) and mostly things went ok. And then, the expected issues began.

So long Jack

Hitting compile on AndroidStudio seemed to work for a bit and then it would just hang. Not getting anything useful there, I tried to compile the app from the command line using

./gradlew installDebug

What I saw was that the process would get stuck at a compile with Jack process. Jack was a new toolchain Google was building for Android development and I was the way to use some Java 8 features on current devices. However this month Google announced they were moving away from Jack and fortunately, my app barely used it. So I decided to remove Jack from the app altogether. That worked and AndroidStudio compiled and packaged the app and I got my app running on the emulator! It looked like…

js

Wherefore art the JS Bundle

This seemed to be an simple network issue with the emulator not seeing the locally running server. Having dealt with this while trying to get the emulator to see a locally running rails api, I figured it was something simple. React Native comes with a build it settings activity that you can call by rage-shaking the device or executing

adb shell input keyevent 82

which brings up the options menu that you can then use to launch the Settings Activity.

Wrong Settings

…except that doing that launched my apps preferences screen. Turns out React Native was just looking for a file named preferences.xml file and launching that. It just happens my app’s preferences screen was also defined by the xml file with the same name and so there was a conflict. Changing my apps preference.xml file name got around that.

Crash

I changed the ip address on React Native’s debug screen and went back to the main activity only to have the app crash. Looking at Logcat, I got this weird error

Caused by: java.lang.IllegalAccessError: 
Method 'void android.support.v4.net.ConnectivityManagerCompat.()' 
is inaccessible to class 'com.facebook.react.modules.netinfo.NetInfoModule' 
(declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' 
appears in /data/app/*****.debug-2/base.apk)
     at com.facebook.react.modules.netinfo.NetInfoModule.(NetInfoModule.java:55)
     at com.facebook.react.shell.MainReactPackage.createNativeModules(MainReactPackage.java:67)
     at com.facebook.react.ReactInstanceManagerImpl.processPackage(ReactInstanceManagerImpl.java:793)
     at com.facebook.react.ReactInstanceManagerImpl.createReactContext(ReactInstanceManagerImpl.java:730)
     at com.facebook.react.ReactInstanceManagerImpl.access$600(ReactInstanceManagerImpl.java:91)
     at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:184)

Oh weird. Going by this thread, it looked like an API change in Play Services recently was causing an issue. But hold on, according to the conversation, the issue was fixed in RN v22. What the heck was I using?

Listing dependencies with gradlew

I didn’t know this but you can actually list your exact dependency tree by calling

./gradlew app:dependencies

which gives you a nice dependency tree that looks like

Screen Shot 2017-03-29 at 1.05.06 AM

Since the dependency stated in my build.gradle was just

compile "com.facebook.react:react-native:+"

it could be satisfied by any instance of RN gradle found on Maven Central. Except that one of the steps in setting up the project included defining the local folder in node_modules that held the latest (0.43 at the time of writing) and the only version on Maven Central was old (0.20). Turns out (after about an hour of pulling my hair out) that there was an error in the file path I had used to identify the node_module location and setting it right fixed the final issue.

Viola!

4 hours of dev or so and my app finally launched its hello world React Native screen alongside the native activities. Not too bad, I was expecting worse, given all the new tools in play. Lets hope this is worth it.


Tip:

Btw, unlike developing React for the web (using CreateReactApp), the console that you use to launch the dev server does not show the log messages. To see your app logs, use

reactnative logandroid

 

Author: Arpit Mathur

Arpit Mathur is a Principal Software Engineer at Comcast Labs where he is currently working on Virtual and Augmented Reality as well as investigating Blockchains and the decentralized internet.

2 thoughts on “Adding React Native to an existing Android App”

  1. Hi, I’m trying to have a React Native view in my Android app as well. Following the official documentation hasn’t got it working for me. Will you do a post on how to integrate RN into Android? That will be super helpful since I haven’t seen anything like that online.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s