简体   繁体   中英

Service Leaking with onRetainCustomNonConfigurationInstance

Problem
In my Activity, my bound Service leaks. But this only happens after the first screen orientation change. On the second (and following) changes of the screen orientation, the service does not leak. I can't unbind the service in onPause because the Service needs to run in foreground (if you unbind the service, foreground is stopped). Also, after rotation, the service still works (I can still call methods of the service).

Environment
I am developing for midSdkVersion=8 and targetSdkVersion=18 and I am using the SupportActionBar .

Question
Is there a way to prevent the Service to leak? I didn't find anything that helps, yet. Am I missing something?

Code
Relevant parts of MainActivity that extends ActionBarActivity from support library:

AbstractPlayerService mService;
private boolean mBound;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.drawer_layout);

    // Abstract Class that extends Service
    AbstractPlayerService service = (AbstractPlayerService) getLastCustomNonConfigurationInstance();

    if(service != null) { 
        this.mService = service;
        mBound = true;
    }else{
        // init..
    }


@Override
protected void onStart(){
    super.onStart();

    if(!mBound){
        // following line is line 170
        bindService(new Intent(getApplicationContext(), PlayerService.class), mConnection, Context.BIND_AUTO_CREATE);
    }
}


public ServiceConnection mConnection = new ServiceConnection() {

    public void onServiceConnected(ComponentName className, IBinder service) {
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
        mService = null;
    }
};


@Override
public Object onRetainCustomNonConfigurationInstance () {
    return mService;
}

LogCat

11-27 15:42:31.992: E/ActivityThread(25111): Activity de.malaka.player.MainActivity has leaked ServiceConnection de.malaka.player.MainActivity$1@4053fc20 that was originally bound here
11-27 15:42:31.992: E/ActivityThread(25111): android.app.ServiceConnectionLeaked: Activity de.malaka.player.MainActivity has leaked ServiceConnection de.malaka.player.MainActivity$1@4053fc20 that was originally bound here
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:938)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:833)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ContextImpl.bindService(ContextImpl.java:932)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.content.ContextWrapper.bindService(ContextWrapper.java:347)
11-27 15:42:31.992: E/ActivityThread(25111):    at de.malaka.player.MainActivity.onStart(MainActivity.java:170)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.Activity.performStart(Activity.java:3817)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1624)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.os.Looper.loop(Looper.java:130)
11-27 15:42:31.992: E/ActivityThread(25111):    at android.app.ActivityThread.main(ActivityThread.java:3691)
11-27 15:42:31.992: E/ActivityThread(25111):    at java.lang.reflect.Method.invokeNative(Native Method)
11-27 15:42:31.992: E/ActivityThread(25111):    at java.lang.reflect.Method.invoke(Method.java:507)
11-27 15:42:31.992: E/ActivityThread(25111):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
11-27 15:42:31.992: E/ActivityThread(25111):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
11-27 15:42:31.992: E/ActivityThread(25111):    at dalvik.system.NativeStart.main(Native Method)

If you take a look at onRetainCustomNonConfigurationInstance in FragmentActivity source code you'll see that is calls Activity#onRetainNonConfigurationInstance and that method is deprecated since level 13. In your case you can very well remove that method since you're anyway binding in onStart ... and you MUST unbind in onStop :

@Override
protected void onStop() {
    super.onStop();
    unbindService(mConnection);
}

According to Service foreground documentation , there is no direct connection between running a service in the foreground and having it as bounded or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM