在保持唤醒锁定和调用startForeground之后服务被杀死

即使我持有唤醒锁并且我已经调用了startForeground ,我遇到的问题是我的服务被杀死了。 当平板电脑(华硕Transformer TF101)发生这种情况时, 停止服务而不调用onDestroy 。 没有其他应用程序可见,log cat显示任何不寻常的内容(没有’内存不足’消息等)。 被杀后,服务立即重新启动。

我正在开发的应用程序是一个聊天客户端,需要一个持续的连接,它也是基于插件的,所以我的应用程序是这样开发的:客户端 – HostService – 多个子’服务’。

主机服务是粘滞的,持有唤醒锁并调用startForeground(并显示通知),子服务不粘,不保持唤醒锁并且是后台服务。

如果客户端本身是打开的,则问题不会发生,但我要使用的模型是用户可以使用该设备并保持连接(接收消息等),而无需始终打开客户端本身。

任何人都可以提供任何解释为什么服务以这种方式被杀死,如果是这样,防止它发生? 当聊天客户端显示用户登录和注销时,并且服务死亡会终止所有打开的连接,这会使聊天客户端“反弹”。 目前,它似乎发生在每15到45分钟之间。

此外,如果有人知道如何在没有整个连接持续时间的唤醒锁的情况下持续打开套接字连接,我很乐意听到它!

主机服务源的修剪测试用例版本如下。

public class HostService extends Service { PowerManager m_powerManager = null; PowerManager.WakeLock m_wakeLock = null; @Override public IBinder onBind( Intent intent ) { return m_serviceImplementation; } @Override public void onCreate() { super.onCreate(); } @Override public void onDestroy() { if( m_wakeLock != null ) { m_wakeLock.release(); m_wakeLock = null; } stopForeground( true ); super.onDestroy(); } @Override public int onStartCommand( Intent intent, int flags, int startId ) { // Display a notification about us starting. We put an icon in the // status bar. Notification notification = createNotification(); startForeground( R.string.service_running, notification ); if( m_powerManager == null ) { m_powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE); } if( m_wakeLock == null ) { m_wakeLock = m_powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Keep background services running"); m_wakeLock.acquire(); } // We want this service to continue running until it is explicitly // stopped, so return sticky. return START_STICKY; } /** * Create a notification to show the service is running */ private Notification createNotification() { CharSequence text = getText( R.string.service_running ); CharSequence title = getText( R.string.app_name ); // The PendingIntent to launch our activity if the user selects this // notification PendingIntent contentIntent = PendingIntent.getActivity( this, 0, new Intent(this, MainChat.class) , 0 ); Notification notification = new Notification( android.R.drawable.sym_action_chat, title, System.currentTimeMillis() ); notification.setLatestEventInfo( this, title, text, contentIntent ); return notification; } private final IMessageInterface.Stub m_serviceImplementation = new IMessageInterface.Stub() { ... }; } 

Android Manifest(相关位):

    

即使我持有唤醒锁并且我已经调用了startForeground,我遇到的问题是我的服务被杀死了。

startForeground()降低了服务被杀死的可能性,但它并没有阻止它。

我正在开发的应用程序是一个聊天客户端,需要一个持续的连接,它也是基于插件的,所以我的应用程序是这样开发的:客户端 – HostService – 多个子’服务’。

我建议摆脱其中一个层。 即使操作系统没有关闭您,许多用户也会(例如,任务杀手,在设置中运行服务),考虑到您运行太多服务。

如果客户端本身是打开的,则问题不会发生,但我要使用的模型是用户可以使用该设备并保持连接(接收消息等),而无需始终打开客户端本身。

我建议选择这个。 你可能认为这很性感。 您的一些用户会因为浪费电池而攻击您。

任何人都可以提供任何解释为什么服务以这种方式被杀死,如果是这样,防止它发生?

我开始摆脱android:process=":remote" 。 你不需要它。 你不想要它。 你可能因为拥有它而伤害自己,因为它可能加速Android对摆脱你的服务的兴趣。 你绝对会因为拥有它而伤害用户,因为你没有充分的理由浪费内存。

然后,如果你将它们作为单独的应用程序实现,我将摆脱插件。 在这种情况下,每个都将在自己的进程中运行,浪费更多的RAM。 此外,您当前的实现将是有缺陷的,因为您不会将您的服务命名为com.mydomain.chatClient.server.HostService直到时间结束,因为您没有使用来分离关注点“内部命名的服务”和“其他希望使用它的单独安装的应用程序调用的服务”。 如果你没有将插件作为单独的应用程序实现,那么我没有看到将它们放在单独的服务中的价值,而不是将它们全部折叠到一个服务中。

此外,如果有人知道如何在没有整个连接持续时间的唤醒锁的情况下持续打开套接字连接,我很乐意听到它!

如果套接字是使用无线数据而不是WiFi,则不需要一直使用WakeLock 。 套接字将保持打开状态,该套接字上的传入数据包将唤醒您的代码。 此时,您需要获取一个WakeLock足够长的时间,以便您在数据到达时执行任何操作,然后释放WakeLock

但是,如果你使用WiFi,这个技巧不起作用,因此需要一个WakeLock (可能还有一个WifiLock )。