更新:以前我找不到一个定义良好的模式,以确定我的前台服务何时被杀死。经过对设备的更多调试(不会发生这种情况)我发现了。
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;
}
答案 0 :(得分:7)
由于以下原因,这发生在 Xiomi 手机中。
MIUI 7.0的解决方案=>安全性=>自动启动=>选择要在background =>中运行的应用重新启动强> 重启后,您的设备应该能够像其他Android设备一样在后台运行您的应用程序服务。
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)
不确定这一点,但根据我的理解,这可能是因为
我不知道您是否使用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足迹。