I have a service which sends notifications every 2 minutes..
When the phone gets locked no new notifications are received and only when I unlock my phone I receive notifications )
Whether there is any way to change it..?
Best solution for running some task every 2 minutes is AlarmManager And do not use wakelocks except you don't need to hold device in work mode (like mp3 player for example), because it will spend battery.
UPDATE FOR ENYONE WHO TO LAZY FOR READING MANUAL
For using AlarmManager you need broadcast receiver at first.
public class ExampleReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
// this method will be called by AlarmManager. But be carefull it has timeout
// if your task need more time, you should run thread from there with wakelocks
}
}
Then you can set task to AlarmManager.
public class ExampleActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
Intent intent = new Intent(this,ExampleReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime()+INTERVAL,pendingIntent);
}
}
This example run task once after INTERVAL. And it will wakeup phone for this task. You can set repeating tasks due AlarmManager, or it possible better to set new task just from receiver
When phone is locked, the device goes to deep-sleep mode and it will not handle any wait/sleep timer related delays.
Try using AlarmManager instead for getting notification every 2 mins. Or may be hold WAKE LOCKS (though might result in battery drain and not recommended)
You might be able to accomplish your goal using the PowerManager API:
http://developer.android.com/reference/android/os/PowerManager.html
You can use this to wake the phone up briefly to handle your notification. Make sure you're familiar with how the PowerManager API works, though - it's easy to write your code in a way that drains the battery.
Related
In my app i am using AlarmManagerto start service every week on a specific time. But in some cases instead of waiting another 7 days I need to call the service on the next day. Because of that I'm not using reapeating alarm but instead in the started service I'm creating new Alarm and set it to a specific date. Something like this:
public class AlarmService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//do something
//setting new alarm
AlarmManager alarmMng = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(this,AlarmService.class);
PendingIntent alarmIntent = PendingIntent.getService(this, 0, i, 0);
Calendar c = Calendar.getInstance();
if(something) alarmMng.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis()+1000*60*60*24,alarmIntent);
else alarmMng.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis()+1000*60*60*24*7,alarmIntent);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
Everything works fine but I wonder if this is good way to do it. Is it a good idea to create new alarm from service that was just called by one? Is it considered bad programming practice? If so how else should I handle it?
Is it considered bad programming practice?
No - this is a fine use case for creating alarm events. If you look at the documentation, use of AlarmManager is intended to send events to your app even if it is not running. Receiving those events in a Service that then schedules another alarm event is perfectly fine. The rest of my answer is intended to explain how to answer the other question you ask:
Is it a good idea to create new alarm from service that was just
called by one?
To determine if you need a Service really depends on the "do something" portion of your code more than setting the alarm. For example, you might be fine using a IntentService or even a BroadcastReceiver.
EDIT:
In other words, you will need a background process to handle this. Determining the appropriate background process (Receiver or Service) depends on how much processing needs to be done. Generally, setting an alarm all by itself could probably be handled in a Receiver but if it takes too long to process (e.g. more than 10 seconds) you will get an ANR (Application Not Responding) crash. That's when you need a service.
END EDIT..
This is a good post about services: Service vs IntentService
Specifically, the concern you should have is if your service is called multiple times, you should probably include code to cancel any previous alarms created by it, before setting a new alarm.
EDIT: Also, you are not "creating a new service" or "new alarm" each time. Services will have onStartCommand called each time an intent is sent to it (by the AlarmManager or by any other means). A new instance is not created unless it is not already instantiated.
I have an application that does something in a service triggered by an alarm every 10 minutes while the app is in the background. I want the Alarm to keep going off even if the OS kills the app (So its dead and have to relaunch) and only kill it if the user actually removes the app from recent apps or force kills it from settings (or is logged off but that already works). I have tried many different approaches, latest I tried this http://www.dotkam.com/2011/01/10/android-prefer-alarms-and-intent-receivers-to-services/ without any luck. My Alarm looks like this.
if(ActivityLifecycleHandler.isApplicationInForeground()) {
return; // If App is in foreground do not start alarm!
}
String alarm = Context.ALARM_SERVICE;
AlarmManager am = ( AlarmManager ) context.getSystemService( alarm );
Intent intent = new Intent(locationBroadcastAction);
PendingIntent pi = PendingIntent.getBroadcast( context.getApplicationContext(), 0, intent, 0 );
int type = AlarmManager.ELAPSED_REALTIME_WAKEUP;
// Set trigger time to 0, because want to fire off the first one instantly
am.setRepeating( type, 0, ONE_MINUTE, pi );
And the BroadcastReceiver:
public class LocationBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent ) {
Intent myIntent = new Intent( context, LocationService.class );
context.startService( myIntent );
}
}
Any idea of what I am doing wrong? Everything works fine until the OS kills the app.
The alarm should goes off if the app was killed, even if if was removed from the recent app (but not if it was force-stopped).
It is actually the whole point of using the AlarmManager :
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.
You can see if the alarm is still there with :
adb shell dumpsys alarm
What is probably happening is that the device is woken up to receive the alarm, but fall asleep again as soon as the receiver finishes, before the service can start.
The receiver should take a wake lock (to be released by the service). The support library provides a WakefulBroadcastReceiver which does exactly that :
Helper for the common pattern of implementing a BroadcastReceiver that
receives a device wakeup event and then passes the work off to a
Service, while ensuring that the device does not go back to sleep
during the transition.
I'm looking at implementing the step sensor API introduced in Android 4.4 (http://youtu.be/yv9jskPvLUc). However, I am unable to find a clear explanation on what the recommended way to monitor this in the background is? It seems like most examples only show how to do this with an activity while the app is running. I don't particularly need a high frequency of updates - I basically want to log the amount of steps the user has walked every hour to a backend service.
Should I just spin up a background service that calls registerListener on SensorManager, or is there a more elegant way?
As far as I know, there is no way around the SensorManager, but if you need the data very infrequently, you could trigger the sensor manually and get its values with a TriggerEventListener, which is a little cleaner than a SensorEventListener.
AlarmManager is typically the best option for starting an hourly timer, and it works even if your app isn't running. AlarmManager sends an Intent to a class that extends BroadcastReceiver, and that class will start your Service. The AlarmManager can be set anywhere in your app depending on your implementation.
StepCountService
SensorManager sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
Sensor stepCounter = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
sensorManager.requestTriggerSensor(listener, stepCounter);
private TriggerEventListener listener = new TriggerEventListener(){
#Override
public void onTrigger(TriggerEvent event) {
//handle step count here
}
}
MainActivity
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,AlarmManager.INTERVAL_HOUR,
AlarmManager.INTERVAL_HOUR, alarmIntent);
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, StepCountService.class);
context.startService(service);
}
}
This is not a complete solution, but the most energy-efficient way could be to wake up your device every hour or so, start a service which quickly reads the data, then goes back to sleep.
Depending on which device level you target, using a WakefulBroadcastReceiver, as described in this answer, seems the way to go.
You need to
create the code by modifying the templates at WakefulBroadcastReceiver
add the Service and the BroadCastReceiver into the manifest.
schedule a repeating alarm somewhere in your app
If any of the points a less than clear, say so. See http://code.tutsplus.com/tutorials/android-barometer-logger-acquiring-sensor-data--mobile-10558
#TheoKanning's answer is the correct way to do this manually. Alternatively, Google Fit continuously logs this data and has an API you can use to pull it into your app.
https://developers.google.com/fit/android/get-started
https://developers.google.com/fit/android/history
My intention is to make an application that will track the movement of my android phone for every few minutes and send it to my server. I have read a lot online on how to do it with a service, AlarmManager and Partial_WakeLock. I have also gone through the commonsware examples in github.com but I was a bit confused because I am still not experienced in android.
I have been successful in getting my application to [get location and send it to my server]. How do I make my service wakeup every few minutes and do [work mentioned]? In the Wakeful example in commonsware, in which method do I mention my [work] and in which method do I keep calling it?
You need a Service and an AlarmManager. Your Service will handle getting the position and posting it to the server and AlarmManager will invoke your service basen on an interval you decide. You should initialize your AlarmManager with your Service roughly like this in onCreate or other place you want:
AlarmManager alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, YourAlarmReceiver.class),PendingIntent.FLAG_CANCEL_CURRENT);
// Use inexact repeating which is easier on battery (system can phase events and not wake at exact times)
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, YOUR_ALARM_TRIGGER_AT_TIME,YOUR_ALARM_INTERVAL, pendingIntent);
YourAlarmReceiver gonna start your service
public class YourAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, YourService.class));
}
}
On how to use Services refer to the android website http://developer.android.com/guide/topics/fundamentals/services.html
you could use a partial wakeLock with a sleep(X) which when the sleep(x) is resolved the system will call the next line of code, but the problem is I am seeing a possible infinite cycle that might need a task kill action, or just crash the system.
I'm currently having a problem integrating AlarmManager and BroadcastReceiver.
Im my app, I'm running a background service that runs regardless that app is running or not. I think I get this part working fine. The background service keeps an array that changes based on user's location. However, at 8:00am everyday, I want the app to reset the array variable to default. After much looking around online, it seems like the way to do this is via AlarmManager (to initiate the task every 8:00am) and using BroadcastReceiver (to receive the alarm, and perform the task).
So basically the code goes something like this:
public class BackgroundService extends Service {
private ArrayList thisArray;
private BroadcastReceiver thisReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
setArrayToDefault();
}
}
#Override
public void onCreate(){
super.onCreate();
Calendar cal = new GregorianCalendar();
cal.add(Calendar.MINUTE, 2); //example
this.registerReceiver(thisReceiver, new IntentFilter("BackgroundService"));
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), ONE_MINUTE, "what to put here?"); //example, repeat every minute
}
private void setArrayToDefault(){
//here, the array will be changed back to default values
}
}
My main issue is on how to set the AlarmManager to call thisReceiver everytime it's set. Any idea? Is my approach correct?
Im my app, I'm running a background service that runs regardless that app is running or not.
Please don't. This is why users attack us with task killers and the Force Stop from the Manage Services screen in Settings.
My main issue is on how to set the AlarmManager to call thisReceiver everytime it's set. Any idea?
You are not registering the BroadcastReceiver, so AlarmManager will not be able to contact it.
Please please please please please please please redesign your service such that it does not have to run all of the time. Android will be killing off your service due to old age, anyway, so if you want a reliable and stable app, you need to do this redesign, anyway.