diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index a2f47b6..6cac27a 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1,2 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt b/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt
index 9285a00..f3a6dc6 100644
--- a/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt
+++ b/android/src/main/java/com/weightscalebridge/WeightScaleBridgeModule.kt
@@ -1,23 +1,193 @@
package com.weightscalebridge
-import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.module.annotations.ReactModule
+import android.Manifest
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.BluetoothLeScanner
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanResult
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.ContextCompat
+import com.facebook.react.bridge.*
+import com.facebook.react.modules.core.DeviceEventManagerModule
+import kotlin.math.pow
+import kotlin.math.round
-@ReactModule(name = WeightScaleBridgeModule.NAME)
-class WeightScaleBridgeModule(reactContext: ReactApplicationContext) :
- NativeWeightScaleBridgeSpec(reactContext) {
+class WeightScaleModule(
+ private val reactContext: ReactApplicationContext
+) : ReactContextBaseJavaModule(reactContext) {
- override fun getName(): String {
- return NAME
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private var scanner: BluetoothLeScanner? = null
+ private var isScanning = false
+ private var timer: CountDownTimer? = null
+ private var currentWeight = 0.0
+
+ override fun getName(): String = "WeightScaleBridge"
+
+ init {
+ val manager =
+ reactContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ bluetoothAdapter = manager.adapter
+ scanner = bluetoothAdapter?.bluetoothLeScanner
}
- // Example method
- // See https://reactnative.dev/docs/native-modules-android
- override fun multiply(a: Double, b: Double): Double {
- return a * b
+ private fun sendEvent(name: String, params: WritableMap?) {
+ reactContext
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
+ .emit(name, params)
}
- companion object {
- const val NAME = "WeightScaleBridge"
+ @ReactMethod
+ fun isBluetoothEnabled(promise: Promise) {
+ try {
+ val enabled = bluetoothAdapter?.isEnabled ?: false
+ promise.resolve(enabled)
+ } catch (e: Exception) {
+ promise.reject("BLUETOOTH_CHECK_ERROR", e.message, e)
+ }
}
-}
+
+ @ReactMethod
+ fun startScanning(promise: Promise) {
+ try {
+ if (!hasPermissions()) {
+ promise.reject("PERMISSION", "Bluetooth permissions not granted")
+ return
+ }
+
+ if (bluetoothAdapter?.isEnabled != true) {
+ promise.reject("BLUETOOTH", "Bluetooth disabled")
+ return
+ }
+
+ if (isScanning) {
+ promise.resolve(true)
+ return
+ }
+
+ isScanning = true
+ currentWeight = 0.0
+
+ scanner?.startScan(scanCallback)
+
+ sendEvent(
+ "onWeightScaleStatus",
+ Arguments.createMap().apply { putString("status", "scanning") }
+ )
+
+ timer = object : CountDownTimer(20000, 1000) {
+ override fun onTick(ms: Long) {}
+ override fun onFinish() {
+ stopScanning(null)
+ }
+ }.start()
+
+ promise.resolve(true)
+ } catch (e: Exception) {
+ promise.reject("SCAN_ERROR", e.message, e)
+ }
+ }
+
+ @ReactMethod
+ fun stopScanning(promise: Promise?) {
+ try {
+ scanner?.stopScan(scanCallback)
+ } catch (_: Exception) {}
+
+ timer?.cancel()
+ isScanning = false
+
+ sendEvent(
+ "onWeightScaleStatus",
+ Arguments.createMap().apply { putString("status", "stopped") }
+ )
+
+ promise?.resolve(true)
+ }
+
+ private val scanCallback = object : ScanCallback() {
+ override fun onScanResult(type: Int, result: ScanResult) {
+ val record = result.scanRecord ?: return
+ val data = record.manufacturerSpecificData
+
+ if (data.size() == 0) return
+
+ val raw = data.valueAt(0)
+ if (raw.size < 2) return
+
+ val weight = (((raw[0].toInt() and 0xff) shl 8) or
+ (raw[1].toInt() and 0xff)) / 10.0
+
+ currentWeight = weight
+
+ sendEvent(
+ "onWeightData",
+ Arguments.createMap().apply {
+ putDouble("weight", weight)
+ putBoolean("isStable", true)
+ }
+ )
+
+ sendEvent(
+ "onWeightScaleStatus",
+ Arguments.createMap().apply {
+ putString("status", "complete")
+ putString("message", "$weight kg")
+ }
+ )
+
+ stopScanning(null)
+ }
+
+ override fun onScanFailed(errorCode: Int) {
+ super.onScanFailed(errorCode)
+
+ sendEvent(
+ "onWeightScaleStatus",
+ Arguments.createMap().apply {
+ putString("status", "error")
+ putString("message", "Scan failed with code: $errorCode")
+ }
+ )
+
+ isScanning = false
+ }
+ }
+
+ @ReactMethod
+ fun calculateBMI(weight: Double, heightCm: Double, promise: Promise) {
+ try {
+ if (heightCm <= 0) {
+ promise.reject("INVALID_HEIGHT", "Height must be greater than 0")
+ return
+ }
+
+ val bmi = weight / (heightCm / 100).pow(2)
+ promise.resolve(round(bmi * 10) / 10)
+ } catch (e: Exception) {
+ promise.reject("BMI_ERROR", e.message, e)
+ }
+ }
+
+ private fun hasPermissions(): Boolean {
+ val perms =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
+ arrayOf(
+ Manifest.permission.BLUETOOTH_SCAN,
+ Manifest.permission.BLUETOOTH_CONNECT
+ )
+ else
+ arrayOf(
+ Manifest.permission.ACCESS_FINE_LOCATION
+ )
+
+ return perms.all {
+ ContextCompat.checkSelfPermission(reactContext, it) ==
+ PackageManager.PERMISSION_GRANTED
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt b/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt
index b5a984a..90fd8c0 100644
--- a/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt
+++ b/android/src/main/java/com/weightscalebridge/WeightScaleBridgePackage.kt
@@ -1,33 +1,19 @@
package com.weightscalebridge
-import com.facebook.react.BaseReactPackage
+import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.module.model.ReactModuleInfo
-import com.facebook.react.module.model.ReactModuleInfoProvider
-import java.util.HashMap
+import com.facebook.react.uimanager.ViewManager
-class WeightScaleBridgePackage : BaseReactPackage() {
- override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
- return if (name == WeightScaleBridgeModule.NAME) {
- WeightScaleBridgeModule(reactContext)
- } else {
- null
- }
+class WeightScaleBridgePackage : ReactPackage {
+
+ override fun createNativeModules(
+ reactContext: ReactApplicationContext
+ ): List {
+ return listOf(WeightScaleModule(reactContext))
}
- override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
- return ReactModuleInfoProvider {
- val moduleInfos: MutableMap = HashMap()
- moduleInfos[WeightScaleBridgeModule.NAME] = ReactModuleInfo(
- WeightScaleBridgeModule.NAME,
- WeightScaleBridgeModule.NAME,
- false, // canOverrideExistingModule
- false, // needsEagerInit
- false, // isCxxModule
- true // isTurboModule
- )
- moduleInfos
- }
- }
+ override fun createViewManagers(
+ reactContext: ReactApplicationContext
+ ): List> = emptyList()
}
diff --git a/src/index.tsx b/src/index.tsx
index 34b188d..c3d4088 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,5 +1,26 @@
-import WeightScaleBridge from './NativeWeightScaleBridge';
+import { NativeModules, Platform } from 'react-native';
-export function multiply(a: number, b: number): number {
- return WeightScaleBridge.multiply(a, b);
+const LINKING_ERROR =
+ `The package 'react-native-weight-scale-bridge' doesn't seem to be linked. Make sure:\n\n` +
+ Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
+ '- You rebuilt the app after installing the package\n' +
+ '- You are not using Expo Go\n';
+
+// Changed to match the native module name
+const WeightScaleBridge = NativeModules.WeightScaleBridge;
+
+if (!WeightScaleBridge) {
+ throw new Error(LINKING_ERROR);
}
+
+export const startScanning = () =>
+ WeightScaleBridge.startScanning();
+
+export const stopScanning = () =>
+ WeightScaleBridge.stopScanning();
+
+export const calculateBMI = (weight: number, heightCm: number) =>
+ WeightScaleBridge.calculateBMI(weight, heightCm);
+
+export const isBluetoothEnabled = () =>
+ WeightScaleBridge.isBluetoothEnabled();
\ No newline at end of file