- So You Want to Build a Bluetooth App with React Native and Expo
- Part 1 — Ejecting Expo and Bluetooth
- Overview
- 1 — Introduction
- 2 — Eject Expo
- Step 1
- Step 2
- Step 3
- Step 4
- Step 5
- Step 6
- 3 — iOS Setup
- Step 1
- Step 2
- Step 3
- Step 4
- Step 5
- Step 6
- 4— Android Setup
- Step 1
- Step 2
- Step 3
- Step 4
- 5—Conclusion
- 6 — Who to ask for help
- 7 — Troubleshooting
So You Want to Build a Bluetooth App with React Native and Expo
Update: The post below is out of date, and left leave this here for historical reference. There is no requirement for ejecting (deprecated) from Expo’s ecosystem. You can use Config plugin to achieve the same result as mentioned below. To learn more how about config plugins, which are the Expo way of customizing the prebuild phase of a project, see our documentation.
Let’s say you’re starting your next project, and your app is Bluetooth-based. Which means you have to connect to a Bluetooth-enabled device. At Penta Medical, we use React Native and various libraries to connect to our Bluetooth Low Energy (BLE) device without having to write much native code. Here’s a quick guide to help you accomplish all of this with React Native and Expo. (Before we begin, you should know that this method will only work for BLE devices and not Bluetooth classic devices.)
Part 1 — Ejecting Expo and Bluetooth
This guide is Part One of a planned three-part series. In this first part, we focus on ejecting Expo and setting up React Native to interface with the Bluetooth capabilities of the phone. In the second part, we’ll explore a simple Bluetooth app, and in the third, we’ll re-build the same app using Expo’s future Bluetooth API. Here’s a quick overview of what we’ll cover today:
Overview
1. Introduction
2. Eject Expo
3. iOS setup
4. Android setup
5. Conclusion
6. Who to ask for help
7. Troubleshooting
1 — Introduction
As many developers have, Expo was the first place we looked for a Bluetooth API. It only made sense to turn to them as they provide a ton of useful JavaScript APIs that interact with a mobile device. But lo and behold our Google search left us empty handed. There is no Bluetooth API for Expo yet, but you can still build a Bluetooth app with Expo.
As soon as we discovered this, we made a feature request on Canny for an Expo Bluetooth API. Canny is the best way to get the features you care about prioritized on the Expo roadmap.
2 — Eject Expo
But maybe you’re like us and you need Bluetooth and you need it now. You can still use Expo, but there is a catch, you will need to eject your Expo project. Yes, you heard me right (see below).
Before we dive into ejecting your Expo project let’s talk about the challenges of ejecting expo. Here are some of them:
- Adding native libraries requires a great deal of Xcode and Android Studio setup (the focus of this guide).
- Expo makes your life easier, but when you eject Expo some of that easiness goes away. For example, getting setup and getting the app on your phone.
- Installing your project is no longer as easy as npm install
So, if Expo builds a Bluetooth API it will make our life much easier, but for now we must use the libraries at our disposal. There is a library called React Native BLE Plx built by a company called Polidea. We are going to use this library to interact with the Bluetooth capabilities of the mobile device. Since this library adds custom native modules we must eject our Expo project. This allows us to use ExpoKit to add custom native modules. Let’s get started.
Step 1
Before we begin its a good idea to update your Mac OS to the latest version. Additionally, you will need Xcode and the Command Line Tools which come with Xcode. You can get Xcode here and or update Xcode to the latest version in the App Store.
Lastly, open Xcode → Preferences → Locations and ensure you have the Command Line Tools setup like the below image.
From this point on I am assuming you have an Expo project setup. For example, you used expo-cli or similar as a starting point for your app. For example:
npm install -g expo-cli
mkdir ~/workspace
cd ~/workspace
expo init myapp
And have changed directories into your app like so cd ~/workspace/myapp .
Step 2
If you don’t have it, run npm install -g expo to get the expo command line library. If you haven’t used expo , the first thing you’ll need to do is log in with your Expo account using expo login .
Step 3
Ejecting requires the same keys as building a standalone app. Follow these instructions before continuing to the next step. The important keys are: bundleIdentifier , package , name , icon , version , slug and sdkVersion .
Step 4
From your project directory, run expo eject . This will download the required dependencies and build native projects under the ios and android directories.
Install react-native-cli CLI tools if you don’t have it like so: npm install -g react-native-cli .
We can now add third-party native modules for React Native, non-Expo-specific instructions such as react-native link will work. We will need to use this command to use react-native-ble-plx .
Step 5
From your project directory, we need to install react-native-ble-plx to do so run npm install react-native-ble-plx —save .
Step 6
Now we link the native dependency like so react-native link react-native-ble-plx , a command we are only allowed to use because we have ejected Expo.
Unfortunately, react-native link is not fully automatic. From this point on we will need to set-up Android and iOS manually.
3 — iOS Setup
Let’s set up the project for iOS. The minimal supported version of iOS is 8.0.
Step 1
In Xcode, add an empty Swift file if you don’t have at least one:
- Select File/New/File…
- Choose Swift file and click Next.
- Name it however you want, select your application target and create it.
- Accept to create Objective-C bridging header.
Step 2
In a terminal from your project directory install cocoapods like so:
sudo gem install cocoapods
pod setup
Step 3
We start by moving into the iOS folder of our RN project, and typing pod init, which generates the template Podfile.
Update your ios/Podfile to contain:
pod 'react-native-ble-plx', :path => '../node_modules/react-native-ble-plx'
pod 'react-native-ble-plx-swift', :path => '../node_modules/react-native-ble-plx'
Step 4
Then from your project directory install the pods in the ios directory:
Step 5
Optionally, if you want to support background mode:
- In your application target go to the Capabilities . →. Background Modes → Enable Uses Bluetooth LE Accessories .
- Pass restoreStateIdentifier and restoreStateFunction to the BleManager constructor.
Step 6
Now in Xcode you can build the project, Product → Build and then run the project Product → Run . If you get warnings thats okay, but if you get errors see the troubleshooting section below.
4— Android Setup
Let’s setup the project for Android.
Step 1
Install Android Studio here. Choose the standard setup.
Step 2
In android/app/build.gradle , ensure that the min SDK version is at least 18:
android .
defaultConfig minSdkVersion 18
.
Step 3
In android/app/src/main/AndroidManifest.xml , add Bluetooth permissions and update :
Step 4
Connect your phone via USB. In a terminal, go to cd ~/Library/Android/sdk/platform-tools/ and run ./adb devices to ensure that your device shows up.
From your project directory run react-native run-android to test that the app installs on your phone.
5—Conclusion
I hope you haven’t lost too much hair as that was a lot of setup! Hopefully, when Expo builds a Bluetooth API, it’ll make this process much easier, at which point we’ll explore it in the third part of this series. And in the second part we’ll build a simple Bluetooth app using react-native-ble-plx and Expo. For now, check out the documentation to learn more about this useful library we setup.
6 — Who to ask for help
- If you have an Expo specific question, post your question on Expo’s forum. If you need live help check out the #bluetooth channel on Expo’s Slack.
- If you have a react-native-ble-plx specific question post a Github issue here. The team at Polidea is very helpful.
- Lastly, give me a follow on Twitter and tweet or DM me any questions. I tend to be very active on Twitter.
7 — Troubleshooting
- Runtime Error: SIGABRT on fileprivate var connectedDevices = Dictionary() — see this Github issue
- RCTDefines not found — You forgot to add the Header Build paths (see instructions above)
- RCTBridgeModule.h not found — Check the header search path and make sure its not using ./nvm caches. If needed re-clone the project and make sure you npm cache clean before you install everything
- RCTBluetoothManager not found — first make sure you opened yourappname.xcworkspace not yourappname.xcodeproj . If that doesn’t work try rebuilding by doing cd ./node_modules/react-native-ble-plx then ./build_ios_frameworks.sh
- RCTDefines not found in RNDeviceInfo — You forgot to add the header build path $/../../../ios/Pods/Headers/Public and should do a npm cache clean and then restart your computer and build again
- No visible @interface for ‘RCTAsyncLocalStorage’ declares the selector ‘initWithStorageDirectory: — see this Github issue
Looking forward to building a Bluetooth app with Expo? Follow our guest blogger Adrian Carolli on Github and Twitter to keep updated.