react-native-google-nearby-messages
An async Google Nearby Messages API Wrapper for React Native (Android & iOS), supporting autolinking, custom discovery modes (broadcast
, scan
, ..), custom discovery mediums (bluetooth
, audio
, ..), awaitable native invokations and React hooks!
Also, this is a good example on how to use Swift in a React Native - Native Module.
Install
This packages uses React Native autolinking (> 0.60)
npm i react-native-google-nearby-messages
# for iOS
cd ios && pod install && cd ..
Note (iOS): Everytime you run
pod install
an entry calledAssets.car
is created in your Build Phases -> [CP] Copy Pods Resources which causes the build to fail. This is a known bug in the Google NearbyMessages pod. A workaround is to manually remove this file everytime you runpod install
. See #4 (comment) for an automatic fix. Please create a PR here if you found a better solution for this!
Usage
See the example app.
iOS Setup
See: https://developers.google.com/nearby/messages/ios/get-started
- Add bluetooth permissions (
NSBluetoothPeripheralUsageDescription
,NSBluetoothAlwaysUsageDescription
for 'ble', andNSMicrophoneUsageDescription
for 'audio') toInfo.plist
- Create your API Key at the Google Developer Console.
- (Optionally): Add the react-native-permissions library to check if Bluetooth is available on the device (it's
'unavailable'
on iOS Simulators!) If it's'unavailable'
, calls to subscribe or publish might crash the app (EXC_BAD_ACCESS
) so only call if Bluetooth permission isdenied
,granted
orblocked
. This library will handle the permission checking for you when you callpublish()
orsubscribe()
for the first time. - Pass the generated API Key as a parameter using the
connect
function
Android Setup
See: https://developers.google.com/nearby/messages/android/get-started
-
Create your API Key at the Google Developer Console.
-
Add your generated API Key and Permissions to your
AndroidManifest.xml
:<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.sample.app" > <!-- For BLE/Bluetooth --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- For Audio --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <application ...> <meta-data android:name="com.google.android.nearby.messages.API_KEY" android:value="API_KEY" /> <activity> ... </activity> </application> </manifest>
-
(Optionally): Call
checkBluetoothAvailability()
to ensure that Bluetooth capabilities are available on the current device. -
Call
connect
without any key.
Publishing
import { connect, publish, addOnErrorListener } from 'react-native-google-nearby-messages';
const removeListener = addOnErrorListener((kind, message) => console.error(`${kind}: ${message}`));
const disconnect = await connect({ apiKey: GOOGLE_API_KEY });
const unpublish = await publish('hello !');
// later, e.g. in componentWillUnmount()
removeListener();
unpublish();
disconnect();
Make sure to unpublish, disconnect and remove any listeners as they won't be removed automatically! I don't know if that's possible, if so, please create a Pull Request.
Subscribing
import { connect, subscribe, addOnErrorListener } from 'react-native-google-nearby-messages';
const removeListener = addOnErrorListener((kind, message) => console.error(`${kind}: ${message}`));
const disconnect = await connect({ apiKey: GOOGLE_API_KEY });
const unsubscribe = await subscribe(
(m) => {
console.log(`new message found: ${m}`);
},
(m) => {
console.log(`message lost: ${m}`);
});
// later, e.g. in componentWillUnmount()
removeListener();
unsubscribe();
disconnect();
Make sure to unpublish, disconnect and remove any listeners as they won't be removed automatically! I don't know if that's possible, if so, please create a Pull Request.
Bluetooth Availability
Check if the user has granted Bluetooth Permissions. This feature is experimental, and strongly differs between iOS and Android.
import { checkBluetoothPermission } from 'react-native-google-nearby-messages';
const hasPermission = await checkBluetoothPermission();
Check if bluetooth is available on this device. This feature is experimental, and strongly differs between iOS and Android. Make sure to use a library like react-native-permissions to check if Bluetooth is really available, otherwise your Application might crash with a EXEC_BAD_ACCESS
error. See troubleshooting
import { checkBluetoothAvailability } from 'react-native-google-nearby-messages';
const isBluetoothAvailable = await checkBluetoothAvailability();
React Hooks
This library also provides react hooks for common use cases. In case you're not familiar with hooks, please read the hooks documentation. When the component unmounts, the hooks automatically stop publishing, subscribing, remove error listeners and disconnect for you. You can also look into the hooks source code and tweak them for your use case.
Make sure to memoize the NearbyConfig
object using useMemo
, otherwise the hooks will fall into an infinite loop of re-renders because the config object gets re-created each time and therefore has changed. (See: react useEffect's deps)
useNearbyPublication
Publishes a message and returns a state which describes the Nearby API status. (e.g.: connecting
, published
, error
, ...)
export default function App() {
const nearbyConfig = useMemo<NearbyConfig>(() => ({ apiKey: GOOGLE_API_KEY }), []);
const nearbyStatus = useNearbyPublication(nearbyConfig, 'Hello from Nearby!');
// ...
}
useNearbySubscription
Subscribe to nearby messages and return a state for all messages in an array, as well as a state describing the Nearby API Status. (e.g.: connecting
, published
, error
, ...)
export default function App() {
const nearbyConfig = useMemo<NearbyConfig>(() => ({ apiKey: GOOGLE_API_KEY }), []);
const { nearbyMessages, nearbyStatus } = useNearbySubscription(nearbyConfig);
return (
<FlatList
data={nearbyMessages}
renderItem={({ item }) => <Text>{item}</Text>}
/>
);
}
useNearbySearch
Search for a specific message using nearby messages. The isNearby
local specifies whether the string iPhone 11
could be found using the Nearby API, and the nearbyStatus
local describes the current status of the Nearby API. (e.g.: connecting
, published
, error
, ...)
export default function App() {
const nearbyConfig = useMemo<NearbyConfig>(() => ({ apiKey: GOOGLE_API_KEY }), []);
const { isNearby, nearbyStatus } = useNearbySearch(nearbyConfig, 'iPhone 11');
return (
<Text>{isNearby ? 'iPhone 11 is nearby!' : 'iPhone 11 is far, far away.'}</Text>
);
}
useNearbyErrorCallback
Subscribe to any errors emitted from the Nearby API.
export default function App() {
useNearbyErrorCallback((kind, message) => {
console.log(`Nearby API Error: ${kind}: ${message}`)
});
}
Troubleshooting
If you're having any trouble getting the Nearby API working, please make sure you've read the Troubleshooting Page.
If that doesn't help either, create an issue.