You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何控制SQLite数据库中移动传感器数据的记录频率?

问题分析与解决方案

核心问题在于所有传感器共用同一个记录时间戳,导致只要有一个传感器触发记录,其他传感器会立刻满足时间间隔条件,进而频繁写入数据库。再加上SENSOR_DELAY_NORMAL本身采样频率较高(约20-50Hz),叠加逻辑缺陷后产生了大量冗余数据。

修复后的代码

package com.example.sensorsapp

import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

// 为每个传感器维护独立的记录状态
data class SensorRecordState(
    var lastRecordTime: Long = 0,
    var lastX: Float = 0f,
    var lastY: Float = 0f,
    var lastZ: Float = 0f
)

class MainActivity : AppCompatActivity(), SensorEventListener {

    private lateinit var sensorManager: SensorManager
    private lateinit var accelerometer: Sensor
    private lateinit var gyroscope: Sensor
    private lateinit var gravity: Sensor
    private lateinit var proximity: Sensor
    private lateinit var orientation: Sensor
    private lateinit var rotationVector: Sensor
    private lateinit var linearAcceleration: Sensor
    private lateinit var dbHelper: MyDatabaseHelper
    private lateinit var db: SQLiteDatabase
    private lateinit var readingTextView: TextView
    private lateinit var gyroscopeTextView: TextView
    private lateinit var gravityTextView: TextView
    private lateinit var proximityTextView: TextView
    private lateinit var orientationTextView: TextView
    private lateinit var rotationVectorTextView: TextView
    private lateinit var linearAccelerationTextView: TextView
    private lateinit var startStopButton: Button
    private var isRecording = false

    // 每个传感器独立的记录状态
    private val sensorRecordStates = mutableMapOf<Int, SensorRecordState>()
    private val recordInterval = 75000L // 初始设为75秒,可按需调整
    private val deltaThreshold = 1.0f // 数据变化阈值,避免小波动触发记录

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化UI元素
        readingTextView = findViewById(R.id.readingTextView)
        startStopButton = findViewById(R.id.startStopButton)
        gyroscopeTextView = findViewById(R.id.gyroscopeTextView)
        gravityTextView = findViewById(R.id.gravityTextView)
        proximityTextView = findViewById(R.id.proximityTextView)
        orientationTextView = findViewById(R.id.orientationTextView)
        rotationVectorTextView = findViewById(R.id.rotationVectorTextView)
        linearAccelerationTextView = findViewById(R.id.linearAccelerationTextView)

        // 初始化数据库
        dbHelper = MyDatabaseHelper(this)
        db = dbHelper.writableDatabase

        // 初始化传感器
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
        gravity = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
        proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
        orientation = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION)
        rotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
        linearAcceleration = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)

        // 注册传感器,使用更低采样频率减少回调次数
        val sensorDelay = SensorManager.SENSOR_DELAY_UI // 约60Hz,比NORMAL频率更低
        accelerometer?.let { sensorManager.registerListener(this, it, sensorDelay) }
        gyroscope?.let { sensorManager.registerListener(this, it, sensorDelay) }
        gravity?.let { sensorManager.registerListener(this, it, sensorDelay) }
        proximity?.let { sensorManager.registerListener(this, it, sensorDelay) }
        orientation?.let { sensorManager.registerListener(this, it, sensorDelay) }
        rotationVector?.let { sensorManager.registerListener(this, it, sensorDelay) }
        linearAcceleration?.let { sensorManager.registerListener(this, it, sensorDelay) }

        startStopButton.setOnClickListener {
            isRecording = !isRecording
            startStopButton.text = if (isRecording) "停止记录" else "开始记录"
        }
    }

    override fun onSensorChanged(event: SensorEvent?) {
        if (event == null || !isRecording) return

        val currentTime = System.currentTimeMillis()
        val sensorType = event.sensor.type
        val x = event.values[0]
        val y = event.values[1]
        val z = event.values[2]

        // 获取当前传感器的记录状态,不存在则初始化
        val state = sensorRecordStates.getOrPut(sensorType) { SensorRecordState() }

        // 判断是否需要记录:时间间隔达标 或 数据变化超过阈值
        val shouldRecord = if (currentTime - state.lastRecordTime >= recordInterval) {
            true
        } else {
            Math.abs(x - state.lastX) >= deltaThreshold ||
            Math.abs(y - state.lastY) >= deltaThreshold ||
            Math.abs(z - state.lastZ) >= deltaThreshold
        }

        if (shouldRecord) {
            recordSensorData(event.sensor, x, y, z)
            // 更新当前传感器的记录状态
            state.apply {
                lastRecordTime = currentTime
                lastX = x
                lastY = y
                lastZ = z
            }
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}

    private fun recordSensorData(sensor: Sensor, xValue: Float, yValue: Float, zValue: Float) {
        val sensorName = sensor.getStringType()
        val values = ContentValues().apply {
            put(MyDatabaseHelper.TIMESTAMP, System.currentTimeMillis())
            put(MyDatabaseHelper.SENSOR_NAME, sensorName)
            put(MyDatabaseHelper.X_VALUE, xValue)
            put(MyDatabaseHelper.Y_VALUE, yValue)
            put(MyDatabaseHelper.Z_VALUE, zValue)
        }
        db.insert(MyDatabaseHelper.TABLE_NAME, null, values)
    }

    override fun onDestroy() {
        super.onDestroy()
        sensorManager.unregisterListener(this)
        db.close()
    }
}

// 补充数据库Helper类(原代码未给出,确保完整性)
class MyDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "SensorData.db", null, 1) {
    companion object {
        const val TABLE_NAME = "sensor_readings"
        const val TIMESTAMP = "timestamp"
        const val SENSOR_NAME = "sensor_name"
        const val X_VALUE = "x_value"
        const val Y_VALUE = "y_value"
        const val Z_VALUE = "z_value"
    }

    override fun onCreate(db: SQLiteDatabase) {
        val createTable = """
            CREATE TABLE $TABLE_NAME (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                $TIMESTAMP INTEGER,
                $SENSOR_NAME TEXT,
                $X_VALUE REAL,
                $Y_VALUE REAL,
                $Z_VALUE REAL
            )
        """.trimIndent()
        db.execSQL(createTable)
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL("DROP TABLE IF EXISTS $TABLE_NAME")
        onCreate(db)
    }
}

关键修改点

  • 独立传感器状态管理:用SensorRecordState类为每个传感器维护独立的最后记录时间和历史值,避免全局时间戳导致的连锁记录。
  • 降低采样频率:将传感器延迟从SENSOR_DELAY_NORMAL改为SENSOR_DELAY_UI,减少回调次数,降低不必要的计算。
  • 优化记录判断逻辑:每个传感器单独判断是否满足时间间隔或数据变化阈值,避免不同传感器互相干扰。
  • 可配置参数:recordInterval和deltaThreshold设为可调整变量,方便根据需求微调记录密度。

数据量控制建议

要达到一周6000-8000条记录的目标:

  • 按7天=10080分钟计算,目标8000条则平均每条记录间隔约1.26分钟(75秒),对应代码中recordInterval = 75000L。
  • 若某些传感器(如距离传感器)变化频率低,可单独为其设置更长的记录间隔。
  • 微调deltaThreshold值,避免微小波动触发额外记录。

内容的提问来源于stack exchange,提问作者Nosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:44:54