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

Android熄屏状态下持续获取Sensor与GNSS数据的实现问题咨询

解决方案

1. 将普通Service改为前台服务(核心修改)

Android 10+ 长时间后台运行的任务必须使用前台服务,系统会为运行前台服务的进程提权,减少被后台查杀的概率。

步骤1:添加权限

在AndroidManifest.xml中添加以下权限:

<!-- 前台服务基础权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 10+ 后台采集位置所需权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- 唤醒锁权限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

运行时权限申请除了原有的ACCESS_FINE_LOCATION,还要新增ACCESS_BACKGROUND_LOCATION,必须引导用户同意「始终允许位置访问」,否则熄屏后GNSS数据会被系统截断。

步骤2:启动时绑定前台通知

修改DataCollectorService的onStartCommand方法,启动服务时调用startForeground绑定常驻通知:

@RequiresApi(api = Build.VERSION_CODES.R)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // 注册前台服务通知渠道
    String CHANNEL_ID = "sensor_collect_service";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(
                CHANNEL_ID,
                "传感器数据采集",
                NotificationManager.IMPORTANCE_HIGH
        );
        channel.setSound(null, null);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);
    }
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("正在采集传感器/GNSS数据")
            .setContentText("关闭该通知会导致采集中断")
            .setSmallIcon(R.mipmap.ic_launcher) // 替换为你的应用图标
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setCategory(Notification.CATEGORY_SERVICE)
            .build();
    // 启动前台服务,通知ID不能为0
    startForeground(1001, notification);
    
    // 原有逻辑补充参数持久化,避免进程重启后参数丢失
    SharedPreferences sp = getSharedPreferences("collect_config", MODE_PRIVATE);
    if (intent != null) {
        appStartTime = intent.getLongExtra("startTime", 0);
        samplingFrequency = intent.getIntExtra("samplingFrequency", 10000);
        meanOfTrans = intent.getIntExtra("meanOfTrans", 0);
        // 存储参数到本地
        sp.edit()
                .putLong("startTime", appStartTime)
                .putInt("samplingFrequency", samplingFrequency)
                .putInt("meanOfTrans", meanOfTrans)
                .apply();
    } else {
        // 进程被系统杀掉重启时从本地读取参数
        appStartTime = sp.getLong("startTime", System.currentTimeMillis());
        samplingFrequency = sp.getInt("samplingFrequency", 10000);
        meanOfTrans = sp.getInt("meanOfTrans", 0);
    }
    
    if (initial) {
        registerSensors();
        // WakeLock移到Service中作为成员变量持有,不要放在Activity中
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DLR_KN_MOBILITY_APP:SERVICE_WAKE_LOCK");
        mWakeLock.acquire(150 * 60 * 1000L); // 150分钟,单位为毫秒
        initial = false;
    }
    return START_STICKY;
}

步骤3:修改服务启动方式

Android 8及以上版本启动前台服务需要调用startForegroundService,修改MainActivity的toggleBackgroundService方法:

if (on) {
    Intent serviceIntent = new Intent(this, DataCollectorService.class);
    serviceIntent.putExtra("startTime", appStartTime);
    serviceIntent.putExtra("samplingFrequency", samplingFrequency);
    serviceIntent.putExtra("meanOfTrans", meanOfTrans);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(serviceIntent);
    } else {
        startService(serviceIntent);
    }
}

步骤4:服务销毁时清理资源

修改DataCollectorService的onDestroy方法,释放资源:

@Override
public void onDestroy() {
    super.onDestroy();
    stopForeground(true);
    // 释放WakeLock
    if (mWakeLock != null && mWakeLock.isHeld()) {
        mWakeLock.release();
    }
    unregisterReceiver(mReceiver);
    disableSensors();
}

2. 优化传感器回调逻辑

为传感器回调指定独立的工作线程,避免主线程被系统挂起导致回调中断:

// 在registerSensors方法中新增以下代码
HandlerThread sensorThread = new HandlerThread("sensorCallbackThread");
sensorThread.start();
Handler sensorHandler = new Handler(sensorThread.getLooper());
// 注册传感器时传入handler
if (mAccelerometer != null) {
    mSensorManager.registerListener(this, mAccelerometer, samplingFrequency, sensorHandler);
}
// 其余传感器注册逻辑同理,都传入该handler

3. 厂商定制系统适配

你测试的机型中POCO属于小米系,有额外的后台限制,需要引导用户手动开启权限:

  • 小米/POCO:进入应用信息页,开启「自启动权限」,将省电策略设置为「无限制」
  • 三星:进入电池优化设置,将应用加入「不优化」列表
  • 原生Pixel:仅需开启前台服务和后台位置权限即可正常运行
    按照以上方案修改后,可实现熄屏状态下连续数小时的稳定数据采集,覆盖你需要的多场景测试需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 18:45:08