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

如何修复使用加速度计的应用在锁屏模式下停止运行的问题?

解决Android锁屏后应用停止运行的问题

嘿,这个问题我之前开发传感器应用时也踩过坑!Android系统在锁屏或者屏幕自动熄灭后,会把后台应用的CPU资源大幅限制,甚至暂停传感器监听和MediaPlayer播放,所以你的应用就直接停了。下面给你两个靠谱的解决方案,结合你的代码来改:

方案一:使用前台服务(最推荐)

前台服务的优先级远高于普通后台服务,系统不会轻易杀死它,而且能持续保持传感器监听和MediaPlayer运行。不过Android 8.0+要求前台服务必须显示一条通知,让用户知道应用在后台运行。

步骤1:创建前台服务类

把你的传感器监听、外力计算和MediaPlayer逻辑移到Service里,这样即使Activity进入后台,服务依然能运行:

public class AccelerometerService extends Service implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor accelerometerSensor;
    private MediaPlayer mediaPlayer;
    private float maxf;

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化传感器
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        // 初始化MediaPlayer(替换成你的MP3文件)
        mediaPlayer = MediaPlayer.create(this, R.raw.your_mp3_resource);
        
        // 创建前台通知(Android 8.0+必须创建通知渠道)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                "accelerometer_channel", 
                "外力检测服务", 
                NotificationManager.IMPORTANCE_LOW
            );
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
        }
        
        Notification notification = new NotificationCompat.Builder(this, "accelerometer_channel")
                .setContentTitle("外力检测运行中")
                .setContentText("正在监听加速度传感器")
                .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标
                .build();
        // 启动前台服务
        startForeground(1, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 注册传感器监听
        sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
        return START_STICKY; // 服务被系统杀死后尝试自动重启
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // 这里写你的外力计算逻辑(和你之前Activity里的逻辑一致)
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];
        float force = (float) Math.sqrt(x*x + y*y + z*z);
        
        if (force > maxf) {
            maxf = force;
            // 触发MP3播放
            if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
                mediaPlayer.start();
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 释放所有资源,避免内存泄漏
        if (sensorManager != null) {
            sensorManager.unregisterListener(this);
        }
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        stopForeground(true); // 移除前台通知
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null; // 如果不需要Activity绑定服务,返回null即可
    }
}

步骤2:在Activity中启动服务

修改你的Activity代码,启动刚才创建的前台服务:

private TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = findViewById(R.id.your_textview_id);
    
    // 启动前台服务
    Intent serviceIntent = new Intent(this, AccelerometerService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(serviceIntent); // Android 8.0+用这个方法
    } else {
        startService(serviceIntent); // 低版本用这个
    }
}

// 可选:当Activity退出时停止服务
@Override
protected void onDestroy() {
    super.onDestroy();
    Intent serviceIntent = new Intent(this, AccelerometerService.class);
    stopService(serviceIntent);
}

步骤3:配置Manifest文件

在AndroidManifest.xml中添加权限和服务声明:

<!-- 前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 如果需要保持CPU唤醒,可选添加 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application ...>
    <!-- 注册服务 -->
    <service android:name=".AccelerometerService" />
</application>

方案二:使用唤醒锁(不推荐,仅作补充)

唤醒锁可以让CPU保持唤醒状态,但在Android 6.0+的Doze模式下可能失效,而且会增加耗电,所以不如前台服务可靠。如果一定要用,可以这样做:

private SensorManager sensorManager;
private Sensor accelerometerSensor;
private MediaPlayer mediaPlayer;
private PowerManager.WakeLock wakeLock;
private float maxf;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = findViewById(R.id.your_textview_id);
    
    // 初始化唤醒锁
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(
        PowerManager.PARTIAL_WAKE_LOCK, 
        "MyApp::AccelerometerWakeLock"
    );
    
    // 初始化传感器和MediaPlayer
    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mediaPlayer = MediaPlayer.create(this, R.raw.your_mp3_resource);
}

@Override
protected void onResume() {
    super.onResume();
    wakeLock.acquire(); // 获取唤醒锁
    sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
}

// 注意:锁屏时Activity会进入onPause,这里不要释放唤醒锁和传感器,否则还是会停
// @Override
// protected void onPause() {
//     super.onPause();
//     wakeLock.release();
//     sensorManager.unregisterListener(this);
// }

@Override
protected void onDestroy() {
    super.onDestroy();
    wakeLock.release(); // 必须释放唤醒锁,否则会一直耗电
    sensorManager.unregisterListener(this);
    mediaPlayer.release();
}

// 你的传感器监听逻辑...
@Override
public void onSensorChanged(SensorEvent event) {
    // 和之前的计算逻辑一致
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}

关键提醒

  • 优先选择前台服务,它能绕过系统的后台限制,稳定性更高
  • 前台服务的通知不能省略,要写清楚应用在做什么,避免用户困惑
  • 记得在不需要服务时及时停止,减少不必要的耗电和内存占用

内容的提问来源于stack exchange,提问作者Kỳ Đoàn Văn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:22:38