0

I'm making an android wear application, and the main functionality is in the ConnectionService class, which basically handles communication with a websocket. My problem is, that if I quit the application with the buttons on my android wear device, there is no error, everything runs as expected in the background. But if I do a left swipe, quitting the application to the menu, then the application crashes (as far as I know in this case the onDestroy method is running. So I'm getting the following error:

Activity com.example.adambodnar.canary.MainActivity has leaked ServiceConnection com.example.adambodnar.canary.MainActivity$4@79552f9 that was originally bound here android.app.ServiceConnectionLeaked: Activity com.example.adambodnar.canary.MainActivity has leaked ServiceConnection com.example.adambodnar.canary.MainActivity$4@79552f9 that was originally bound here

I have read a lot of questions about this, but I couldn't find a solution matching my problem. The service is running in the background as a foreground service, so I don't want to stop it from running.

Here is the MainActivity.class

public class MainActivity extends FragmentActivity {

    private static ConnectionService mService;
    private boolean mBound = false;
    private final FragmentManager supportFragmentManager = getSupportFragmentManager();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        supportFragmentManager.beginTransaction().replace(R.id.fragment_container, new MainFragment()).commit();
        if(!PermissionHelper.hasPermissions(this, Constants.PERMISSIONS)){
            ActivityCompat.requestPermissions(this, Constants.PERMISSIONS, Constants.PERMISSION_ALL);
        }

        Intent intent = new Intent(this, ConnectionService.class);
        this.startService(intent);
        this.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mConnection = new ServiceConnection() {

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

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    public static void sendMessage(String message) {
        mService.sendMessage(message);
    }

    public static void rebuildWebSocketConnection() {
        mService.rebuildWebSocketConnection();
    }
}

And my ConnectionService:

public class ConnectionService extends Service {

    private WebSocketHelper webSocketHelper = new WebSocketHelper();
    private final String TAG = "ConnectionService";
    private final IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        public ConnectionService getServiceInstance() {
            return ConnectionService.this;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "SERVICE IS BINDED");
        return mBinder;
    }

    @Override
    public void onCreate() {
        System.out.println("ON CREATE OF CONNECTION SERVICE");
        super.onCreate();
        Intent notificationIntent = new Intent(this, MainActivity.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

        Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("My Awesome App")
                .setContentText("Doing some work...")
                .setContentIntent(pendingIntent).build();

        startForeground(1337, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "--- Connection Service onStartCommand ---");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    public void sendMessage(String message) {
        Log.d(TAG, "WebSocketHelper is open: " + webSocketHelper.isWebSocketOpen());
        if (webSocketHelper.isWebSocketOpen()) {
            Log.i(TAG, "--- WebSocket Message: " + message + " ---");
            webSocketHelper.sendMessage(message);
        }
    }
}

So what should I do to make this error disappear?

adamb
  • 793
  • 1
  • 11
  • 20

2 Answers2

0

You should put on onDestroy method the unbinding Service:

@Override
public void onDestroy(){
    super.onDestroy();
    this.unbindService(mConnection);
}
0

Activity com.example.adambodnar.canary.MainActivity has leaked ServiceConnection com.example.adambodnar.canary.MainActivity$4@79552f9 that was originally bound here android.app.ServiceConnectionLeaked: Activity com.example.adambodnar.canary.MainActivity has leaked ServiceConnection com.example.adambodnar.canary.MainActivity$4@79552f9 that was originally bound here

basically onStop you should unbind services.

@Override
    protected void onStop() {
        super.onStop();
        unbindService(mConnection);
    }
Sush
  • 3,864
  • 2
  • 17
  • 35
  • wouldn't this stop the Service from running in the background? – adamb Nov 29 '18 at 15:18
  • Nope. It will unbind. It wont stop the running service only you will lose the service_connection that is connected. Stop service is the separate call. @adamb – Sush Nov 29 '18 at 15:28
  • So Im maybe over abusing my MainActivity, but for me it kills the behaviour of my application. Im using the MainActivity to create alarms when certain SMS message arrives, and I'm loosing all of this functionality if I'm unbinding the service, or quitting with the left swipe – adamb Nov 29 '18 at 15:46
  • Then i must say you have to spend some more time on architecture design, better you use broadcast listeners, observers patterns or bind services in required activities.. make sure release every thing in onstop. In this way will have functionality keep working. suggestion - make one base class activity and extend it wherever required. – Sush Nov 30 '18 at 05:33