# RnSensorStepListener.kt
package com.sensor.step
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.util.Log
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
class RnSensorStepListener(private val reactContext: ReactApplicationContext) : SensorEventListener {
private var sensorManager: SensorManager = reactContext.getSystemService(ReactApplicationContext.SENSOR_SERVICE) as SensorManager
private var stepCounterSensor: Sensor? = null
private var sensorType: Int = Sensor.TYPE_STEP_COUNTER
private var lastUpdate: Long = 0
private var delay: Int = 0
enum class SensorType(val type: String) {
COUNTER("COUNTER"),
DETECTOR("DETECTOR");
companion object {
fun fromString(value: String): SensorType? = values().find { it.type == value }
}
}
fun start(delay: Int, sensorType: SensorType) {
this.delay = delay
this.sensorType = if (sensorType == SensorType.COUNTER) Sensor.TYPE_STEP_COUNTER else Sensor.TYPE_STEP_DETECTOR
stepCounterSensor = sensorManager.getDefaultSensor(this.sensorType)
stepCounterSensor?.let {
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_FASTEST)
}
}
fun stop() {
sensorManager.unregisterListener(this)
}
private fun sendEvent(eventName: String, params: WritableMap?) {
try {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit(eventName, params)
} catch (e: RuntimeException) {
Log.e("ERROR", "Trying to invoke JS before CatalystInstance has been set!", e)
}
}
override fun onSensorChanged(event: SensorEvent?) {
event?.let {
if (it.sensor.type == sensorType) {
val curTime = System.currentTimeMillis()
if (curTime - lastUpdate > delay) {
val map: WritableMap = Arguments.createMap()
map.putDouble("steps", it.values[0].toDouble())
sendEvent("StepCounter", map)
lastUpdate = curTime
}
}
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// Not used
}
}
# RnSensorStepModule.kt
package com.sensor.step
import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Build
import androidx.annotation.RequiresApi
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.sensor.step.RnSensorStepListener.SensorType
class RnSensorStepModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private var sensorStepListener: RnSensorStepListener? = null
@RequiresApi(Build.VERSION_CODES.M)
@ReactMethod
fun requestSensorPermission() {
val activity: Activity? = currentActivity
val permissions = arrayOf(Manifest.permission.ACTIVITY_RECOGNITION)
activity?.requestPermissions(permissions, 0)
}
@RequiresApi(Build.VERSION_CODES.M)
@ReactMethod
fun checkSensorPermission(promise: Promise) {
val permissionGranted = reactContext.checkSelfPermission(Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED
promise.resolve(permissionGranted)
}
@ReactMethod
fun start(delay: Int, sensorType: String) {
if (sensorStepListener == null) {
sensorStepListener = RnSensorStepListener(reactContext)
}
val type = SensorType.fromString(sensorType) ?: SensorType.COUNTER
sensorStepListener?.start(delay, type)
}
@ReactMethod
fun stop() {
sensorStepListener?.stop()
}
@ReactMethod
fun addListener(eventName: String) {
// NativeEventEmitter와의 호환을 위한 더미 메서드
}
@ReactMethod
fun removeListeners(count: Int) {
// NativeEventEmitter와의 호환을 위한 더미 메서드
}
override fun getName(): String {
return "RnSensorStep"
}
}
# RnSensorStepPackage.kt
package com.sensor.step
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class RnSensorStepPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(RnSensorStepModule(reactContext))
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}