I'm developping an app for Samsung devices with an activity that has to handle a NFC tag..
This activity is called when the app is launched and on resume.
I noticed that, when the phone stays awake with the NFC tag connected to it, after a while the device stops recognizing/scanning for NFC tags.
After trying with some other applications from Play Store, I noticed that this doesn't happen only with my app.
All I can do to make it work again is to switch phone's screen on/off or to switch nfc on/off.
I tried different ways to fix it, as to keep the cpu running, but none of these methods worked :
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag");
wl.acquire();
and
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
The only post about my problem that I found is : onTagDiscovered() not called any more when nfc tag already there after updating from 4.4.4 to 5.1.1 Samsung
Unfortunately, I'm working over non-rooted phones, and I'm not able to get a Samsung Knox licence (unless it is free ?)
Thanks in advance
EDIT
Tried with
setKeepScreenOn(true);
But still no change about this bug
We have an industrial control app that operates in communication with a PC. The app can run on two devices - a Samsung Media Player (like a cellphone without the phone) and a Samsung Galaxy 10.1 tablet.
We had a problem with the CPU and WiFi turning off when the display timed out, which was disrupting communication with the PC. It's OK for the display to go off if the user puts the device down, say, to take a break or go to the bathroom, and it saves battery power, but we want WiFi to still work. So we added . . .
private PowerManager.WakeLock wakelock;
private WifiManager.WifiLock wifilock;
...then, during initialization,
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CPUOnly");
wakelock.acquire();
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifilock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "WifiLock");
wifilock.acquire();
And in the manifest:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
This works on the media player. But the same code on the tablet seems to have no effect - when the display goes out the WiFi also goes out. The media player is running Android 2.3.5 (Gingerbread), and the tablet is running Android 4.0.3 (Ice Cream Sandwich).
Any idea why this would behave differently on these two devices and what we can do to fix it? Thanks in advance!
I'm developing an application for my final thesis on computer science, and I need to collect and log accelerometer data. I need to acquire it for a whole day long, so there are serious battery constraints (for instance, I cannot leave the screen on). Also, this isn't a market targeted application, so it is pretty acceptable to do some serious hacking, even low level C/C++ coding, if required.
It is well known that on many devices the listeners for accelerometer events stop generating events when screen goes off (some links regarding this problem: http://code.google.com/p/android/issues/detail?id=3708 , Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock). I have thoroughly searched for some alternatives, some of them include workarounds that do not work for my device (LG P990, stock ROM).
So what happens is this:
When you register an event listener for android accelerometer sensor in a Service, it works fine until the screen is turned off. I have already tried to register the eventListener on a Service, on an IntentService, tried to acquire WakeLocks. Regarding wakelocks, I can verify that the service is still running watching the LOGcat output, but it seems the accelerometer is put into sleep mode. One of the workarounds presented in some of the links is to unregister and re-register the event listener periodically using the thread of an IntentService like in this code snippet bellow
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic==null) {
PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME);
lockStatic.setReferenceCounted(true);
}
return(lockStatic);
}
#Override
protected void onHandleIntent(Intent intent) {
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.unregisterListener(this);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
synchronized (this) {
boolean run = true;
while (run){
try {
wait(1000);
getLock(AccelerometerService.this).acquire();
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.unregisterListener(this);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
Log.d("Accelerometer service", "tick!");
} catch (Exception e) {
run = false;
Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage());
}
}
}
}
#Override
public void onSensorChanged(SensorEvent event) {
Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," + event.values[2]);
}
which indeed makes the onSensorChange be called every time we unregister/register the listener. The problem is that the event received contains always the same values, regardless of me shaking the device.
So, basically my questions are: ( bear with me, I'm almost finishing :P )
is it possible to have low level access (C/C++ approach) to the accelerometer hardware WITHOUT registering to an event listener?
is there any other workaround or hack?
could anyone with a more up-to-date phone kindly test if the problem persists in firmware 3.0 and above?
[UPDATE]
Unfortunately, it seems to be a bug with some cellphones. More details in my answer.
Basically, it is a problem with my phone. Other users have reported this also happens with their phones, from different brands but same Android version. Other persons have no problem at all - strongly indicating that this is not a problem with the stock version of android but from the implementations of each company for their hardware drivers.
I need constant accelerometer data delivered and cannot have a dongle measure this data for me - I have an Arduino with Bluetooth and accelerometer, so I could have implemented this solution. So I decided that the temporary solution for my cellphone was to let the screen on (dimmed) and ignore battery consumption. Later on I will perform the tests for battery usage using another android phone which works with the screen turned off.
More information about the bug
I've researched some more and found reports from other Android users and I think maybe I understand what is happening. The library libsensors.so which has the drivers for the phone sensors is not developed by Google but by each cellphone vendor - of course, because each cellphone has its own specific hardware. Google only provides a C header file so that the developers know what they have to implement. On some implementations for these drivers, the developers simply turn the accelerometer off when the screen goes off, thus preventing the sensor event listener to receive new events.
I also tested this with CyanogenMod RC7.2 but it did not work either, because accelerometer drivers are original from LG.
E-mails exchanged with HR department of LG
I sent an e-mail to the developers of the LG P990 and finally got some concrete answers! This may be of great help to some people like me that are experiencing these issues with Android. I wrote the following question
Hello! I am developing my thesis in computer science and currently I
am fetching data from accelerometer hardware. As of now, I found out
that the accelerometers do not send events when the screen is off, so
even when I grab a wakelock from within one of my programs, I can
verify that my program is still running (through LOGcat output) but no
accelerometer event comes out. I have to dim my screen on (which I
cannot afford, the battery drains too fast) to start receiving
accelerometer events again. I also tried accessing it through native C
code, registering on the accelerometer events but the result was the
same, the accelerometer did not throw any values, even though I was
rotating my device. So I was wondering if I could have direct access
to the hardware, with native code, without having to register to a
listener. Is this possible? If so, could you kindly give some further
advice? I would appreciate very much any help! Martin
For what I received this response:
Dear Martin, We received the answer from Dev. Team. They said that you
can’t get accelerometer event while your phone screen is off. Because
HAL layer didn’t implement sysFS path to get H/W event such as
accelerometer and there is no public API to get event. Thank you. Best
Regards. (Sean Kim)
I then sent an e-mail back, saying among other things, that I considered this a bug, since one should have access to all the hardware when acquiring a wake lock:
[...] I asked this question because I have some friends that also have
Android phones with the same gingerbread version but from other
cellphone brands, and some of them reported they receive events from
the accelerometers when the screen is turned off. I read on some
forums that this bug - I consider it a bug, since when I acquire a
Wakelock I would expect to have some processing going on - depends on
the sensor drivers that the vendors implement for their cellphones. Is
there any possibility that these drivers can be updated or will this
bug be corrected at some point? This would help me enormously with my
ongoing work [...]
And then I received this answer:
In my knowledge from Dev. Team, That isn’t bug. That is a limitless of
this phone because of H/W architecture. We need to redesign the HAL
architecture and device driver to support your request. But, as you
know that is too difficult due to lack of resource. We are trying to
help you with our all efforts but we cannot support your request as I
mentioned. (Sean Kim)
So they apparently know about this but are not trying to correct this because either they don't think it is a bug - which I still strongly believe is a logical flaw - or they don't have the time/resources to correct it.
Bottom line
If you have a cellphone that does not send accelerometer events with the screen off, try updating your firmware. If this does not solve and you really want to do some serious hacking, re implement your hardware layer - hint: it's probably something to do with libsensors.so.
I am not sure if this will actually assist you, but I have found a work around (Not sure how well if will help the battery saving though).
Using bash I have a while loop cat-ing /sys/devices/virtual/accelerometer/accelerometer/acc_file, and when I turn off the screen via the power button the output continues, but is frozen. (I had sshd running in a chroot hence the being able to see it.)
However, in echoing 0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness. The screen turns off, and the output is continuous.
This is on a SGH-T589W, running android version 2.3.6.
I applied the PARTIAL_WAKE_LOCK and it worked like charm to me. Tested on OS 5.0, 6.0 & 7.0. Here's my code to acquire and release wake lock. Be careful it increased the battery drainage, so acquire and release it intelligently.
public void acquireWakeLock() {
final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
releaseWakeLock();
//Acquire new wake lock
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK");
mWakeLock.acquire();
}
public void releaseWakeLock() {
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
mWakeLock = null;
}
}
Ref: https://developer.android.com/training/scheduling/wakelock.html#cpu
I am working on a prediction sdk, who use device sensors (accelerometer/gyroscope) data and predicts the user events. I experienced the same issue.
I've ran into similar problems with the Samsung Nexus running Android 4.0.2 using other system services that stop/pause while the screen is off even though a PARTIAL_WAKE_LOCK is acquired. My solution was to use a SCREEN_DIM_WAKE_LOCK as in:
lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME);
It would be far better to have the screen fully off, but at least this solution works although it would be even better if I could limit using a SCREEN_DIM_WAKE_LOCK to only those devices/OSes that require it.
I hate to disappoint you, but some devices just don't keep acceleromet on while they are in a sleep mode. Some do, others don't. You can check any pedometer weight loss app on store most of them explicitly state that this won't work on some devices.
If the partial wake lock option is not available for your phone it means the driver for the sensor has early_suspend enabled.
There are two options.
1: Disable EARLY_SUSPEND in the driver
2: Add a run time flag that can enable/disable early_suspend functionality at the driver level.
ex. cat /sys/module/earlysuspend/sensor 1/0
IMO the second option should have been there from the beginning.
I have an application in which I am sending network data over WiFI. Everything is fine until I turn the display off or the device goes to 'sleep'. I'm already locking the WiFi however, it seems to be the case that the CPU speed ramps down when in sleep which causes my streaming to not behave properly (i.e. packets don't flow as fast as I would like as they do when the device is not sleeping).
I know that I possibly can/possibly should address this at the protocol level however, that might possibly not be possible as well...
Is there any way to "prevent the CPU from going to 'sleep' when the screen is off"? If so, how? If not, any advice on how to keep the speed of my WiFi stream consistent whether the device is in sleep mode or not?
Grab a PARTIAL_WAKE_LOCK from the PowerManager. You'll also need to add the WAKE_LOCK permission to your manifest.
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag");
wl.acquire();
//do what you need to do
wl.release();
Okay, so, after much more research and experimenting, it seems that the real issue is the fact that, at least on some phones, their WiFi goes into a 'partial sleep' mode EVEN IF you've taken the WiFi lock. It seems that this is what the 'WIFI_MODE_FULL_HIGH_PERF' flag was invented for when taking the WiFi lock... unfortunately, this flag is only available on some devices/Android versions (I have no clue as to which but, it wasn't available to me). So, therefore, it isn't a fix for all devices.
The only "solution" (which is actually a kludge) seems to be to 'detect when the screen is turned off and then, set an alarm that turns the screen back on immediately thereafter'. The links that helped a little bit with this are:
How to keep a task alive after phone sleeps?
and
http://android.modaco.com/topic/330272-screen-off-wifi-off/
I hope that this helps people who are experiencing WiFi disruption when the phone goes to sleep/screen is turned off (and the phone is unplugged/disconnected [e.g. you won't see this effect when connected to adb; only when the phone is running with nothing connected to it]).
I searched and was not able to find the answer to this question. I am working on app that will run all the time. I am using wifi and everything works fine until the device sleeps. One device sends out multicast packets and the other one should get them and wake up but it is not. Right now the network thread is started from a service thread started by StartService() from my main class. IN the service I get a wifi lock and a wifi multicast lock so that wifi and multicast "should" stay on when the device sleeps. I also tried adding a partial wake lock to the mix but still nothing works. Any ideas? I am devleoping on two nexus ones running android 2.3.3 right now.
You need to set the PowerManager.ACQUIRE_CAUSES_WAKEUP flag in your WakeLock, however PowerManager.ACQUIRE_CAUSES_WAKEUP flag doesn't work with PowerManager.PARTIAL_WAKE_LOCK, but it should work with PowerManager.SCREEN_DIM_WAKE_LOCK.
Below code should wake the display and CPU of your device, when you call acquire() on the WakeLock. The 5 second sleep should give your WiFi enough time to wake.
WakeLock lock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
lock.acquire();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
// do work here..
lock.release()