Compare commits

...

2 Commits

Author SHA1 Message Date
c14d41b345 refactor: update WeightScaleBridge integration and error handling
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
CI / build-library (pull_request) Has been cancelled
CI / build-android (pull_request) Has been cancelled
CI / build-ios (pull_request) Has been cancelled
2025-12-16 16:39:05 +05:30
88a89bcbd3 Latest Code Updated 2025-12-16 15:10:39 +05:30
4 changed files with 231 additions and 42 deletions

View File

@@ -1,2 +1,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
</manifest>

View File

@@ -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
}
}
}

View File

@@ -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<NativeModule> {
return listOf(WeightScaleModule(reactContext))
}
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
return ReactModuleInfoProvider {
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
moduleInfos[WeightScaleBridgeModule.NAME] = ReactModuleInfo(
WeightScaleBridgeModule.NAME,
WeightScaleBridgeModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
false, // isCxxModule
true // isTurboModule
)
moduleInfos
}
}
override fun createViewManagers(
reactContext: ReactApplicationContext
): List<ViewManager<*, *>> = emptyList()
}

View File

@@ -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();