Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android foreground service slow if device is idle

I have an android foreground service, called with the notification. In the service Im just logging every 10 seconds "Tick tack", but the priority of the service is navigate in a webview every X seconds, so Im using new threads and working in the main thread too.

If I have the app connected to the usb the logs seems ok, the "tick tack" is called every 10 seconds, same if the mobile is unlocked and Im wathing the logs on the app.

But when I disconnect the usb, or I lock the device this is what is happening:

2018-11-14 12:11:53.115 12596-12596/? I/Service: tick tack
2018-11-14 12:12:18.704 12596-12596/? I/Service: tick tack
2018-11-14 12:15:42.572 12596-12596/? I/Service: tick tack
2018-11-14 12:17:30.942 12596-12596/? I/Service: tick tack
2018-11-14 12:17:53.534 12596-12596/? I/Service: tick tack
2018-11-14 12:18:27.118 12596-12596/? I/Service: tick tack
2018-11-14 12:18:37.118 12596-12596/? I/Service: tick tack
2018-11-14 12:18:47.118 12596-12596/? I/Service: tick tack
2018-11-14 12:18:57.121 12596-12596/? I/Service: tick tack
2018-11-14 12:19:25.208 12596-12596/? I/Service: tick tack
2018-11-14 12:19:48.294 12596-12596/? I/Service: tick tack

What is the limit of foreground services? Can I do hard foreground work even the device is idle?

like image 424
Pablo Cegarra Avatar asked Nov 14 '18 11:11

Pablo Cegarra


People also ask

What are the limitations of a foreground service in Android?

When your app starts a foreground service while the app is running in the background, the foreground service has the following limitations: Unless the user has granted the ACCESS_BACKGROUND_LOCATION permission to your app, the foreground service cannot access location.

What is a short-running foreground service on Android?

Devices that run Android 12 (API level 31) or higher provide a streamlined experience for short-running foreground services. On these devices, the system waits 10 seconds before showing the notification associated with a foreground service. There are a few exceptions; several types of services always display a notification immediately.

What happens to apps when the device is idle?

When the user plugs the device into a power supply, the system releases apps from the standby state, allowing them to freely access the network and to execute any pending jobs and syncs. If the device is idle for long periods of time, the system allows idle apps network access around once a day.

Can apps that target Android 12 start foreground services while running?

Apps that target Android 12 can no longer start foreground services while running in the background, except for a few special cases.


1 Answers

I have made this library the other day for something similar service in background and foreground

And its working absolutely fine with no problems.

The reason I choose to run it with AlarmManager is that the AlarmManager is a great candidate for scheduling if an application needs to perform a local event + allows an application to schedule tasks that may need to run or repeat beyond the scope of its lifecycle. This allows the application to perform some function even after the application process or all of its Android components have been cleaned up by the system.

UPDATE

Call this method to start the service

 public void call(int Value_in_seconds) {
        if (Value_in_seconds == (int) Value_in_seconds) {
            // Number is integer
            Long time = new GregorianCalendar().getTimeInMillis() + Value_in_seconds * 1000;
            // create an Intent and set the class which will execute when Alarm triggers, here
            // ServiceReciever in the Intent, the onRecieve() method of this class will execute when
            // alarm triggers
            Intent intentAlarm = new Intent(context, ServiceReciever.class);
            // create the object
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            //set the alarm for particular time
            alarmManager.set(AlarmManager.RTC_WAKEUP, time, PendingIntent.getBroadcast(context, 1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
        } else {
            Toast.makeText(context,  context.getString(R.string.intValue), Toast.LENGTH_SHORT).show();
        }
    }

Create ServiceReciever Class

public class ServiceReciever extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //call the method here

    }
}

inside your manifest

<application>
<receiver android:name="hossamscott.com.github.backgroundservice.ServiceReciever" android:process=":ff" android:exported="true" android:enabled="true">
</receiver>

<service android:name="hossamscott.com.github.backgroundservice.BackgroundTask"/>

</application>

And thats should be it, tho if you like to run it in Thread Than you can add the next lines

public class BackgroundTask extends Service {

    private boolean isRunning;
    private Context context;
    private Thread backgroundThread;


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        this.context = this;
        this.isRunning = false;
        this.backgroundThread = new Thread(myTask);
    }

    private Runnable myTask = new Runnable() {
        public void run() {
            // Do something here
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    // do your logic here
                }
            });
            stopSelf();
        }
    };

    @Override
    public void onDestroy() {
        this.isRunning = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (!this.isRunning) {
            this.isRunning = true;
            this.backgroundThread.start();
        }
        return START_STICKY;
    }

}

And to call this class edit ServiceReciever to be like this

 @Override
    public void onReceive(Context context, Intent intent) {
        //call the method here
        Intent background = new Intent(context, BackgroundTask.class);
        context.startService(background);
    }
like image 58
Hossam Hassan Avatar answered Oct 25 '22 18:10

Hossam Hassan