如何实现手机熄屏休眠时仍可正常触发onSensorChanged()回调
安卓加速度传感器后台运行修复方案
你遇到的熄屏后传感器监听停止的核心原因有两个:一是当前监听逻辑绑定了Activity生命周期,熄屏后Activity进入后台优先级被降低甚至被挂起;二是Android原生及厂商定制的省电策略会限制后台应用的传感器访问权限。
1. 调整现有Activity的传感器注销逻辑
首先移除onPause()方法里的传感器注销代码,改为只在Activity销毁时再注销:
// 删除onPause里的mSensorManager?.unregisterListener(this)逻辑 override fun onDestroy() { super.onDestroy() // 仅在页面销毁时注销监听 mSensorManager?.unregisterListener(this) }
2. 用前台服务托管传感器监听逻辑(核心修改)
Activity的后台存活优先级极低,需要把传感器注册、数据处理逻辑全部移到前台服务中运行,前台服务会展示常驻通知,系统会给它更高的存活权限,不会被随意杀死:
- 第一步,在
AndroidManifest.xml中添加权限和服务声明:
<!-- 基础权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- 可选:防止系统休眠导致监听中断 --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application ...> <service android:name=".AccelMonitorService" android:foregroundServiceType="dataSync" /> </application>
- 第二步,创建前台服务类实现传感器监听:
class AccelMonitorService : Service(), SensorEventListener { private lateinit var mSensorManager: SensorManager private var mAccelerometer: Sensor? = null override fun onCreate() { super.onCreate() mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION) // 注册传感器,可选添加唤醒标志保证休眠时也能触发回调 mSensorManager.registerListener( this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL, // 不需要休眠时触发的话可以删掉下面这个参数,降低功耗 SensorManager.SENSOR_FLAG_WAKE_UP ) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // Android 8.0+要求创建通知通道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "accel_monitor_channel", "加速度监测服务", NotificationManager.IMPORTANCE_LOW ) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } // 构建前台服务通知 val notification = NotificationCompat.Builder(this, "accel_monitor_channel") .setContentTitle("加速度监测中") .setContentText("后台正在检测手机加速度数据") .setSmallIcon(R.drawable.ic_app_icon) // 替换为你应用的图标资源 .build() // 启动前台服务,ID不能为0 startForeground(1001, notification) // 服务被杀死后自动重启 return START_STICKY } override fun onSensorChanged(event: SensorEvent?) { // 把你原来的加速度计算、最大值统计逻辑写在这里 } override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} override fun onDestroy() { super.onDestroy() mSensorManager.unregisterListener(this) } override fun onBind(intent: Intent?): IBinder? = null }
- 第三步,在Activity中启动服务:
val serviceIntent = Intent(this, AccelMonitorService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent) } else { startService(serviceIntent) }
3. 绕过厂商省电限制(适配国产ROM)
小米、华为、vivo等国产ROM有定制的省电策略,你可以引导用户手动将应用加入省电白名单:
// 跳转到系统省电优化页面 val intent = Intent(android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) startActivity(intent)
内容的提问来源于stack exchange,提问作者Enrico Cortinovis
相关产品推荐
相关产品推荐

