调用stopService()后Foreground Service仍持续运行的问题排查
Foreground Service 停止问题排查
我查阅Android官方文档关于Foreground Service的说明:
调用
stopForeground()可将服务移出前台,该方法的布尔参数控制是否移除状态栏通知,但服务会继续运行;若在前台运行时停止服务,仅通知会被移除。
这是否意味着无法完全停止服务,需由系统处理?还是需要手动操作?我调用stopService(intent)方法停止服务,但通知移除后服务仍在运行。
Logcat中出现警告:
W/System: A resource failed to call close.该信息无法提供足够排障线索。
我的Service实现代码
public class MyService extends Service { RemoteViews custom; NotificationManager notificationmanager; Notification notification; IBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); notificationmanager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); Notification_Channel(this); startForeground(2,Show_notification(this)); } public class MyBinder extends Binder { MyService getService() { return MyService.this; } } @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { String action = intent.getAction(); if(action!=null) { switch (action) { case "stop": stopService(intent); stopSelf(); break; } } return START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); } @RequiresApi(api = Build.VERSION_CODES.S) public void Notification_Channel (Context context) { //creating channel String offerchannelname = "..."; String offerchanneldescription = "..."; int offerchannel_importance = NotificationManager.IMPORTANCE_LOW; NotificationChannel notifchannel = new NotificationChannel( offerchannelid, offerchannelname,offerchannel_importance); notifchannel.setDescription(offerchanneldescription); // disable sound notifchannel.setSound(null,null); notificationmanager.createNotificationChannel(notifchannel); // using custom Layout custom = new RemoteViews(context.getPackageName(),R.layout.audio_player_notification); Show_notification(context); } @RequiresApi(api = Build.VERSION_CODES.S) public Notification Show_notification(Context context) { PendingIntent pendingIntent; Intent clickIntent = new Intent("action1"); pendingIntent = PendingIntent.getBroadcast(context,3, clickIntent, PendingIntent.FLAG_IMMUTABLE| PendingIntent.FLAG_UPDATE_CURRENT); custom.setOnClickPendingIntent(R.id.MyId,pendingIntent); Intent clickIntent2 = new Intent("action2"); pendingIntent = PendingIntent.getBroadcast(context,4, clickIntent2,PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); custom.setOnClickPendingIntent(R.id.myId_player,pendingIntent); Intent clickIntent3 = new Intent("action3"); pendingIntent = PendingIntent.getBroadcast(context,5, clickIntent3,PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); custom.setOnClickPendingIntent(R.id.myid,pendingIntent); Intent open_intent = new Intent(context,Main_Page.class); open_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); pendingIntent= PendingIntent.getActivity(context.getApplicationContext(),0,open_intent,PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); return notification=new NotificationCompat.Builder(context,channel_id) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true) .setContentIntent(pendingIntent) .setStyle(new NotificationCompat.DecoratedCustomViewStyle()) .setCustomContentView(custom) .setSmallIcon(R.drawable.ic_launcher_foreground) .build(); } }
启动服务的代码
Intent service_intent = new Intent(context,MyService.class); ContextCompat.startForegroundService(context,service_intent); context.bindService(service_intent, this,Context.BIND_AUTO_CREATE);
停止服务的代码
Intent service_intent = new Intent(context,MyService.class); service_intent.setAction("stop"); ContextCompat.startForegroundService(context,service_intent); context.unbindService(service_intent,this);
问题原因与修复方案
核心问题
- 绑定未正确解除:启动服务时同时调用了
bindService,绑定服务会让服务生命周期与绑定组件绑定,仅调用stopService/stopSelf无法终止服务,必须先解绑。 - 停止逻辑错误:
onStartCommand中调用stopService(intent)无效,且未先移除前台状态;停止服务时调用startForegroundService属于多余操作。 - 解绑方式错误:
unbindService需要传入绑定用的ServiceConnection实例,而非Intent,当前代码会导致解绑失败。
修复步骤
1. 修正Service内的停止逻辑
@Override public int onStartCommand(Intent intent, int flags, int startId) { String action = intent.getAction(); if(action!=null) { switch (action) { case "stop": // 先移除前台状态和通知 stopForeground(true); // 停止服务 stopSelf(); break; } } return START_NOT_STICKY; }
2. 正确解除绑定
绑定服务时保存ServiceConnection实例:
// 在Activity中定义 private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 处理绑定逻辑 } @Override public void onServiceDisconnected(ComponentName name) { } };
停止时正确解绑:
try { context.unbindService(serviceConnection); } catch (IllegalArgumentException e) { // 避免未绑定时报错 e.printStackTrace(); }
3. 调整停止服务的代码
// 先解绑 try { context.unbindService(serviceConnection); } catch (IllegalArgumentException e) { e.printStackTrace(); } // 直接停止服务 Intent stopIntent = new Intent(context, MyService.class); context.stopService(stopIntent);
4. 完善资源清理
在onDestroy中清理资源,解决resource failed to call close警告:
@Override public void onDestroy() { super.onDestroy(); custom = null; if (notificationmanager != null) { notificationmanager.cancelAll(); notificationmanager = null; } }
关键知识点
- Foreground Service完全停止需要解除所有绑定 + 调用停止方法(
stopService/stopSelf)。 stopForeground(true)仅移除前台状态和通知,服务仍在运行,必须手动停止。- 绑定服务后,只有所有绑定解除且无待处理启动命令时,
onDestroy才会触发。
内容的提问来源于stack exchange,提问作者A.G
相关产品推荐
相关产品推荐

