androidbackgrounddoze

How to keep internet connection alive for a long time on android?


We are creating internal app which needs to have unkillable or very long living websocket connection. How can I achieve that? I have it working in foreground service, disabled battery optimization etc. but it doesnt seem to work. I tried all standard options.

Command adb shell dumpsys deviceidle whitelist +PACKAGE doesnt seem to help either.

Would rooting phone and setting app as system app help? Are there enterprise Custom ROMs which give control over battery optimizations and other stuff?


Solution

  • You should use a Foreground Service with a partial wakelock, in order to prevent the phone from sleeping. Here below an example of Foreground Service Class that implements a Wakelock:

    public class ICService extends Service {
        
        private static final int ID = 1;                        // The id of the notification
        
        private NotificationCompat.Builder builder;
        private NotificationManager mNotificationManager;
        private PowerManager.WakeLock wakeLock;                 // PARTIAL_WAKELOCK
        
        /**
         * Returns the instance of the service
         */
        public class LocalBinder extends Binder {
            public ICService getServiceInstance(){
                return ICService.this;
            }
        }
        private final IBinder mBinder = new LocalBinder();      // IBinder
        
        @Override
        public void onCreate() {
            super.onCreate();
            // PARTIAL_WAKELOCK
            PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"INSERT_YOUR_APP_NAME:wakelock");
        }
        
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            startForeground(ID, getNotification());
            return START_NOT_STICKY;
        }
        
        @SuppressLint("WakelockTimeout")
        @Override
        public IBinder onBind(Intent intent) {
            if (wakeLock != null && !wakeLock.isHeld()) {
                wakeLock.acquire();
            }
            return mBinder;
        }
        
        @Override
        public void onDestroy() {
            // PARTIAL_WAKELOCK
            if (wakeLock != null && wakeLock.isHeld()) {
                wakeLock.release();
            }
            super.onDestroy();
        }
    
        private Notification getNotification() {
            final String CHANNEL_ID = "YOUR_SERVICE_CHANNEL";
    
            builder = new NotificationCompat.Builder(this, CHANNEL_ID);
            //builder.setSmallIcon(R.drawable.ic_notification_24dp)
            builder.setSmallIcon(R.mipmap.YOUR_RESOURCE_ICON)
                .setColor(getResources().getColor(R.color.colorPrimaryLight))
                .setContentTitle(getString(R.string.app_name))
                .setShowWhen(false)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setCategory(NotificationCompat.CATEGORY_SERVICE)
                .setOngoing(true)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setContentText(composeContentText());
    
            final Intent startIntent = new Intent(getApplicationContext(), ICActivity.class);
            startIntent.setAction(Intent.ACTION_MAIN);
            startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            startIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 1, startIntent, 0);
            builder.setContentIntent(contentIntent);
            return builder.build();
        }
    }
    

    Obviously you still have also to disable battery optimization for your app. You can browse a real working example of this service (but used for GPS) here.