I'm creating an application that needs to keep track of a lot of things the user is doing. This all needs to happen in the background and needs to be running continiously. To mention two: constant tracking of activity with google activity API and location tracking with google's geofence API.
I have created a (Intent)Service for each parameter I am tracking and everything is going well. Even when you kill the application, the service will start again on the background and perform as expected.
MY PROBLEM: As soon as I lock my phone, it stops tracking. As soon as I light up my screen or unlock it works again.
NOTE1: I'm using one main service which controls all other (intent)services sensing the parameters. (I'm not sure if this is the best way to do it or if I should create one big service?...).
What I've tried is the PARTIAL_WAKE_LOCK to keep awake my main service controlling all other services. This didn't work. I've also tried to use the PARTIAL_WAKE_LOCK to keep awake the services sensing the parameters. This did not work either.
NOTE2: I know this should not be done in real applications but it's a must. It's an application for an experiment and will never go in the playstore. Also all users will be notified what will be tracked and how this can effect their battery during the experiment.
#Override
public void onCreate() {
super.onCreate();
...
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (! keepCPUOn){
wakeLock.acquire();
keepCPUOn = true;
}
}
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Many thanks!
Beginning with Android 6 and its new Doze mode the wake locks don't prevent the device to enter sleep mode, they are ignored
Proposed solution: Your service need to be a foreground service, that's it should call startForeground() and show a non dismissable notification, and you need to acquire a partial wake lock too.
I am also creating app like your. location tracking work in background and UI screen doesn't lock. in which UI screen you are start location service please put below code in that java file.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_current_ride_new);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
}
This code is working perfectly for me.
I've just add my app in Protected apps in settings my phone Android 4.4 (this flug allow to keep running after the screen is turned off)
Related
I am using location manger class to receive location updates my requirement is such that I have to listen for contious location updates but the problem I am facing that once it disconnects I don't know how to reatablish GPS connection,furthermore in some device once device sleeps i m not able to receive any location updates please provide any solutions to achieve this any help is appreciated..
public void setup(MainActivity activity) {
if (!setup) {
this.activity = activity;
Intent locationIntent = new Intent(this.activity, LocationIntentService.class);
mLocationPendingIntent = PendingIntent.getService(this.activity, 0, locationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent detectedIntent = new Intent(this.activity, ActivityDetectionIntentService.class);
mDetectedActivityPendingIntent = PendingIntent.getService(this.activity, 0, detectedIntent, PendingIntent.FLAG_UPDATE_CURRENT);
googleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(activity)
.addOnConnectionFailedListener(activity)
.addApi(ActivityRecognition.API)
.build();
setup = true;
}
}
**LocationIntentService.java**
public class LocationIntentService extends IntentService {
public LocationIntentService() {
super("LocationServices");
}
public LocationIntentService(String name) {
super("LocationServices");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
Location location = intent.getParcelableExtra(LocationManager.KEY_LOCATION_CHANGED);
if (location != null) {
Intent localIntent = new Intent(HWUtil.LOCAL_RECEIVER);
localIntent.addCategory(Intent.CATEGORY_DEFAULT);
localIntent.putExtra(HWUtil.LOCATION, location);
localIntent.putExtra(HWUtil.FROM, HWUtil.LOCATION_SERVICE);
sendBroadcast(localIntent);
}
}
}
}
and i m sending this location updates to Broadcastrecciver
Please note that the continuous usage of pure GPS as location provider is quite energy hungry on mobile devices. Once that is said, I would perform your task as follows:
I would use a (background) service that would be working togheter with your mobile app. I.e., the mobile app will start the execution of this service (check startForeground() functionality so that your service could be run almost with no interruption, and including a notification on statusBar that can be linked to your activity).
The service (or any internal class) would implement the LocationListener interface and will be the one that actually will be sampling locations. Once you get a location you will process it (depending on your requirements you might want to process it in another thread since the default thread of a created service is the same than the Activity UI).
Once processed, youw would deliver the response to the Android activity, i.e., you would call a public method of your activity, or would implement a more complex communication strategy with Handlers, etc.
In regard with the continuous location sampling, I would strongly suggest you to use AlarmManager services so that you could schedule the next readings (you could make it at exact repeating intervals, see official developer's documentation).
If (and only if) the processing of the location update is heavy or time consuming (for instance, you have to transmit it to a server) you could acquire and hold a WakeLock for avoiding the device to fall into sleep mode; do not forget to release the WakeLock after your processing is done, since it is a major cause of energy sinks in mobile apps, so be very careful with this.
Hope it helps for you
AFAIK, wake lock is the easiest way to do. PowerManager.WakeLock
wake lock is a mechanism to indicate that your application needs to have the device stay on.
Any application using a WakeLock must request the android.permission.WAKE_LOCK permission in an element of the application's manifest. Obtain a wake lock by calling newWakeLock(int, String).
Call acquire() to acquire the wake lock and force the device to stay on at the level that was requested when the wake lock was created.
You should aquire a wake lock:
//in onCreate of your service
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
cpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"gps_service");
cpuWakeLock.acquire();
// Release in onDestroy of your service
if (cpuWakeLock.isHeld())
cpuWakeLock.release();
and add this to your manifest:
https://developer.android.com/reference/android/Manifest.permission.html
Above is good if you need continuous location updates.
I tried to add this code to my project in my MainActivity/onCreate void:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyApp::MyWakelockTag");
wakeLock.acquire();
Then I tested it my tablet. I was working over ~25 mins but then it stopped again. Sending of the location data was stopped. Then I pushed the pwr button of the tablet and the GPS ikon disapeared on the top of the screen and did not come back...
I develop a small app, this one have to run always over all when the device is sleep or deep sleep (press right button to turn off the screen) I read many posts about it, and all tell me that the way is use PowerManager, and my question is if I use fine this command, my structure is> myActivity.class, ReceiverBoot.class and ServiceBoot.class, I use the POwerManager class on myActivity.class like this:
PowerManager mgr = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
PowerManager wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP , "MyWakeLock");
on onCreateMethod after of this one put
wakeLock.acquire();
and after of this one I have a
super.onCreate(savedInstanceState);
this.mTimer.scheduleAtFixedRate(
new TimerTask(){
#Override
public void run(){doTask();}
} , 0, 1000);
wakeLock.release();
on Manifest XML code I have
<uses-permission android:name="android.permission.WAKE_LOCK" />
and on layout XML code have
android:keepScreenOn="true"
but after to 10seg the creen es OFF always but the app is running, jut with wifi.
the app work very fine with wifi conn, but when change to 3G conn, the app is gone, I use fine this command?? the problem is the kind of conn to Internet??? thanks a lot!
I'm not 100% clear on your issue. Whether its the data issue, or the screen issue. (Or if the screen issue is what you are doing to try and fix the data issue?).
For the screen
You are not using the right lock to keep the screen on. PARTIAL_WAKE_LOCK only requests that you can use the processor. To keep the screen on your app use one of SCREEN_DIM_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK or FULL_WAKE_LOCK depending on what you want. This lock should be held for as long as you need the lock. Currently you are releasing it in onCreate(). Keep in mind that if the user presses the power button though that your lock is released (with PARTIAL being the exception to this).
If your intent is just to keep the screen on when a view is active then it's better not to use the lock at all. The wake lock needs an extra permission. You can do it by adding this to your onCreate override:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
This is the same effect as using android:keepScreenOn="true", which you already seem to be doing. I can't however tell why that isn't working from your snippets. Make sure you are inflating the right layout.
For your data
The device will likely be switching off 3G data when the screen is not active (and no lock is present). Again, don't release your lock if you need it (Though don't keep it forever either, that's just going to suck up phone battery).
I use wakelock to keep the display on.
However, when the app is ended, the display also be turned off.
I want to keep it on after the app is ended.
What should I do?
What you want to do is use the .On_AFTER_RELEASE flag see below.
PowerManager pm;
PowerManager.WakeLock wakeLock;
// Put the next 5 lines in a method that is called when you want to acquire a wakelock //or in the OnREceive() of a broadcast receiver.`
PowerManager pm = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(
pm.ON_AFTER_RELEASE|pm.SCREEN_DIM_WAKE_LOCK, "My wakelook");
wakeLock.acquire();
...Do Stuff here
//Override the onDestroy of your activity to release the wakelock when it is destroyed.
#Override
protected void onDestroy() {
super.onDestroy();
wakelock.release;
}
This will keep the screen lit up as if someone interacted with the device (pushed the power button, touched the screen, etc.) right when you release the wakelock. At that point a normal power down will occur if there is no further interaction with the device (screen goes dim, and then it goes dark).
I
Let me know if that helped.
Thx
******************Added*************
If you want to wake up the phone from after the screen goes dark you can create your wakelock with the following flags. This is good if you have a broadcast receiver and want to turn on the screen when an event happens so the user can immediately see a UI (Notification, Toast, Layout,etc.)
PowerManager.WakeLock wakeLock = pm.newWakeLock(
pm.ACQUIRE_CAUSES_WAKEUP|pm.ON_AFTER_RELEASE|pm.SCREEN_DIM_WAKE_LOCK, "My wakelook");
And for how long do you need the display to stay on? Just for some time, or until certain event happen?
Don't release the wakelock when application is ended. You may schedule an event for a period of time you need to keep the screen on. But generally it's a bad practice as holding full wakelock may prevent not only screen but other hardware from going to sleep.
How do I prevent an Android device from going to sleep programmatically?
If you just want to prevent the sleep mode on a specific View, just call setKeepScreenOn(true) on that View or set the keepScreenOn property to true. This will prevent the screen from going off while the View is on the screen. No special permission required for this.
One option is to use a wake lock. Example from the docs:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
// screen and CPU will stay awake during this section
wl.release();
There's also a table on this page that describes the different kinds of wakelocks.
Be aware that some caution needs to be taken when using wake locks. Ensure that you always release() the lock when you're done with it (or not in the foreground). Otherwise your app can potentially cause some serious battery drain and CPU usage.
The documentation also contains a useful page that describes different approaches to keeping a device awake, and when you might choose to use one. If "prevent device from going to sleep" only refers to the screen (and not keeping the CPU active) then a wake lock is probably more than you need.
You also need to be sure you have the WAKE_LOCK permission set in your manifest in order to use this method.
I found another working solution: add the following line to your app under the onCreate event.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
My sample Cordova project looks like this:
package com.apps.demo;
import android.os.Bundle;
import android.view.WindowManager;
import org.apache.cordova.*;
public class ScanManActivity extends DroidGap {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.loadUrl("http://stackoverflow.com");
}
}
After that, my app would not go to sleep while it was open. Thanks for the anwer goes to xSus.
android:keepScreenOn="true" could be better option to have from layout XML.
More info: https://developer.android.com/training/scheduling/wakelock.html
Set flags on Activity's Window as below
#Override public void onResume() {
super.onResume();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override public void onPause() {
super.onPause();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
From the root shell (e.g. adb shell), you can lock with:
echo mylockname >/sys/power/wake_lock
After which the device will stay awake, until you do:
echo mylockname >/sys/power/wake_unlock
With the same string for 'mylockname'.
Note that this will not prevent the screen from going black, but it will prevent the CPU from sleeping.
Note that /sys/power/wake_lock is read-write for user radio (1001) and group system (1000), and, of course, root.
A reference is here: http://lwn.net/Articles/479841/
what #eldarerathis said is correct in all aspects, the wake lock is the right way of keeping the device from going to sleep.
I don't know waht you app needs to do but it is really important that you think on how architect your app so that you don't force the phone to stay awake for more that you need, or the battery life will suffer enormously.
I would point you to this really good example on how to use AlarmManager to fire events and wake up the phone and (your app) to perform what you need to do and then go to sleep again: Alarm Manager (source: commonsware.com)
If you are a Xamarin user, this is the solution:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle); //always call superclass first
this.Window.AddFlags(WindowManagerFlags.KeepScreenOn);
LoadApplication(new App());
}
I'm using Wakelock in my application to prevent the phone from sleeping when the app is visible.
The problem comes when there is an orientation change and the system destroys and re-creates the app in landscape mode. If the wakelock timer has expired in the background the system takes the release of wakelock as an opportunity to switch off the screen.
Edit: I should mention that I am setting Wakelock onResume, and releasing onPause - as I understand it, it's necessary to release then to prevent the app from leaking the wakelock.
I need wakelock to continue through the orientation change.
Below I've outlined a solution to this. Is this the preferred way to handle it, and are there any alternatives?
Create a service which holds wakelock (rather than the activity) and when the activity unbinds the service starts a countdown timer (for say 10 seconds) in which it will release wakelock when the timer expires if the activity does not rebind. If it was a simple orientation change the activity will rebind within that 10 seconds and so maintain wakelock, if it doesn't, wakelock will be released.
Thanks.
Instead of a WakeLock, try getWindow().setFlags() using the WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON flag.
If the wakelock timer has expired in
the background the system takes the
release of wakelock as an opportunity
to switch off the screen.
It shouldn't. By definition, the user has interacted with the device, so the screen should stay on for that reason, independent of anything else.
Here's how I did it...
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "DoNotDimScreen");
Followed by...
wl.acquire();
... when you need to actually activate the wake lock.
The 'PowerManager.ON_AFTER_RELEASE' flag pokes the user activity timer so the screen stays on for a little longer when this wake lock is released, which will be the case when your activity is Destroyed on a change of orientation.
Works OK for me!
I did it by actually never releasing the wakelock. Instead, I acquire it with timeout.
private PowerManager.WakeLock wl;
protected void onStart(Bundle savedInstanceState) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "Words counter");
// disable reference counting, as acquire/release calls are not paired
wl.setReferenceCounted(false);
wl.acquire();
}
protected void onStop() {
// acquire for few seconds to keep lock until onStart is called with new orietnation
wl.acquire(3000);
}
Advantages over other methods:
Usable with the SCREEN_DIM_WAKE_LOCK
Simple (no need to play with isFinishing() etc.)
Does not poke user activity after orientation change. I.e. dimmed display stays dimmed
If you release (e.g. the time is over but the user remained in the activity), it's released immediately. No need to wait for default timeout.