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

Android收音机应用点击返回键后自动关闭,如何修复?

解决Android收音机应用后台运行被强制停止的问题

核心问题分析

你的应用在后台被系统回收,导致MyPlayService的onDestroy()被调用,本质原因是普通后台Service在Android 8.0+系统中优先级极低,容易被系统杀死,同时当前代码没有做前台服务的适配,也存在一些Service逻辑的小问题。

以下是具体修复方案:


一、将Service改为前台服务(关键修复)

Android 8.0(API 26)及以上版本对后台Service有严格限制,必须将播放音频的Service改为前台服务,才能保证后台稳定运行。

修改MyPlayService的onStartCommand方法

添加前台服务通知逻辑:

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import androidx.core.app.NotificationCompat;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    System.out.println("onStartCommand");

    link = intent.getStringExtra("AudioLink");
    mediaPlayer.reset();
    musicStoppedListener = (MusicStoppedListener) ApplicationClass.context;

    // 初始化前台服务通知
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // 创建通知渠道(API26+必须)
        NotificationChannel channel = new NotificationChannel(
                "radio_play_channel",
                "电台播放",
                NotificationManager.IMPORTANCE_LOW
        );
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);

        Notification notification = new NotificationCompat.Builder(this, "radio_play_channel")
                .setContentTitle("Yes Radio 正在播放")
                .setContentText("https://radio.lankayes.lk/8002/stream")
                .setSmallIcon(R.drawable.ic_notification) // 替换为你的通知图标
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .build();
        startForeground(1, notification);
    } else {
        // 适配低版本系统
        Notification notification = new NotificationCompat.Builder(this)
                .setContentTitle("Yes Radio 正在播放")
                .setContentText("https://radio.lankayes.lk/8002/stream")
                .setSmallIcon(R.drawable.ic_notification)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .build();
        startForeground(1, notification);
    }

    if (!mediaPlayer.isPlaying()) {
        try {
            mediaPlayer.setDataSource(link);
            mediaPlayer.prepareAsync();
        } catch (Exception e) {
            Toast.makeText(this, "播放错误:" + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    return START_STICKY;
}

在AndroidManifest.xml中添加权限

<!-- 前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- API33+需要的通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

二、优化onBackPressed方法

保留moveTaskToBack(true)即可,不需要额外启动Home页的Intent,避免不必要的操作:

@Override
public void onBackPressed(){
    System.out.println("onBackPressed");
    // 将应用任务移到后台,Activity不会被销毁
    moveTaskToBack(true);
}

三、修复Service的潜在逻辑问题

  1. 避免重复重置MediaPlayer
    修改onStartCommand,只有当播放链接变化时才重置播放器:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    System.out.println("onStartCommand");

    String newLink = intent.getStringExtra("AudioLink");
    // 仅当链接变化时重置播放器
    if (newLink != null && !newLink.equals(link)) {
        link = newLink;
        mediaPlayer.reset();
        try {
            mediaPlayer.setDataSource(link);
            mediaPlayer.prepareAsync();
        } catch (Exception e) {
            Toast.makeText(this, "播放错误:" + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    // 前台服务通知代码...

    return START_STICKY;
}
  1. 处理MediaPlayer错误,防止Service被系统销毁
    在onError方法中返回true,表示自行处理错误,避免系统终止Service:
@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int i1) {
    System.out.println("onError");
    switch (what) {
        case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
            Toast.makeText(this, "播放格式不支持", Toast.LENGTH_SHORT).show();
            break;
        case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
            Toast.makeText(this, "服务器连接失败", Toast.LENGTH_SHORT).show();
            break;
        case MediaPlayer.MEDIA_ERROR_UNKNOWN:
            Toast.makeText(this, "未知播放错误", Toast.LENGTH_SHORT).show();
            break;
    }
    // 返回true,告诉系统已处理错误,不要销毁Service
    return true;
}

四、优化Service启动方式

在MainActivity的playAudio方法中,适配API26+的前台服务启动要求:

private void playAudio() {
    System.out.println("playAudio");
    serviceIntent.putExtra("AudioLink", stream);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(serviceIntent);
    } else {
        startService(serviceIntent);
    }
}

测试验证

  1. 启动应用,点击播放按钮开始播放电台
  2. 点击返回键,应用退到后台
  3. 观察日志,确认MyPlayService的onDestroy()不会被调用
  4. 检查通知栏是否显示前台服务通知(Android8.0+)

内容的提问来源于stack exchange,提问作者Poorna Senani Gamage

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:20:16