I am having a problem where my service is being killed even though I am holding a wake lock and I have called startForeground. When this occurs the tablet (ASUS Transformer TF101), stops the service without calling onDestroy. There are no other apps visible, and log cat shows nothing out of the ordinary (no 'out of memory' message etc). Immediately after being killed, the service restarts.
The app I am developing is a chat client and needs a constant connection, it is also plugin based, so my app is developed as such: Client - HostService - Multiple child 'Services'.
The host service is sticky holds the wake lock and calls startForeground (and displays a notification as such), the child services are not sticky, do not hold wake locks and are background services.
If the client itself is open the issue does not occur, but the model I am going for is that the user can use the device and stay connected (receiving messages etc) without having the client itself open at all times.
Can anybody offer any explanation as to why the service is being killed in this way, and if so prevent it from happening? As the chat clients show when a user logs on and off, and the service dying kills all open connections, this makes the chat client 'bounce'. At present it seems to happen somewhere between every 15 and 45 minutes.
Also, if anybody is aware of a way to keep a socket connection open continuously without holding a wake lock for the entire connection duration, I would love to hear it!
The trimmed test case version of the host service source is below.
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 (relevant bits):
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="11" />
<service android:name="com.mydomain.chatClient.server.HostService" android:exported="true" android:enabled="true" android:process=":remote"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />