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...
Related
One of my peer developer has written an intent service that makes an API call and then sleeps for 2 mins. After waking up, it sends again.
Below is the code:
public class GpsTrackingService extends IntentService {
....
#Override
protected void onHandleIntent(Intent intent) {
do{
try{
//make API call here
//then go to sleep for 2 mins
TimeUnit.SECONDS.sleep(120);
} catch(InterruptedException ex){
ex.printStackTrace();
}
} while (preferences.shouldSendGps()); //till the user can send gps.
}
....
}
Manifest
<service android:name=".commons.GpsTrackingService" />
This is working fine when the phone is active. However, whenever the phone goes into doze mode it fails to wake.
Will using alarm manager with WAKE permission solve this?
I have just got the code base and need to fix this within today. It'll be great if someone can help.
As the documentation says:
In Doze mode, the system attempts to conserve battery by restricting
apps' access to network and CPU-intensive services. It also prevents
apps from accessing the network and defers their jobs, syncs, and
standard alarms.
Periodically, the system exits Doze for a brief time to let apps
complete their deferred activities. During this maintenance window,
the system runs all pending syncs, jobs, and alarms, and lets apps
access the network.
In few words, while in Doze mode the system suspends network accesses, ignores Wake Locks, stops acquiring data from sensors, defers AlarmManager jobs to the next Doze maintenance window (which are progressively less frequently called), also WiFi scans, JobScheduler jobs and Sync adapters do not run.
Neither setAndAllowWhileIdle() nor setExactAndAllowWhileIdle() can fire alarms more than once per 9 (?) minutes, per app.
And it seems that the Foreground Services are also involved into this "Doze Drama", at least in MarshMellow (M).
To survive in this situation, tons of applications need to be at least rewiewed. Can you imagine a simple mp3 player which stops playing music when the device enters in Doze Mode?
Doze mode starts automatically, when the device is unplugged from the power supply and left on the table for about 1 hour or so, or even earlier when the user clicks the power button to power down the screen, but I think this could depend by the device manufacturer too.
I tried a lot of countermeasures, some of them really hilarious.
At the end of my tests I reached a possible solution:
One possible (and maybe the only) way to have your app running even when the host device is in Doze mode, is basically to have a ForegroundService (even a fake one, doing no jobs at all) running in another process with an acquired partial WakeLock.
What you need to do is basically the following (you could create a simple project to test it):
1 - In your new project, create a new class which extends Application (myApp), or use the
main activity of the new project.
2 - In myApp onCreate() start a Service (myAntiDozeService)
3 - In myAntiDozeService onStartCommand(), create the Notification
needed to start the service as a foreground service, start the
service with startForeground(id, notification) and acquire the
partial WakeLock.
REMEMBER! This will work, but it is just a starting point, because you have to be careful with the "Side Effects" this approach will generate:
1 - Battery drain: The CPU will work for your app forever if you
don't use some strategy and leave the WakeLock always active.
2 - One notification will be always shown, even in the lockscreen,
and this notification cannot be removed by simply swiping it out, it
will be always there until you'll stop the foreground service.
OK, let's do it.
myApp.java
public class myApp extends Application {
private static final String STARTFOREGROUND_ACTION = "STARTFOREGROUND_ACTION";
private static final String STOPFOREGROUND_ACTION = "STOPFOREGROUND_ACTION";
#Override
public void onCreate() {
super.onCreate();
// start foreground service
startForeService();
}
private void stopForeService() {
Intent service = new Intent(this, myAntiDozeService.class);
service.setAction(STOPFOREGROUND_ACTION);
stopService(service);
}
private void startForeService(){
Intent service = new Intent(this, myAntiDozeService.class);
service.setAction(STARTFOREGROUND_ACTION);
startService(service);
}
#Override
public void onTerminate() {
stopForeService();
super.onTerminate();
}
}
myAntiDozeService.java
public class myAntiDozeService extends Service {
private static final String TAG = myAntiDozeService.class.getName();
private static boolean is_service_running = false;
private Context mContext;
private PowerManager.WakeLock mWakeLock;
private static final int NOTIFICATION_ID = 12345678;
private static final String STARTFOREGROUND_ACTION = "STARTFOREGROUND_ACTION";
private static final String STOPFOREGROUND_ACTION = "STOPFOREGROUND_ACTION";
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!is_service_running && STARTFOREGROUND_ACTION.equals(intent.getAction())) {
Log.i(TAG, "Received Start Foreground Intent ");
showNotification();
is_service_running = true;
acquireWakeLock();
} else if (is_service_running && STOPFOREGROUND_ACTION.equals(intent.getAction())) {
Log.i(TAG, "Received Stop Foreground Intent");
is_service_running = false;
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
#Override
public void onDestroy() {
releaseWakeLock();
super.onDestroy();
}
private void showNotification(){
Intent notificationIntent = new Intent(mContext, ActivityMain.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(mContext)
.setContentTitle("myApp")
.setTicker("myApp")
.setContentText("Application is running")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.build();
// starts this service as foreground
startForeground(NOTIFICATION_ID, notification);
}
public void acquireWakeLock() {
final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
releaseWakeLock();
//Acquire new wake lock
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG+"PARTIAL_WAKE_LOCK");
mWakeLock.acquire();
}
public void releaseWakeLock() {
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
mWakeLock = null;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
AndroidManifest.xml changes.
In the AndroidManifest.xml add this permission:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Don't forget to add the name of your app in the <application> tag:
<application
....
android:name=".myApp"
....
And finally add your foreground service running into another process:
<service
android:name=".myAntiDozeService"
android:process=":MyAntiDozeProcessName">
</service>
A couple of notes.
In the previous example, the notification created, when clicked,
opens the ActivityMain activity of your test project.
Intent notificationIntent = new Intent(mContext, ActivityMain.class);
but you can use another kind of intent too.
To test it, you have to add some job to be performed into your
ActivityMain.java, for example some repeating alarm (which was
normally stopped when the device falls in Doze Mode), or a ripetitive
network access, or a timed tone played, or.... whatever you want.
Remember that the job performed by the main activity has to run
forever because to test this AntiDoze you need to wait at least 1
hour to be sure the device enters in Doze Mode.
To enter in Doze mode, the device has to be quiet and unplugged, so
you can't test it while you are debugging. Debug your app first,
check that everything is running then stop it, unplug, restart the
app again and leave the device alone and quiet on your desk.
The adb commands suggested by the documentation to simulate Doze
and StandBy modes could and could not give you the right results
(it depends, I suppose, by the device manufacturer, drivers, bla
bla). Please make your tests in the REAL behaviour.
In my first test, I used an AlarmManager and a tone generator to play a tone every 10 minutes just to understand that my app was still active.
And it is still running from about 18 hours, breaking my ears with a loud tone exactly every 10 minutes. :-)
Happy coding!
One of my peer developer has written an intent service that makes an API call and then sleeps for 2 mins. After waking up, it sends again.
Only have a service running while it is actively delivering value to the user. Sitting around for two minutes, watching the clock tick, is not actively delivering value to the user.
Will using alarm manager with WAKE permission solve this?
That depends on what you mean by "solve this". You can use AlarmManager to request to get control every two minutes so that you can do work. While the device is in Doze mode, you will not actually get control every two minutes, but once per maintenance window.
I have an android application with a foreground service that listens to gps location updates, I am using LocationManager with gps provider only.
I have this piece of code:
Intent intent = new Intent(this, LocationUpdateReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, this.INTERVAL, 0.0f, pi);
I'm getting location updates through receiver. It is working correctly when screen is on, but when I turn the device screen off, it stop getting location updates. It is working on my redmi 5 device, and working as expected. but my problem apprears on huawei.
Note:
this.INTERVAL = 10000;
I'm using wakeLock to prevent the device from sleeping as follows:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG:");
wakeLock.aquire();
Also my service in Manifist.xml like this
<service android:name="com.arttech.services.LocationService" android:enabled="true" />
And finally, I'm showing notification for my foreground service as follows:
Notification.Builder ongoing = new Notification.Builder(getBaseContext()).setSmallIcon(R.drawable.logo).setContentTitle("Location Service").setOngoing(true);
if (Build.VERSION.SDK_INT >= 26) {
ongoing.setChannelId("myChannelID");
}
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATIONID, ongoing.build());
Anyone can help me with this issue? I'm struggling for more than one month and I'm getting nowhere.
Thanks
Update:
I also tried to add my app as protected app manually through battery settings, but I get the same behavior. I tested some app called relive, and it records the GPS locations perfectly. What am I doing wrong?
UPDATE:
Here are my OnStartCommand code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("omar","Service Started");
LocationObserver.getInstance().addObserver(this);
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT > 8)
{
Log.d("omar_build",SDK_INT+"");
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
CreateConnectionInstance(); // Connect to socket
startTracking();
isLocationServiceRunning = true;
return START_STICKY;
}
Maybe this helps you, from commonsware
https://commonsware.com/blog/2015/11/18/another-doze-edge-case-foreground.html
A foreground service with a partial WakeLock is supposed to block Doze mode, presumably with an eye towards music players and the like. However, Mr. Nalevka discovered that if the process with the foreground service also has the foreground activity, Doze mode takes over again.
Dianne Hackborn’s recommended workaround is to split the foreground
service out into a separate process. Since there doesn’t seem to be a
way to link to specific G+ comments, you’ll need to scroll way down
the comments list on this post to get to their exchange.
This is probably due to restriction applied by custom brands like Huawei and some others. You should add your app into whitelist of phone. Please check following link How to WhiteList app in Doze mode Android 6.0
UPDATE :
make these two changes and then check
Acquire wakelock into onStartCommand
Acquire wakelock with some approximate time
Release your wakelock when service destroy or when service work is done
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (powerManager != null)
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
if (mWakeLock != null)
mWakeLock.acquire(TimeUnit.HOURS.toMillis(10));
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)
If i let the phone sit for a long time like 15 minutes i lose my receiver but i thought it was to persist like a service after being killed for memory.
Manifest:
<receiver
android:name=".WearableReceiver"
android:enabled="false">
<intent-filter>
<action android:name="com.example.johnbravado.MESSAGE_PROCESSED"/>
</intent-filter>
</receiver>
In Activity to start receiver
ComponentName component = new ComponentName(CounterActivity.this, WearableReceiver.class);
getPackageManager()
.setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
The receiver
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//MyConstants.getInstance().showToast("Message Rcvd");
PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"com.example.johnbravado");
wakeLock.acquire();
// Do Work
MyConstants.getInstance().msgReqAction(intent.getIntExtra(MyConstants.BROADCAST_DATA_REQ, 0));
wakeLock.release();
}
The broadcast sender
String BROADCAST_ACTION_RESP = "com.example.johnbravado.MESSAGE_PROCESSED"
#Override
public void onMessageReceived(final MessageEvent messageEvent) {
nodeId = messageEvent.getSourceNodeId();
String incomingPath = messageEvent.getPath();
int incomingReq = Integer.parseInt(new String(messageEvent.getData()));
if(incomingPath.equalsIgnoreCase(MyConstants.MSG_COUNTER_REQ_PATH)) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(BROADCAST_ACTION_RESP);
broadcastIntent.putExtra(MyConstants.BROADCAST_DATA_REQ, incomingReq);
sendBroadcast(broadcastIntent);
}else if(incomingPath.equalsIgnoreCase(MyConstants.MSG_DEFAULT_PATH)){
}
}
only way I get this to persist for long periods of time is to invoke a service
wearableReceiverIntent = new Intent(this, WearableReceiverService.class);
if(!WearableReceiverService.isRunning())
startService(wearableReceiverIntent);
the service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
IntentFilter filter = new IntentFilter(MyConstants.BROADCAST_ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new WearableReceiver();
registerReceiver(receiver, filter);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notif_bible)
.setContentText("Preaching").build();
startForeground(MyConstants.NOTIF_COUNTING_SERVICE, notification);
isRunning = true;
return START_STICKY;
}
If I run the service it persists for long periods of time but it drains the battery unnecessarily considering I interact only once every 10 minutes. I was under impression Broadcast receiver would work like service except for short bursts of work. invoke the service if you need to do long actions.
A BroadcastReceiver handles an intent and then stops again. This handling of an intent should be fast. If you want to do a lot of stuff, you should start an Service from the BroadcastReceiver and handle it from there.
A BroadcastReceiver object is only valid for the duration of the call
to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
A BroadcastReceiver is started using the sendBroadcast intent.
So remove android:enabled="false" and use sendBroadcast, which will startup the Receiver by Android.
http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html
Greenify was killing my app when the screen went off. I was battling something I had no hope of defending against with code. After I explicitly told Greenify to not kill my app, I never told it to kill my app to begin with, everything worked as intended.
I had the same problem due on my Asus ZenPad due to the Asus Mobile Manager app, specifically the "Auto start manager" was blocking the intent to my app.
Deactivating the app (uninstall is not possible) worth nothing, the solution has been to leave the app installed but whitelist my developing app so it can receive broadcast like PACKAGE_REPLACE. (Pay attention that the switches are confusing, you actually have to touch on "blocked" so it turns on into "allowed" to enable it.
I think another option is to update or change the ROM (choosing one without all that bloatware).
If your BroadcastReceiver is setup in your manifest, there is no need to try and adjust the PackageManager component information for your package. As long as you remove the enabled="false" part.
Your BroadcastReceiver should be very short with what it does: typically update some internal data or start another component which can do the heavy lifting of your app's operation. You can use it to trigger a Service to do this type of thing in the background. But, note that "background" in this case means without user-interaction. It does not mean a background context of execution, such as a secondary thread. It is up to you do manage the thread(s) in your Service. Your BroadcastReceiver and Service callback entry points (onReceive() and onStartIntent()) run in the context of the main thread of your app.
Power management definitely plays a roll in all of this. Is your broadcast Intent actually being sent and done in a way which will wake the device? If it does wake the device and send the Intent, the device will only stay awake long enough for the BroadcastReceiver to run its onReceive(); after that returns there are no guarantees. The device will aggressively sleep, which is why wakelocks are a thing. However, use of wakelocks can cause excessive battery drain, unless used properly. If you are running on Marshmallow or newer, the Doze functionality can also wreck havoc on your plans. Wakelocks are ignored when in Doze mode and won't be considered until the user brings the device out of doze.
I had the same issue and it was resolved by granting auto launch permission for the app.
Go to
Settings->Permissions->Manage Auto Launch
and allow auto launch for your app.
In reference to Accelerometer seems to only work for a few seconds?
I'm using the BOOT_COMPLETED broadcast event to call the following:
public class OnBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, ShakeEventService.class);
context.startService(service);
}
}
Which in turn calls this:
public class ShakeEventService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sManager.registerListener(thisSensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
return Service.START_STICKY;
}
}
There are lots of other functions and whatnot within that class, obviously, and technically everything works fine, except that regardless of what flag I return (START_STICKY, START_STICKY_COMPATIBILITY, START_NOT_STICKY, or START_REDELIVER_INTENT), the service is being killed after anywhere between 5 and 25 minutes and doesn't re-initiate until the next boot.
I've read a lot about Android 4.2 introducing new battery optimisations that kill off background processes, and I've read all sorts of bug reports with START_STICKY no longer working, but the various work-arounds seem to not be making any difference in my case. Not sure whether I'm attempting to implement them wrongly or if these workarounds have just stopped working in the more recent versions. My test device is running 5.1.1.
I'm at a bit of a loss here and would appreciate some help again please.
EDIT
For anybody else stumbling into this problem, the accepted answer below includes a working wakelock that keeps the service alive on Nexus 7 running Android 5.1.1 and LG G4 running Android 6.
Additionally, prefixing the android:process attribute of the manifest file with a colon does seem important for keeping the wakelock in place. Ref http://developer.android.com/guide/topics/manifest/service-element.html
Still no luck on a Samsung S6 Edge running the same Android 5.1.1 though, so it looks like Samsung implement something within their battery optimisations that's causing a premature kill..
All you have to do to have a service that is constently alive is:
<!-- BackGroundService Service -->
<service
android:name="com.settings.BackgroundService"
android:enabled="true"
android:exported="false"
android:process=":my_process" />
2) onStartCommand should return:
return Service.START_STICKY;
and that's all buddy after I Start the service from the main activity it is on for the whole day/
You need to use a Partial Wakelock with the service. If your service is interactive with the user, you might consider making the service foreground.
This is a working example for a Partial Wakelock:
Use this when service is started:
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock cpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
cpuWakeLock.acquire();
When the service is stopped, do call cpuWakeLock.release();
imports android.support.v4.content.WakefulBroadcastReceiver which
Android Studio is telling me doesn't exist.
You need to import the support library for that.
To do the trick use JobScheduler and JobService which allow you to execute code periodically.
First create a class that extends JobService, then implement required methods and add your service code/start another service from within the JobService onStartJob() method.
Here's an example for executing a JobService operation periodically:
ComponentName serviceComponent = new ComponentName(context, yourJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
builder.setRequiresDeviceIdle(false);
builder.setRequiresCharging(false);
builder.setPeriodic(60000); // <<<<---- 60 seconds interval
JobScheduler jobScheduler = (JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(builder.build());
You can find more info here:
https://developer.android.com/reference/android/app/job/JobService.html
Good luck!