How-To Build React-Native On Android Without Issue
Building apps for mobile can sometimes be problematic. When using the awesome react-native setup, it’s can be a lot easier, but Android can give you a whole slew of different problems where it’s not always clear what that issue is. Looking through Google there will be a lot of similar questions, but not always the right answer for your issue.
Instead of having to go through a lot of other sites like I did, I’ve compiled all of that information into this article, while also explaining the information given, and why you need it. We’re going to cover the process, errors, issues, and how to build Android apps without any trouble. Once you have finished this article, any other errors should make sense to you no matter how vague.
Building for Android
This is where things can start to get a bit complicated if you are completely new to the platform. It’s not too bad when everything is laid out, and you are aware of what can come up. If you have not taken the time already, going though Facebook’s guide to setting up for Android is a great idea. Once you have all of those boxes checked, you will have the basic platform you need to create react-native apps.
Before we start, I would like to go over a very crude explanation of the react-native process when using the ‘run-android’ command. It first starts the react packager (server), and then starts compiling the app using Gradle. When react-native is done compiling the app, it then uploads it to the available android device using the Android Debug Bridge. It’s during this process chain that the issues arise.
So with that said, let’s look at what is going on, what can happen, and what to do to prevent bad things from happening.
Commands to Know
Before we get started, I wanted to lay out a very helpful list of commands needed for Android development with react-native.
android avd # Start AVD Manager android sdk # Start SDK Manager adb devices # Check available devices adb install <package> # Install package to device adb start-server # start adb server adb kill-server # stop adb servere adb reverse tcp:8081 tcp:8081 # reverse server traffic to send to emulator (Android OS 5.0+) adb shell input keyevent 82 # send "shake" to device for dev options emulator -avd <avd name> # Start avd emulator with name <avd name> emulator -list-avds # list available avds
This list makes up of every single common command you’ll use when building for Android.
When everything works perfectly, you can start an emulator, type ‘react-native run android‘ in your project folder, and everything will work. Unfortunately, this isn’t always the case. To understand what is happening, let’s check to make sure everything is working like it should.
Watchman Homebrew not npm
For OSX, you will want to make sure to use the homebrew version of Watchman. Installing from the Node Package Manager will cause errors. I personally found this out the hard way. If you do not, you will see errors from the react-native packager.
Watch your AVDs
Anytime you create a new AVD be sure to increase the size of the configure screen. The reason I say this is that it does not show the entire configure screen, where you can find other options, and most important errors and warnings about your configuration. If you have a AVD that’s not going to work with the configuration, it will tell you. The one error to watch out for is when it mentions that it will not work without a certain system image. or that there is not a matching ABI. These sdk packages can be easily overlooked, and finding them can be a chore, but we will discuss this more in a minute.
You want to make sure you set your SDK path with the ANDROID_HOME variable before you create a single project. If you create a new project using ‘react-native init’ like you should, you will receive errors that the SDK is missing. This is where you’ll have to set it in the project explicitly. To do so we need to make a ‘/android/local.properties’ file, and add:
sdk.dir = /path/to/the/android/sdk
Of course changing the directory to the correct directory.
In OSX we also want to make sure our path exports are set accordingly. This is mentioned in the React-Native docs mentioned earlier, but I also found where the exports didn’t always load on startup. To remedy this issue you can add the following to the .bash_profile in your home folder to make sure that the .bashrc contents load flawlessly. If it doesn’t exist, simply create it with the following code:
[[ -s ~/.bashrc ]] && source ~/.bashrc
Using the SDK Manager you can find a lot of different API packages, tools, and various ABIs to simulate all sorts of Android environments. To gain access to this repository of packages you can open the SDK Manager using Android Studio’s Splash Screen and going to Configure > SDK Manager. The thing that can trip people up, and it did me, is that it doesn’t show everything by default! I’m sure this is to reduce the amount of noise, and simplifying the install process, but que sera sera.
When you are missing packages, but swear you installed everything you needed, it’s probably because you missed something only shown in the Standalone SDK Manager list. In the Android Studio SDK Manager, you can actually find a button that takes you straight there. If you look below the list, there is an option to Launch Standalone SDK Manager, which will show all of the packages. You can also check the box on the right that says Show Package Details, which will give you more options to choose from. For a more straight-forward approach, you can also run the standalone manager by running android sdk in the Terminal or Command Prompt.
Remember when we talked about making it easier to get the packages for AVDs? You can actually use Android Studio’s AVD Manager to make sure you have everything needed when starting and creating AVDs. Unlike the standalone AVD Manager, The Studio’s AVD Manager will tell you when you’re missing ABIs, or SDK packages needed to run correctly, and when making a new profile it will not allow you to continue with the profile if it doesn’t have the packages needed to run correctly. This can certainly help you make sure that you have everything you need for your emulators, and builds.
Errors to Watch Out For
When running the ‘react-native run-android –debug’ command to build, if it errors here are some of the most common errors:
No online devices found: This means it cannot see the emulator, or the emulator is not running. Use ‘adb devices’ to list available devices.
ShellCommandUnresponsiveException: This happens on the app:installDebug module process, and means communication with the emulator is not sound. I’m being vague, because so is the error, and what needs to be fixed. This can be due to the avd device not having the correct packages to run. It can also be because gradle is using a version that doesn’t work.
The ShellCommandUnresponsiveException is a very generic error, and happens for many different things, but you can always count on it having to do with the device it’s sending to. I myself ran into an issue where it gave an error that it could not find an emulator that could handle density -1, with ABI of <abi I was using>. No matter what I did, or what I looked for, it would never work with the emulator. I’ll discuss this in it’s own section below.
If the Build Fails On App
If for some reason your build fails on the :app portion, you may see that the error isn’t very verbose. Well, it is, but not with anything helpful. To get a better error, you can hand-compile it, and get a real error. To do so, go into the android folder, and then run:
Project/Android:> ./gradlew app --debug
Running the gradle script by hand for the ‘app’ with the –debug flag, you can not only see much more information, but also see all of the errors that happen in the process that cause it to fail. You can also use the –info, and –stacktrace flags for different outputs that may fit your needs a bit more.
If the Build Fails on InstallDebug
The one place the build is well-known to have issues is the installDebug process, where it sends the compiled package to the device. This is where you will receive that generic error, and while you can compile it by hand to get more errors, the reason is most likely emulator related. If you find yourself making sure everything mentioned above is working fine, but are still receiving errors from installDebug, you may want to result to installing manually. This allows you to skip the step where the script installs the package to the device, and continue on your own.
Since the script made it this far, we know the package has been compiled, which we can find in the output. This means we can install manually with the following, and move forward:
Project/:> adb install android/app/build/outputs/apk/debug.apk
This will install the apk package to the available device, and continue where you left off. If for some reason the AVD has issues with execution (starting the app for you), you will need to go to the app list in the emulator, and start the newly uploaded APK.
Just because the tools and platform tools are API version 24 and 23, that doesn’t mean the target OS has to match that. On my own system I found that I could only get 6.0 (API 23 Marshmallow) to work with an ARM processor, and even then uploading to it gave errors. Using 4.2 (API 17 Jellybean) instead provided a quick boot, and no issues at all. Surprisingly moving up to 4.3 (API 18 Jellybean) brought errors with uploading and execution. Just be aware that you may need to manually install and execute when running versions above 4.2, assuming they do start.
There are surely ways to make these later versions work well, but if it’s taking too much time loading, or simply taking too much time to work, and you don’t need a specific version, go with an older version you know is going to work right out of the box.
HAXM is the driver used with Intel CPUs to emulate x86 CPUs for the emulators. When I started looking for reasons why emulators would not work on my old mid 2009 Macbook Pro with P7500 Core2Duo, I saw a lot of talk about the Intel HAXM driver not working for the Core2Duo on OSX. I can tell you right now, that’s no longer true. Intel’s 6.0.3 driver comes stock with the SDK for OSX, and works just fine. Depending on your CPU it may be trivial emulating x86_64, but that’s not a huge deal. Either way it needed to be mentioned since there is little word saying it does work.
I do want to mention I have seen where some Core2Duo users had a CPU that had issues with HAXM, and when replaced worked perfectly fine. If you someone who is really curious (I keep trying to ignore the urge), you can always install Windows with Bootcamp, and see if works on Windows which will remove that worry.
When the Android Emulator Simply Does Not Work
So if you find yourself in a “Worse Case Scenario” like I did at first, stop looking at new and used Macs on Amazon (even though you can get them really cheap), and instead look at alternatives.
Right now I have three alternatives I suggest that all work well, where one of them I’m really fond of, and the other two I could live without. The only downfall from these three are they are all AOS Jellybean, but that won’t keep you from making anything.
Bluestacks: This is a great emulator advertised as an emulator for Android games on your PC and Mac. Bluestacks 2 is available for Windows, which gives you portrait view, and keystrokes for actions like “shake”. Once you start this emulator up you’ll see it as a device in the adb device list, so you can upload apks right to it to test them out. I cannot tell for sure, but it seems to be using Jellybean 4.2.
While it’s not my favorite, it works well for development, and Bluestacks 2 makes it even better.
Droid 4x: Droid4x is similar in nature to Bluestacks, as it’s geared towards games offering a subscription service to run Android apps on iOS; I have yet to try using it in the iOS sim. Even though it can take a very long time to download since it’s on a slow server halfway across the world, it’s a very well put together emulator using VirtualBox. Unfortunately it doesn’t show in the device list, but gives you an easy option to install APKs which works out quite well. I’m not sure about the OS version due to the many changes, but it almost seems to be 4.2 or 4.3.
AndyOS: Last is AndyOS, another VirtualBox-based emulator. Before you install you need to make sure to have the VirtualBox stand-alone installed, and it takes a lot of CPU getting started, and after; my system actually crashed with a gray screen error the first time running. It’s runs a lot like the android AVD in the sense it needs to initialize for the first time. For me it took 20 minutes to see this finish, but once it did, it made for a great emulator.
On a good note it’s another emulator that shows in the device list since debugging is on by default, allowing you to upload to it. AndyOS also gives you a full Android OS, and not something dumbed down lacking options like the other two. Having a portrait view, geolocation, microphone, Google Play, Google Services, and keybindings makes this a great emulator for development, and a great replacement for AVDs all together. It is definitely my favorite out of the three, but it is extremely CPU intensive. Since it offers all of the default options, you can see it runs 4.2.2 Jellybean.
What about Genymotion?
I know many suggest Genymotion as an AVD replacement, but in my current experience it doesn’t work for every system. Even being another VirtualBox setup, it refuses to work on my system at all. This could be a 10.11 issue, or a Core2Duo issue, but I certainly cannot speask about it when it won’t run on my system at all.
Once you get your app running in an emulator, you will usually be presented with a red screen and an error complaining about not seeing the development server. The general cause for this is needing to send data back in the opposite direction, and we can do this when you run the reverse command to reverse the data flow. Reload, and check out your running application!
> adb reverse tcp:8081 tcp:8081
If you are using an emulator with AOS older than 5.0, the reverse isn’t going to help. Instead we need to access the adb server. For emulators that do not have a shake button or hotkey, you can send the key event to the device manually.
> adb shell input keyevent 82
Now we can go to the Dev Settings, and choose the Debug server host * port for device option. In this option we can use the IP address of our machine, which we can find in the terminal using the ifconfig command in Linux and OSX, or in the Windows Command Prompt (cmd) using ipconfig. You should find the IP address starting with 192.168, or 10.[0-255], but most likely the first. For instance for my system I’m using: 192.168.1.105:8081 . After that’s set go back to the application, send another shake command, and then click reload. You’ll start seeing the react-native package manager doing some work, and then see a message on your emulator, “Fetching JS Bundle”. Sit back, and get ready for your app to load!
We should now have a working app running on our emulator, and all the knowledge needed to do it all again when we need to!
So now that we’ve gone through the entire process, and have seen what is needed to get your react-native apps working on Android no matter what the situation, I hope that this answers a lot of questions. If you still have questions, please feel free to ask below, and I’ll be happy to answer them, and maybe add them to the article.