Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceConnectionLeaked in Android

Tags:

I'm attempting to use a Service in Android for some basic database operations, but for some reason I'm getting an Activity has leaked ServiceConnection error. I'll post the full Logcat readout at the bottom.

I have to use the same service in multiple activities, so I've created a Superclass to handle all of the service tasks. It looks like this:

private MyInterface child;

public void onCreate(Bundle savedInstanceState, MyInterface child){
    super.onCreate(savedInstanceState);

    doBindService();
}

public void onResume(){
    super.onResume();

    doBindService();
}

protected void onPause(){
    super.onPause();

    doUnbindService();
}

private boolean bound;
private boolean binding;

ServiceConnection Connection = new ServiceConnection(){

    //called when the service is connected
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(LOGTAG, "Bound to Service");
        bound = true;
        binding = false;
        toServiceMessenger = new Messenger(service);
        while(!commandsForService.isEmpty()){
            sendToService(commandsForService.poll());
        }
    }

    //called when the service is disconnected
    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(LOGTAG, "Unboud from Service");
        bound = false;
        binding = false;
        toServiceMessenger = null;
    }
};

private boolean doBindService(){
    Log.d(LOGTAG, "Attempting to Bind to Service");
    if(!bound && !binding){
        binding = true;
        bindService(new Intent(this, global.FetchService.class), Connection, Context.BIND_AUTO_CREATE);
    }
    return bound;
}

private void doUnbindService(){
    Log.d(LOGTAG, "Attempting to Unbind from Service");
    if(bound && !binding){
        binding = true;
        unbindService(Connection);
    }
}

public void sendToService(Message msg){
    if(bound){
        sendMessageToService(msg);
    }
    else{
        commandsForService.add(msg);
    }
}

private void sendMessageToService(Message msg){
    if(bound){
        msg.replyTo = fromServiceMessenger;
        try {
            toServiceMessenger.send(msg);
        } catch (RemoteException e) {
            Log.d(LOGTAG, "RemoteException communicating with service");
        }
    }
    else{
        Log.d(LOGTAG, "Error: toServiceMessenger null while bound");
    }
}

The idea is that the child activity will never need to worry about being connected to the service or not, the Superclass should take care of getting data the service and back to the child.

The Logcat points doBindService() in onCreate() --> bindService(new Intent(this, global.FetchService.class), Connection, Context.BIND_AUTO_CREATE); as the line causing the error. However, the service only leaks after the activity has been running and visible for longer than 15 seconds, so I don't think that onCreate() should have been called.

Here's the Logcat:

09-02 09:25:40.635: E/ActivityThread(5963): Activity childActivity has leaked ServiceConnection superClass$1@42cb1b70 that was originally bound here
09-02 09:25:40.635: E/ActivityThread(5963): android.app.ServiceConnectionLeaked: Activity childActivity has leaked ServiceConnection superClass$1@42cb1b70 that was originally bound here
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1055)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:949)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ContextImpl.bindService(ContextImpl.java:1472)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ContextImpl.bindService(ContextImpl.java:1464)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.content.ContextWrapper.bindService(ContextWrapper.java:394)
09-02 09:25:40.635: E/ActivityThread(5963):     at superClass.doBindService(FetchActivity.java:253)
09-02 09:25:40.635: E/ActivityThread(5963):     at superClass.onCreate(FetchActivity.java:61)
09-02 09:25:40.635: E/ActivityThread(5963):     at childActivity.onCreate(Showcase_Activity.java:37)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.Activity.performCreate(Activity.java:5066)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.access$600(ActivityThread.java:151)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.os.Looper.loop(Looper.java:155)
09-02 09:25:40.635: E/ActivityThread(5963):     at android.app.ActivityThread.main(ActivityThread.java:5493)
09-02 09:25:40.635: E/ActivityThread(5963):     at java.lang.reflect.Method.invokeNative(Native Method)
09-02 09:25:40.635: E/ActivityThread(5963):     at java.lang.reflect.Method.invoke(Method.java:511)
09-02 09:25:40.635: E/ActivityThread(5963):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
09-02 09:25:40.635: E/ActivityThread(5963):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
09-02 09:25:40.635: E/ActivityThread(5963):     at dalvik.system.NativeStart.main(Native Method)

Any help will be greatly appreciated.

like image 961
MrMannWood Avatar asked Sep 02 '13 14:09

MrMannWood


2 Answers

As you call the doBindService() in the onCreate(), you should add the do UnbindService() in onDestroy().

It works for me.

like image 63
BinqiangSun Avatar answered Oct 13 '22 17:10

BinqiangSun


You're calling doBindService() in both onCreate() and onResume(), trying calling it just in onResume() to match your call to doUnbindService() in onPause()

like image 25
bclymer Avatar answered Oct 13 '22 18:10

bclymer