前台服务在执行互联网相关操作时被杀死

Posted

技术标签:

【中文标题】前台服务在执行互联网相关操作时被杀死【英文标题】:Foreground service gets killed on performing internet related operations 【发布时间】:2017-01-18 14:07:22 【问题描述】:

更新:以前我找不到关于我的前台服务何时被终止的明确模式。在对发生这种情况的设备进行更多调试(并非所有设备上都发生)后,我发现。

1.) 很多时候,当我打开 chrome 加载网站时,前台服务会被终止。有时即使我在使用 whatsapp 也会发生这种情况。

2.) 没有异常,堆栈跟踪没有显示任何有用的信息。

原始问题如下:

*** 上有很多这样的问题,但到目前为止,我阅读的大部分答案都说这取决于 android,我们不能 100% 保证前台服务不会被杀死。一些答案建议使用 START_STICKY ,但这对我来说没有多大帮助。

就我而言,我有一个具有前台服务的音乐播放器应用程序。该服务在某些设备上被终止,主要是某些版本的小米(Android 版本为 5.1.1)。 现在我知道android可能内存不足,所以我的前台服务被杀死了,但是为什么其他音乐播放器应用程序从来没有经历过这样的终止。他们做对了我做错了什么?

我使用startForeground 进行了服务前台服务。此外,我在 onStartCommand 中返回 START_STICKY,尽管这无济于事,因为如果被杀死,服务会在 4-5 秒后重新启动。要将我的服务与我的活动绑定,我使用

bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT );

那么我究竟可以在我的应用中改进/更改什么来防止这种情况发生,如果其他应用正常工作,那么我的情况肯定有问题。有人可以帮忙吗。提前致谢!!

编辑:

这就是我调用 startForeground() 的方式

public void sendNotification() 

        Intent notIntent = new Intent(this, MainActivity.class);
        notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendInt = PendingIntent.getActivity(this, 0,
                notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        Bitmap bitmap = null;
        if (!notificationShowing || !forwarded) 
            Log.i(TAG, "present");
            String title = CommonUtils.getSongFromID(songIndex, this);

            bigView.setTextViewText(R.id.title, title);
            bigView.setImageViewBitmap(R.id.img, bitmap);

            smallView.setTextViewText(R.id.title1, title);
            smallView.setImageViewBitmap(R.id.img1, bitmap);

            if (pauseButton == 1) 
                bigView.setImageViewResource(R.id.pause, R.drawable.pause_noti);
                smallView.setImageViewResource(R.id.pause1, R.drawable.pause_noti);
             else 
                bigView.setImageViewResource(R.id.pause, R.drawable.play_noti);
                smallView.setImageViewResource(R.id.pause1, R.drawable.play_noti);
            

            musicNotification = builder.setContentIntent(pendInt)
                    .setSmallIcon(R.drawable.logo1)
                    .setTicker(songTitle)
                    .setOngoing(true)
                    .setContentTitle("Playing")
                    .setStyle(new Notification.BigTextStyle().bigText("Song App"))
                    .setContentText(songTitle)
                    .setPriority(Notification.PRIORITY_MAX)
                    .build();

            musicNotification.contentView = smallView;
            musicNotification.bigContentView = bigView;

            musicNotification.contentIntent = pendInt;

            Intent switchIntent = new Intent("pause");
            switchIntent.putExtra("button", "pause");
            PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 100, switchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            bigView.setOnClickPendingIntent(R.id.pause, pendingSwitchIntent);
            smallView.setOnClickPendingIntent(R.id.pause1, pendingSwitchIntent);

            Intent switchIntent1 = new Intent("forward");
            switchIntent1.putExtra("button", "forward");
            PendingIntent pendingSwitchIntent2 = PendingIntent.getBroadcast(this, 100, switchIntent1, PendingIntent.FLAG_UPDATE_CURRENT);
            bigView.setOnClickPendingIntent(R.id.forward, pendingSwitchIntent2);
            smallView.setOnClickPendingIntent(R.id.forward1, pendingSwitchIntent2);

            Intent switchIntent2 = new Intent("previous");
            switchIntent2.putExtra("button", "previous");
            PendingIntent pendingSwitchIntent3 = PendingIntent.getBroadcast(this, 100, switchIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
            bigView.setOnClickPendingIntent(R.id.previous, pendingSwitchIntent3);
            smallView.setOnClickPendingIntent(R.id.previous1, pendingSwitchIntent3);

            Intent switchIntent3 = new Intent("end");
            switchIntent3.putExtra("button", "end");
            PendingIntent pendingSwitchIntent4 = PendingIntent.getBroadcast(this, 100, switchIntent3, PendingIntent.FLAG_UPDATE_CURRENT);
            bigView.setOnClickPendingIntent(R.id.end, pendingSwitchIntent4);
            smallView.setOnClickPendingIntent(R.id.end1, pendingSwitchIntent4);

            startForeground(NOTIFY_ID, musicNotification);
            notificationShowing = true;
        
        forwarded = false;

    

【问题讨论】:

你能说明你是如何调用 startForeground() 当您的前台服务被终止时,您是否注意到任何特定模式?例如:当您打开另一个音乐播放器应用程序或当您打开 youtube 等时? @AADTechnical 不,没有特定的模式,即使我只是自己保留它,它也会在一段时间后停止 @ucsunil 感谢您的回复,我已添加代码!谢谢 检查'onTrimMemory'是否被调用? 【参考方案1】:

小米手机出现这种情况,原因如下。

MIUI 7.0 解决方案 => 安全 => 自动启动 => 选择要在后台运行的应用程序 => 重启 重启后,您的设备应该能够像其他安卓设备一样在后台运行您的应用程序服务。

MIUI 4.0 settings

MIUI AutoStart Detailed Description

如果您正在寻找其他手机,请检查这里是服务结构。它会自动重启,但当您重启手机时会调用 BootReceiver。

public class AppService extends Service 

private class LocalBinder extends Binder 
    public AppService getServerInstance() 

        return AppService.this;
    



@Override
public IBinder onBind(Intent intent) 
    return mBinder;



@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    // If we get killed, after returning from here, restart

    return Service.START_STICKY;


@Override
public void onCreate() 
    super.onCreate();

 

@Override
public void onDestroy() 




谢谢,希望对你有帮助。

【讨论】:

感谢您的回答队友,看起来这将解决它,我会测试一下并奖励赏金。非常感谢,我讨厌小米!! 是的,我也讨厌,我花了很多时间专门在小米检查这些东西。 昨天运行良好,但今天又开始停止 :( 什么是开始停止?服务? 是的,伙计!昨天还好好的,今天又停了!!【参考方案2】:

此服务在某些设备上被终止,主要是某些版本的 小米(安卓版本为5.1.1)

不确定,但据我了解,这可能是因为

    供应商的操作系统定制存在错误。 Android 中有关优先处理前台服务的错误,这些错误由服务绑定标志的各种组合(即 BIND_AUTO_CREATE、BIND_IMPORTANT 等)触发。阅读 Robin Davies 的this 回答。

我不知道你是否使用startService()。但如果你不这样做,那么按照这个documentation:

您可以创建一个已启动和绑定的服务。那就是 可以通过调用startService() 来启动服务,这允许 服务无限期地运行,并且还允许客户端绑定到 通过调用bindService() 来服务。(这称为绑定到已启动的服务

如果您确实允许启动和绑定您的服务,那么当 服务已启动,系统不销毁服务时 所有客户端解除绑定。相反,您必须通过以下方式显式停止服务 致电stopSelf()stopService()

虽然您通常应该实现 onBind() 或 onStartCommand(),有时需要同时实现两者。为了 例如,音乐播放器可能会发现允许其服务 无限期运行并提供绑定。这样,一个活动可以 启动服务播放一些音乐,音乐继续播放 即使用户离开应用程序。然后,当用户返回 到应用程序,活动可以绑定到服务重新获得 播放控制。

请务必阅读有关Managing the Lifecycle of a Bound Service 的部分,以了解有关将绑定到已启动服务时的服务生命周期的更多信息。

onStartCommand 将在服务启动的情况下被调用,因此START_STICKY 将仅在startService() 的情况下工作。

进程日志更新

过程 #5:prcp F/S/IF trm:0 22407:com.wave.music.player/u0a2 (fg-服务)

在您的进程中记录您在前台运行的播放器服务,并设置了 adj 设置 prcp (visible foreground service),这意味着它几乎是坚不可摧的。您的服务仍然被操作系统破坏,但运行新启动的应用程序的可用内存可能非常低。按照这个documentation,

系统中只会有几个前台进程,而这些 只有在内存太低以至于连 这些进程可以继续运行。一般来说,此时, 设备已达到内存分页状态,因此需要此操作 为了保持用户界面响应。

所以我认为你没有做错任何事。我只是想建议您阅读this 官方Android 开发人员文档并尝试在单独的进程中运行您的服务(文档建议音乐播放器应用程序采用这种方法)。请小心执行此操作,因为如果操作不正确,它很容易增加(而不是减少)您的 RAM 占用空间。

【讨论】:

感谢您花时间回答。我正在使用 startService() 并将我的活动绑定到我的服务。由于这在我测试过的大多数设备(包括 Google Nexus)上运行良好,我认为这可能是由于小米的操作系统自定义错误。我猜其他优秀的音乐应用程序可能已经明确处理了这个问题。另外我应该补充一点,这种杀戮只有在应用程序最小化/进入后台时才会发生。你认为发生这种情况后它的优先级会发生变化,这就是它被杀死的原因吗?谢谢你的回答!! 是的,可能是这样。在内存不足的情况下,低优先级进程很容易被操作系统杀死。只是一个想法,尝试在绑定服务中使用 Context.BIND_ABOVE_CLIENT 标志可能会对您有所帮助。 嘿,发生错误的设备是我朋友的。我从他那里得到了设备并进行了测试以查看问题。有一些观察 1.) 如果我使用其他应用程序,服务更有可能被杀死。我使用了whatsapp和chrome。有时它会在我打开 chrome 时立即崩溃,但有时它需要一些时间。 2.)stacktrace 中没有错误或任何其他 imp 信息。 3.)我也使用了 R Davies 所说的 sysDump,尽管我没有发现任何异常。我已将其附加在编辑中。你能根据这些想出任何问题吗?我真的很感激任何帮助。谢谢!! 抱歉编辑太大了,这是系统转储结果jpst.it/Nmgz我的应用是com.wave.music.player 好的...我会检查并让您知道是否找到任何东西...您是否检查了 BIND_ABOVE_CLIENT 标志?

以上是关于前台服务在执行互联网相关操作时被杀死的主要内容,如果未能解决你的问题,请参考以下文章

数据库中间件(上)

QProcess::startDetached shell 在父进程死亡时被杀死,如果父进程是一个 systemd 服务

一段时间后,前台服务被Android杀死

如何杀死前台服务

互联网相关原理

5G时代:IDC互联网数据中心与分布式存储