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

时间:2016-09-10 16:35:43

标签: android android-service

更新:以前我找不到一个定义良好的模式,以确定我的前台服务何时被杀死。经过对设备的更多调试(不会发生这种情况)我发现了。

1。)很多时候,当我打开chrome加载网站时,前台服务被杀死了。有时甚至在我使用whatsapp时也会发生这种情况。

2。)没有例外,堆栈跟踪没有显示任何有用的内容。

以下原始问题:

StackOverflow上有很多这样的问题,但到目前为止,我读过的答案主要是说它取决于Android,我们没有100%保证前台服务不会被杀死。一些答案建议START_STICKY,但这对我的情况没有多大帮助。

在我的情况下,我有一个有前台服务的音乐播放器应用程序。这项服务在某些设备上被杀死,主要是Xiomi的某些版本(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;

    }

2 个答案:

答案 0 :(得分:7)

由于以下原因,这发生在 Xiomi 手机中。

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

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() {

}

}

谢谢希望这会对你有所帮助。

答案 1 :(得分:1)

  

此服务在某些设备上被杀死,主要是某些版本的设备   Xiomi(Android版本为5.1.1)

不确定这一点,但根据我的理解,这可能是因为

  1. 来自供应商的操作系统自定义错误。
  2. Android中关于优先处理前台服务的错误,由服务绑定标志的各种组合(即BIND_AUTO_CREATE,BIND_IMPORTANT等)触发。阅读Robin Davies的this回答。
  3. 我不知道您是否使用startService()。但是,如果你不这样做documentation

      

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

         

    如果您确实允许您的服务启动和绑定,那么当   服务已经启动,系统在不破坏服务的时候   所有客户解开。相反,您必须明确停止服务   致电stopSelf()stopService()

         

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

    有关将绑定添加到已启动服务时的服务生命周期的详细信息,请务必阅读有关Managing the Lifecycle of a Bound Service的部分。

    如果已启动服务,则会调用

    onStartCommand,因此START_STICKY仅适用于startService()

    处理日志更新

      

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

    在你的过程中记录你的播放器服务在前台运行,调整设置为prcp (visible foreground service),这意味着它几乎是坚不可摧的。操作系统仍然破坏了您的服务,而不是可用于运行新启动应用程序的内存非常低。根据{{​​3}},

      

    系统中只会有一些前台进程,以及这些进程   如果记忆力太低而且不均匀,那么它只会作为最后的手段被杀死   这些过程可以继续运行。一般来说,此时,   设备已达到内存分页状态,因此需要执行此操作   为了保持用户界面的响应。

    所以我认为你没有做错任何事。我只是建议您阅读documentation官方Android开发人员文档,并尝试在单独的过程中运行您的服务(文档建议这种方法用于音乐播放器应用程序)。小心实现这一点,因为它可以轻松增加 - 而不是减少 - 如果做错了你的RAM足迹。