bgs-core icon indicating copy to clipboard operation
bgs-core copied to clipboard

Timer is not stable ? Timer did not work when the app paused

Open hellojinjie opened this issue 11 years ago • 14 comments

Hi,

I create a service named CoreService using bgs-core I enable the timer using 'enableTimer(50 * 1000);' The timer worked fine when the app is open. When the app go to background, the CoreService is still running in the background, but the timer did not work.

Why you choose Timer to schedule task? Will AlarmManager be a better chooice when CoreService running in background?

tkx

hellojinjie avatar Jan 26 '15 08:01 hellojinjie

What happens when you watch the logcat?

Generally when I'm told that the service isn't running, it is one of two problems:

  1. Developer is trying to JavaScript - this won't work as the JavaScript needs the app to open. All logic needs to be written in Java
  2. There is a bug in the user code. To check, add log.d() statements through the doWork() and custom code or run in debug mode.

Red-Folder avatar Jan 26 '15 19:01 Red-Folder

Thank you for your quick reply, I am trying to debug my APP.

hellojinjie avatar Jan 27 '15 01:01 hellojinjie

I am having the exact same problem. My reason for trying this plugin is to solve the problem of having a timer run in the background when the phone is unplugged and the screen is off. Logcat is deceiving because to use it you need to have your device plugged in. If the device is plugged in and i turn the screen off, the timer works just fine. But as soon as you unplug the device the timer doesn't run anymore.

ronaldjeremy avatar Jan 30 '15 23:01 ronaldjeremy

Maybe the problem is that the CPU goes to sleep when the screen is off i.e when the app is in background.

Android puts its CPU to sleep when there are no WakeLocks.

I had this problem and solved it by acquiring WakeLock when the CPU has to perform work in background.

private PowerManager.WakeLock wl = null;
.
.
.
@Override
    protected void onTimerEnabled() {
        if (wl == null) {
            if (loggingOn)Log.d("WakeLock", "Creating and acquiring wake lock...");
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            this.wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "doWork()");
            wl.setReferenceCounted(false);
            if (!wl.isHeld()) {
                wl.acquire();
                Log.i("WakeLock", "Acquired wake lock!");
            }
        } else {
            if (!wl.isHeld()) {
                if (loggingOn) Log.d("WakeLock", "Wake lock not held...Acquiring wake lock...");
                wl.acquire();
            }
        }

    }


 @Override
    protected void onTimerDisabled() {
        //Release wakelock
        releaseWakeLock();
    }
.
.
.
//Release wake lock should be called whenever you have completed your work
private void releaseWakeLock() {

        if (wl != null) {
            if(loggingOn)Log.i("WakeLock", "wl is not null");
            if (wl.isHeld()) {
                if (loggingOn)
                    Log.i("WakeLock", "We have a wake lock....Releasing wake lock...");
                wl.release();
            }
        }
    }

Do not forget to release the WakeLock when you are done with your work. Hope this helps.

mithiljadhav avatar Jan 31 '15 04:01 mithiljadhav

@mithiljadhav Your solution need to keep the cpu lock awake all the time. Will this consumer too much battery powner ?

hellojinjie avatar Feb 02 '15 00:02 hellojinjie

@ronaldjeremy I'd have a look at some form of logging solution - something that will write a log to file or database - which you can then retrieve later. I'm sure google search will find one. I'd be surprised that your code runs differently between cabled and not (unless it is using specific cabled resources like network).

Red-Folder avatar Feb 02 '15 18:02 Red-Folder

@mithiljadhav's solution worked perfectly! That must have been the problem, thanks!

@Red-Folder, as far as a logging solution, i found one. I simply plug the device back in and it will spit out the accumulated logs while disconnected to logcat (in android studio).

without @mithiljadhav's fix, there are no log entries from my app for the period of time the screen is off and device is unplugged. Everything is frozen. when i turn the screen on (device unplugged) the log entries get written to the buffer that logcat will spit out when plugged back in.

This is on a galaxy note 3 running android 4.4.4

ronaldjeremy avatar Feb 02 '15 22:02 ronaldjeremy

@mithiljadhav I tried your solution in my app. But the app consumer too much battery life.

hellojinjie avatar Feb 09 '15 06:02 hellojinjie

@hellojinjie Sorry for late reply.

In my case, the timer needs to run every second as long as the app is running. So basically, when the user finishes the task, the timer stops. Generally the timer is used for few minutes to 20 minutes.

In your case, you run the timer every 50 seconds. Probably, the above fix would not be right for you, since keeping the CPU awake when no work is being done will obviously drain battery.

I think AlarmManager would be a better choice if you want to perform a task after 50 seconds.

mithiljadhav avatar Feb 09 '15 06:02 mithiljadhav

@mithiljadhav

Ohh, I see. In my case the timer is used for a very long time. As long as the phone is on.

I will try AlarmManager,

Thank you for your reply.

hellojinjie avatar Feb 09 '15 07:02 hellojinjie

This may be related to KitKat bug (https://code.google.com/p/android/issues/detail?id=63793) - although notes say that this should work for 4.4.4

Maybe because I not using START_STICKY - see (https://github.com/Red-Folder/bgs-core/issues/9)

Once I've completed the above, I'll re-review the scheduler/ AlarmManager setup

Red-Folder avatar Mar 17 '15 13:03 Red-Folder

I too had a problem with the timer running only once after phone reboot (using registerForBootStart with BOOT_COMPLETED) and then not running anymore. This happened only when phone was not connected to PC via USB - the probably PC forced the phone to be awaken (which I realized afterwards)... I use Samsung J5 (J500) with Android 5.1.1.

@mithiljadhav Your solution works great - thanks a lot!!! :) I dont mind the battery drain since my Android phone (used as telemetry unit) will be powered from the grid all the time...

@Red-Folder Thanks for the great plugin! However the timer surely is not 100% reliable as we can see - especially the use of Timer and TimerTask for the timer itself is not well suited for "mission critical" applications (well whole Android is not) - I read that AlarmManager should be more reliable, but I did not investigate that... Have you thought about trying to implement AlarmManager within the plugin?

kozuch avatar May 09 '16 15:05 kozuch

@kozuch

I think AlarmManager has been implemented by others (have a look through the issues). It has been a while since I've touched this project so I'm struggling to remember if I've tried on not.

Unfortunately I don't have the environment/ time/ inclination to do much more with this project at the moment. Feel free to fork the code and have a go. Let us know how you get on.

I would however make a small comment on "mission critical"; If you have a really critical app then I'd personally avoid Codova. I've always found that Cordova is for that 1 step beyond a HTML web app. The minute you want to get more advanced then you want to me looking at going fully native (or the middle ground tools like Xamarin or NativeScript). Its a personal opinion from someone that doesn't work much in the space - so feel free to take it or leave it ;)

Red-Folder avatar May 11 '16 10:05 Red-Folder

@Red-Folder Thanks for reply. I did not know AlarmManager would already be implemented - I will look around. I agree on your "mission critical" opinion - my app is actually far from such "critical" application, but I meant it rather as general comment touching on the "reliability" of various things on Andrlid (as said the whole Android platform is not suited for critical applications).

kozuch avatar May 12 '16 15:05 kozuch