I have a program that reads and writes all the sensors values file, but when you turn off the screen stops the listener on the sensors and the record on txt file.
I already tried with the wake lock, but with little success, I want to know if you have ideas or if I have to resort to a wake to keep me always on the monitor, let me know.
thanks
Solved?
Try onResume and LocationListener
You better should use a Service for listening to the sensors. I did so with my Sports Tracker app and ist works fine.
At least the GPS system (LocationManager.requestLocationUpdates) is working with a wakelock when the screen is turned off. I don't know about the other sensors. (you tagged GPS with your question)
Related
I've searched for many answers, posts and articles about getting sensor data even when the screen was off, and most of them suggested to try and use a PARTIAL_WAKE_LOCK. I read the documentation, and from what I've understood, all it said was needed to do was to call:
val wakeLock: PowerManager.WakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag").apply {
acquire()
}
}
I did this in the onCreate method of the activity that should trigger the wakelock, and I made sure that when the activity is closed the wakelock is released.
My goal is to let the user turn off the screen while in this activity that has a foreground service:
startService(Intent(this, ForegroundService::class.java))
that picks up data from the linear acceleration sensor. Currently though, the partial wakelock does not seem to do anything. As soon as the screen is turned off, the data from the sensor is stopped (as Android would normally do without a wakelock).
It is important that my foreground service analizes the sensor data continuously (so I don't think sensor batching could work for me), and that the user can turn the screen off (all the code works when the screen is on).
Any ideas on how to make this work?
Edit: The service does not stop when the screen is turned off. All the other tasks that the service has to do are correctly done. And that worked without the PARTIAL_WAKELOCK too. It’s just that Android stops getting sensor updates although I have added the Wakelock. That’s the issue.
I'm making an app that keeps track of how many times the user uses their phone, meaning how many times they picked up/checked their phone everyday. I've searched through stackoverflow and other sites but I can't find any information that would help me implement this; any ideas? Is there a certain class I can use?
Use BroadcastService and IntentFilter to keep track of when the screen is turned on and off (ACTION_SCREEN_ON and ACTION_SCREEN_OFF). Each time the screen is turned on, increase a counter.
You could register for the ACTION_SCREEN_ON broadcast. Then just increment a counter (saved to disk just in case) each time its received. But you can't do that via the manifest, so you'd need to do it in a foreground service.
When the battery on my Android device dies what methods in the Activity and Fragment classes (if any) are called during the "Powering Off" stage of the device?
Also, if a user is currently looking at a screen in my app and they hold the power button and choose switch off, do the events called/not called coincide with when the battery is depleted and shuts down automatically?
OnPause?
OnStop?
OnDestroy?
OnDetach?
Bonus:
Will I have enough time to save a small amount of data to a web server?
To clarify "dies" when the device's battery is 'completely' dead, accepts no more input and a message box/loading screen pops up on the screen stating "Powering Off". Shortly there after the device switches off.
I just need enough time to save a forms state before the phone switches off, I have a strategy to clean the saved data should the phone not switch off, but I want to get as close to the phone switching off as possible (any more than a minute is pointless really).
onDestroy is called on everything when the battery reaches 0.5%
EDIT: There is no specified time that you have to do anything in the shutdown process resulting from low/dead battery, that would be dependent on the specific phone battery and not the system, so you may have enough time to save data to a web server on some phones but not others. Experimentally, I have only been able to write a short line to a file I was already writing to before onDestroy was called and nothing more.
The methods you have mentioned is activity life cycle callback, none of them will be called when battery is low. You need to use a broadcast receiver for this
See this How to detect when the Battery's low : Android?
I need to alert the user of certain events by means of:
Vibration
Notification
The vibration should remain on indefinitely until the user ACKs the notification.
The problem is vibration stops when the device goes to sleep. I've read the following questions:
Allow phone to vibrate when screen turns off
Continue vibration even after the screen goes to sleep mode in Android
There was an answer to one of the above mentioned questions saying that vibrating without patterns did the trick. So I've tried calling the version of Vibrator.vibrate that accepts milliseconds instead of a pattern with a large number but the vibration stops anyway.
Other answers suggest to register a receiver on the ACTION_SCREEN_OFF action. This would allow me to resume vibration if the device goes to sleep after the alarm has started, but won't work if the device was already slept.
However, I could get the thing working if I were able to turn the screen on first, then register the receiver to deal with any screen off event that could happen from there on. So I've tried acquiring a full wake lock when the triggering event is received, before starting sound or vibration, but it does not work despite I'm using the flags FULL_WAKE_LOCK and ACQUIRE_CAUSES_WAKEUP. The wakeup part works, but soon after that the device goes to sleep again. I would like to think the FULL_WAKE_LOCK flag does not work because it has been deprecated in API 17, but my device is a Samsung running 4.1.2 which is API 16!
The recommended approach now seems to be using
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON but this should be called from an activity, and I don't have any screen up unless the user clicks in the notification, and if this happens the sound and vibration should already have been stopped.
So it looks like a dead-end.
What else could I try?
UPDATE:
I had no luck keeping the screen always on with wake locks, but on the other hand they allow me to turn the screen on if only for a few seconds. I actually don't need to keep the screen on, so I'm registering the receiver on the Intent.ACTION_SCREEN_OFF action, and when the screen goes off, the receiver resumes vibration again. This worked well in the Samsung, but I've now switched to a Huawei to continue testing and the receiver does not work.
UPDATE:
Here's the stack trace of the exception in the Huawei device:
java.util.NoSuchElementException: Death link does not exist
at android.os.BinderProxy.unlinkToDeath(Native Method)
at com.android.server.VibratorService.unlinkVibration(VibratorService.java:294)
at com.android.server.VibratorService.removeVibrationLocked(VibratorService.java:284)
at com.android.server.VibratorService.cancelVibrate(VibratorService.java:213)
at android.os.IVibratorService$Stub.onTransact(IVibratorService.java:83)
at android.os.Binder.execTransact(Binder.java:338)
at dalvik.system.NativeStart.run(Native Method)
Do you intend to let the device go to sleep or not? You can acquire a wakelock that wakes the screen on.
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "myTAG");
wl.acquire(LOCK_SCREEN_TIME_MINUTES * 60 * 1000);
That doesn't work for you?
After that you can show the notification, but I'm not sure of the effect, will it hold the vibrations. Above one works on GalaxyTab 2 with android 4.2.2 and HTC Hero with android 2.3.4.
After some testing I finally managed to get it working.
The Vibrator class hass two methods:
vibrate (long[] pattern, int repeat)
vibrate (long milliseconds)
The first one is the only way of vibrating indefinitely using the API (passing 0 as the second argument). But this has been proven to break in some devices (Huawei), as I posted in the question. I'm not talking about the vibration being stopped by the OS when the device goes to sleep, this had been dealt with using a receiver plus a wake lock as described in the question. I'm talking about exceptions, caused by a bugged implementation (the Vibrator class is abstract).
The second variant of this method does not accept a pattern, and does not allow indefinite vibration, but we can cheat this by passing a very large number of milliseconds as parameter. This works well in some devices (Huawei) as the answer I cited in the question correctly pointed, but does not work in others (Samsung), where the implementation has a default max value that will be used instead if the value passed as parameter exceeds it. This max value is actually less than a minute, and this means we can't rely on this approach.
So I went all out on this and created a Service, where I manually vibrate indefinitely like this:
while(vibrationActive){
Vibrator.vibrate(1000);
Thread.sleep(1000);
}
The receiver trick to detect when the screen goes off is no longer needed. Of course the OS keeps shutting down the vibrator when this happens, but the next iteration of the loop will resume vibration again. With this approach it is possible to create a sort of pattern as well, if the sleep time is greater than the vibration time, but again this pattern will be interrupted at any point if the screen goes off.
A dedicated service just to turn the vibrator on and off reliably. Can you believe it? About 150 lines of code (without the unit tests) for something that should have been possible with a few lines.
Disclaimer: My app already working without any Wake Locks for 1+ year and all is well for most devices.
I'm tracking GPS and it works like this:
AlarmReceiver starts Service every 5/10/15 minutes (as user wishes)
Service subscribes for Location updates and waits MAX 1 minute for good GPS.
Wrap up, send data to server and shut down service.
Due to bad connections and bad locations - whole thing take up to 2-3 minutes sometimes. And it works. No matter if phone is sleeping or not.
Now I'm reading about WakeLock and it doesn't make sense to me. How come my stuff is working? Is that coincidence?
How come my stuff is working?
A combination of things, including a dollop of luck. :-)
First, as Joel noted, the device wakes up briefly courtesy of your alarm, but the OS is only guaranteed to hold a WakeLock for the duration of onReceive() of a BroadcastReceiver.
It is possible that, at least on some versions of Android, requesting GPS updates causes the OS to acquire its own WakeLock. This is undocumented behavior AFAIK, and I have never relied upon it personally. If it does, though, and you are doing the rest of your work ("Wrap up, send data to server and shut down service") before removing location updates, that would explain the behavior.
There are still potential gaps in your approach (e.g., if you delegate to a Service to do the work and are not holding a WakeLock as part of passing control to that service). Statistically speaking, it may fail occasionally but work a lot of the time.
Personally, I recommend using a WakeLock, in case the undocumented behavior changes. That's what I do in LocationPoller.
Well reading from the AlarmManager documentation..
The Alarm Manager holds a CPU wake lock as long as the alarm
receiver's onReceive() method is executing.
Further...
Note: The Alarm Manager is intended for cases where you want to have
your application code run at a specific time, even if your application
is not currently running. For normal timing operations (ticks,
timeouts, etc) it is easier and much more efficient to use Handler.
So based on that.. I think it makes sense that it currently works; correct me if I'm wrong.