react-native-goodflip-bca-height
v0.1.1
Published
GoodFlip BCA Height SDK for React Native
Readme
react-native-goodflip-bca-height
This project is a minimal React Native app showing how to integrate **react-native-goodflip-bca-height** – a GoodFlip smart scale (weight + height) SDK wrapper – on Android and iOS, including the required **react-native-permissions setup.
The app:
- Initializes the GoodFlip SDK once at startup
- Scans for nearby GoodFlip height/weight scales over BLE
- Connects to a selected device with user info (id, height, gender, birthday)
- Streams live weight while the user is on the scale
- Displays a final measurement result (weight, height, and itemized scale data)
1. Overview
**react-native-goodflip-bca-height provides:
- BLE-based connection to GoodFlip height/weight smart scales
- User profile (id, height, gender, birthday) for measurements
- Device events: scan started/stopped, device discovered, connection state, live weight, final result
- Native Bluetooth & location permissions handled via
**react-native-permissions** (iOS) and the **Android manifest**
In this demo app, all GoodFlip interactions live in App.tsx:
initGoodFlipSdk()initializes the SDK on mountattachGoodFlipListeners()subscribes to device/scan/measurement eventsstartGoodFlipScan()/stopGoodFlipScan()control scanningconnectGoodFlipDevice(...)connects and triggers a measurement with user datadisconnectGoodFlipDevice(...)cleans up the connection
2. Required Packages
Core dependencies
These are used and already installed in this project (see package.json):
| Package | Purpose |
| ---------------------------------- | --------------------------------------------------------------------------------------- |
| react-native-goodflip-bca-height | Main integration package for GoodFlip height/weight scales (BLE scanning and measuring) |
Peer / supporting dependencies
| Package | Purpose |
| -------------------------- | ---------------------------------------------------------------------------------- |
| react-native-permissions | iOS: Bluetooth & Location permission configuration via Podfile setup_permissions |
Note: The GoodFlip library bundles its required native BLE SDKs and other Android/iOS libraries. You do not need to add extra BLE libraries in Gradle or CocoaPods beyond what
react-native-goodflip-bca-heightpulls in.
3. React Native Setup
3.1 Install dependencies
From your project root:
npm install react-native-goodflip-bca-height react-native-permissions
# or
yarn add react-native-goodflip-bca-height react-native-permissionsAutolinking (React Native 0.60+) handles the native modules for both platforms.
3.2 Rebuild the app
After installing the packages and applying the Android/iOS config below:
# Android
npx react-native run-android
# iOS
cd ios && pod install && cd ..
npx react-native run-ios4. Android Integration
This project is already configured; use this section to mirror the setup in your own app.
4.1 Minimum SDK and compile/target
android/build.gradle:
**minSdkVersion**:24**compileSdkVersion**:36**targetSdkVersion**:36
These are exposed via the shared Gradle ext block and used by android/app/build.gradle:
buildscript {
ext {
buildToolsVersion = "36.0.0"
minSdkVersion = 24
compileSdkVersion = 36
targetSdkVersion = 36
}
}Make sure your app uses at least these versions so the GoodFlip SDK can build and run correctly.
4.2 Bluetooth & Location permissions
This app declares all relevant BLE and location permissions in android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />In your own project, ensure at least:
INTERNETACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATIONBLUETOOTH/BLUETOOTH_ADMIN(for API < 31, usually withandroid:maxSdkVersion="30")BLUETOOTH_SCANBLUETOOTH_CONNECT
The GoodFlip SDK will rely on these for BLE scanning and connecting.
4.3 Build & run
cd android
./gradlew clean
cd ..
npx react-native run-androidFor real BLE testing, use a physical Android device with Bluetooth and (if needed) Location enabled.
5. iOS Integration
This project’s iOS side is already wired for react-native-goodflip-bca-height and react-native-permissions.
5.1 Podfile – permissions setup
ios/Podfile:
- Loads the
react-native-permissionssetup script - Enables Bluetooth and Location permissions via
setup_permissions - Excludes
arm64for the simulator to avoid framework arch issues
Key parts:
# At the top of your Podfile (after require)
permissions_setup_path = File.expand_path('../node_modules/react-native-permissions/scripts/setup.rb', __dir__)
require permissions_setup_path
platform :ios, min_ios_version_supported
prepare_react_native_project!
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
else
use_frameworks! :linkage => :static
end
setup_permissions([
'Bluetooth',
'BluetoothPeripheral',
'Notifications',
'LocationWhenInUse',
])
# Add this line above "use_react_native!" block
use_frameworks! :linkage => :static
#Place this inside you target block
post_install do |installer|
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
end
if target.name == 'QNSDK'
target.build_configurations.each do |config|
config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES'
config.build_settings['WARNING_CFLAGS'] = '-Wno-error -Wno-narrowing'
config.build_settings['OTHER_CFLAGS'] = '$(inherited) -Wno-error -Wno-narrowing'
end
end
end
installer.aggregate_targets.each do |aggregate_target|
aggregate_target.user_project.native_targets.each do |native_target|
native_target.build_configurations.each do |config|
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
end
end
end
qn_config = 'Pods/QNSDK/QNSDK/SDK/QNConfig.h'
if File.exist?(qn_config)
content = File.read(qn_config)
patched = content.gsub('NS_ENUM(NSUInteger,', 'NS_ENUM(NSInteger,')
if content != patched
FileUtils.chmod(0644, qn_config)
File.write(qn_config, patched)
puts "Patched QNSDK QNConfig.h: NSUInteger -> NSInteger"
end
end
endIf you are migrating this setup, make sure:
permissions_setup_pathandrequire permissions_setup_pathare at the topsetup_permissions([...])includes at leastBluetoothandLocationWhenInUse- The
post_installblock setsEXCLUDED_ARCHS[sdk=iphonesimulator*] = 'arm64'for simulator targets
Then run:
cd ios
pod install
cd ..5.2 Info.plist usage descriptions
ios/demo_app/Info.plist already declares the required permission usage strings:
<!-- Bluetooth (scan/connect/advertise) -->
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to scan for and connect to your smart scale.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to communicate with your smart scale.</string>
<!-- Location (needed by iOS when scanning BLE in many cases) -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs your location while in use to detect nearby Bluetooth devices.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs your location even in the background to stay connected to your smart scale.</string>In your own app, customize these strings, but keep the keys so iOS will show the Bluetooth and Location permission prompts.
5.3 Build & run
cd ios
pod install
cd ..
npx react-native run-iosBLE will only work on a real iOS device with Bluetooth enabled. The simulator is useful to verify builds and UI only.
6. Usage in Code (from this demo)
All integration happens in App.tsx. The flow is:
- Initialize SDK on mount with
initGoodFlipSdk() - Attach listeners with
attachGoodFlipListeners(...) - Start scanning with
startGoodFlipScan() - Connect to a selected device with
connectGoodFlipDevice(...)and user info - Show live weight and final result from listener callbacks
- Clean up listeners, scanning, and connections on unmount
Simplified example based on this project:
import { useEffect, useRef, useState } from 'react';
import {
initGoodFlipSdk,
attachGoodFlipListeners,
startGoodFlipScan,
stopGoodFlipScan,
connectGoodFlipDevice,
disconnectGoodFlipDevice,
} from 'react-native-goodflip-bca-height';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Button, Text, View } from 'react-native';
const USER = {
id: 'user-001',
height: 170,
gender: 'male' as const,
birthday: '1990-05-20',
};
export default function App() {
const [devices, setDevices] = useState<any[]>([]);
const [liveWeight, setLiveWeight] = useState<number | null>(null);
const [result, setResult] = useState<any | null>(null);
const listenersRef = useRef<{ remove(): void } | null>(null);
useEffect(() => {
let mounted = true;
const run = async () => {
await initGoodFlipSdk();
if (!mounted) return;
listenersRef.current = attachGoodFlipListeners({
onDeviceDiscovered: (device) => {
setDevices((prev) =>
prev.find((d) => d.mac === device.mac) ? prev : [...prev, device]
);
},
onUnsteadyWeight: (weight) => setLiveWeight(weight),
onScaleData: (data) => {
setResult(data);
setLiveWeight(null);
},
});
};
run();
return () => {
mounted = false;
listenersRef.current?.remove();
disconnectGoodFlipDevice().catch(() => {});
stopGoodFlipScan().catch(() => {});
};
}, []);
const startScan = () => {
setDevices([]);
startGoodFlipScan().catch(() => {});
};
const connect = (mac: string) => {
connectGoodFlipDevice(
mac,
USER.id,
USER.height,
USER.gender,
USER.birthday
).catch(() => {});
};
return (
<SafeAreaProvider>
{/* UI for scanning, listing devices, connecting, and showing results */}
</SafeAreaProvider>
);
}Refer to App.tsx in this repo for the full example including UI state (screens, scanning indicator, errors, etc.).
7. API Reference (as used in this app)
The exact surface area of
react-native-goodflip-bca-heightmay be larger; this is the subset used in this project.
Core functions
| Function | Description |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| initGoodFlipSdk(): Promise<{ sdkReady: boolean; message?: string; error?: string }> | Initialize the GoodFlip SDK. Called once at app start. |
| attachGoodFlipListeners(listeners): { remove(): void } | Subscribe to GoodFlip events (scan, connection, weight, result). Returns a remover. |
| startGoodFlipScan(): Promise<void> | Start scanning for GoodFlip scales over BLE. |
| stopGoodFlipScan(): Promise<void> | Stop scanning. |
| connectGoodFlipDevice(mac, userId, height, gender, birthday): Promise<void> | Connect to a scale and start a measurement with the given user data. |
| disconnectGoodFlipDevice(mac?: string): Promise<void> | Disconnect from the current device (the app passes the connected MAC when available). |
Listener callbacks (from this project)
The app passes this object into attachGoodFlipListeners:
**onDeviceDiscovered(device)**– called when a device is found during scanning
Exampledeviceshape:{ mac, name, rssi }**onScanStarted()/onScanStopped()**– scanning state changes**onScanFailed(errorCode)**– scan failed (error code from native)**onConnectionChanged(event, mac, errorCode)**– connection lifecycleeventexamples:'connecting','connected','disconnected','connectError'**onUnsteadyWeight(weight)**– live weight updates while the user is still moving**onScaleData(data)**– final result once the measurement is complete
The app expects:data.mac: device MACdata.weight: final weight in kgdata.height: final height in cm (if available)data.items: array of{ type, name, value }entries (detailed metrics)
8. Troubleshooting
8.1 “Native module not found” / linking errors
- Ensure you installed the package:
npm install react-native-goodflip-bca-height react-native-permissions
- Run
pod installinsideios/and rebuild:cd ios && pod install && cd ..npx react-native run-ios
- For Android, clean and rebuild:
cd android && ./gradlew clean && cd ..npx react-native run-android
8.2 Android: scanning or connecting does not work
- Confirm your device has Bluetooth and Location enabled.
- Verify the permissions in
AndroidManifest.xml(see 4.2). - Test on a real device, not only on emulators (emulators often lack proper BLE support).
8.3 iOS: Bluetooth or location prompt never appears
- Ensure
Info.plisthas all Bluetooth and Location usage keys (see 5.2). - Verify that
setup_permissions([...])inPodfileincludes:'Bluetooth','BluetoothPeripheral','LocationWhenInUse'
- Run
pod installagain after editing the Podfile.
8.4 iOS simulator: build fails due to arm64 or BLE framework
- This project excludes
arm64for iphonesimulator in the Podfile’spost_installblock. - Make sure your Podfile has:
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'for both pods project and the user project targets.
- Prefer testing BLE on a real iOS device.
8.5 Listener callbacks not firing
- Ensure
initGoodFlipSdk()is called beforeattachGoodFlipListeners. - Make sure you call
startGoodFlipScan()to begin scanning. - Only call
connectGoodFlipDevice(...)after a device has been discovered (e.g. in tap handler on a device row). - Do not forget to keep the reference returned by
attachGoodFlipListenersand call.remove()on unmount.
9. Summary Checklist (for your own app)
React Native
- Install:
react-native-goodflip-bca-height,react-native-permissions,react-native-safe-area-context - Initialize GoodFlip SDK on startup with
initGoodFlipSdk - Attach listeners via
attachGoodFlipListeners - Scan & connect using
startGoodFlipScan,connectGoodFlipDevice, and show results from callbacks
Android
minSdkVersion >= 24,compileSdkVersion/targetSdkVersion >= 34(this demo uses 36)- Add Bluetooth + Location permissions to
AndroidManifest.xml - Build on a real device for BLE
iOS
- Configure
react-native-permissionsinPodfilewithsetup_permissions([...]) - Add Bluetooth and Location usage strings in
Info.plist - Exclude
arm64for the simulator if required by the native frameworks - Run
pod installand then rebuild
Following the patterns in this demo app, you can plug GoodFlip height/weight scale measurements into your own React Native UI while keeping all native BLE and permission handling encapsulated in react-native-goodflip-bca-height.
