I build an application that manage a database of messages and show them to the user, i have a service that basically connect to web server and asks for updates.
I need that service to run every minute even if the application is closed.
so far i wrote the following code:
protected void registerAlarm() {
Intent getUpdatesService = new Intent(this, UpdatesService.class);
PendingIntent sender = PendingIntent.getBroadcast(this, 0, getUpdatesService, 0);
long firstTime = SystemClock.elapsedRealtime();
firstTime += 60 * 1000;
AlarmManager am = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, firstTime, 60 * 1000, sender);
}
I call registerAlarm() from an activity that shows the messages.
That suppose to use AlarmManager to run the service evry minute but it doesn't work.
can anyone help me solve the problem?
I need that service to run every minute even if the application is closed.
That will not be practical on Android 6.0 and higher.
can anyone help me solve the problem?
Tactically, your problem is that you are using SystemClock.elapsedRealtime() and RTC_WAKEUP. Those do not match. Use ELAPSED_REALTIME_WAKEUP.
However:
Your app will not get control every minute on Android 6.0+, unless perhaps the user adds your app to the battery optimization whitelist in Settings
AlarmManager does not work at all in some environments, notably the current developer preview of Android apps on Chrome OS (though for all I know this is a bug)
You should use IntentService instead of Service because it automatically terminates after work is done plus it run on background thread
Related
I have an activity that demonstrates information ping results about servers. This job is done every second with runnable like below code:
pingRunnable = new Runnable() {
#Override
public void run() {
pingMethod();
resultsNotification();
handler.postDelayed(this, 1000);
}
};
on the other hand, I have to show some results in the notification realtime and I did it, But there is a problem, that in the first when the device was locked after 10 min app and activity was destroyed by OS and just notification stopped in a stagnant status. then I tried to fix it with below code:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
wl.release();
Actually, I used wl.release(); like this:
#Override
protected void onDestroy() {
wl.release();
super.onDestroy();
}
It got better when I did it, but when the device was locked this again happened after some hours.
Right now I don't know exactly how can I control these services (background(Runnable) and foreground(Notification) ) together for keeping alive activity for a long time such as two or three days or even more.
First up you shouldn't be using an Activity to do this kind of work a Service is the recommended approach. To do this kind of work intelligently you have a number of options with the Android framework, most recently the new WorkManager component. These services should offer you the ability to control when your background work is scheduled - e.g. only running when a valid network connection is present and by allowing you to select a period when the work should run.
https://developer.android.com/topic/libraries/architecture/workmanager/advanced
Secondly, polling every second will have a drastic impact on battery life - if you do this most likely your app will be flagged as a bad citizen and be a likely candidate for uninstalling.
You should consider whether polling in general is the best option for your users. Using cloud messaging would improve the amount of work your app needs to do to, i.e. you could just push out a notification when the server data changes, which avoids you having to do the manual polling. https://firebase.google.com/docs/cloud-messaging/
I am working on an Android application in which I have to compare current time , with a time (saved) in a file, though everything is working fine. I have use services and in service i have use THREAD to run the service infinitely, and in addition to this i have also used PARTIAL_WAKE_LOCK to continue service even the device is sleep but the issue is that instead of acquiring PARTIAL_WAKE_LOCK my service runs for 1/2 hours and then again go to sleep. I don't want to acquire FULL_WAKE_LOCK. Is there any one who can guide me what i have to do in order to run this comparison, i.e. my service will run perfectly once the user set the time.
Thank you in advance.
You are doing it the wrong way. To create permanent service you must
declare it as foreground. No other way about it:
myService.startForeground(MY_NOTIFICATION_ID, my_notification);
If your interest with such a service is to periodically perform fast-ending
actions, and if the in between periods are long, you probably want to use
the alarm API and improve your app's battery consumption.
Edit:
To set a foreground service you must supply the system with a notification
object to be displayed at notification bar for as long as the service is in foreground
Why is that? Because foreground services cannot be killed, and Android needs to know
that the user is aware of that fact.
Setting as foreground:
static final int NOTIF_ID = 100;
// Create the FG service intent
Intent intent = new Intent(getApplicationContext(), MyActivity.class); // set notification activity
showTaskIntent.setAction(Intent.ACTION_MAIN);
showTaskIntent.addCategory(Intent.CATEGORY_LAUNCHER);
showTaskIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntent = PendingIntent.getActivity(
getApplicationContext(),
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notif = new Notification.Builder(getApplicationContext())
.setContentTitle(getString(R.string.app_name))
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pIntent)
.build();
startForeground(NOTIF_ID, notif);
And reverting to 'stardard' service mode:
stopForeground(true).
Both setting to foreground and reverting to background can be called by either the service itself (e.g. its onCreate() method) or by external code (e.g. the activity that initiated the service). No problems here.
I need some suggestions for approaches to take...
Here's some background info:
Right now I have an Android app and a separate java program running on my server.
The java program continuously go out and gets information from different sites and stores them in 14 different entries in an SQL database on the server.
The Android app then queries the databases to retrieve the info to be displayed.
My goal:
I need suggestions on how to have the app handle checking for updates from the database, and then letting the user know that there is new information.
My first thought is that maybe I need to start a separate thread that queries the database for a time modified. Then if it finds updates, it would pop up on the screen that there is new information.
I'm not too well educated with the way threads or services work, so I guess I'm looking for how to implement this, or whether there is a completely different way to go about update checking that would be better.
Thanks in advance, I appreciate any feedback, input, or suggestions.
Hi Ryan I have also implemented a similar thing in my android app and surprisingly I also had 14 tables in my PostgreSQL Server. First of all, you would want to poll the server periodically even when the app is not in the foreground. For that you need to run a background Service - here you will have to manually create a thread in the service, because Service by default runs on the UI thread OR use an IntentService - you don't have to create a separate thread. Whatever code you write in the intent service will be handled in a different thread automatically
Now you have to make this service execute periodically. For that use an AlarmManager and use the setRepeating()function. In the arguments you have to give a PendingIntent to your Service or IntentService. But don't use an alarm manager if you are going to poll the server for every less than 1 minute. Because the battery will be wasted a lot.
Here is some code that might give you an idea :
function setalarm()
{
Intent intent = new Intent(getBaseContext(), Intent_Service.class);
PendingIntent sender = PendingIntent.getBroadcast(getBaseContext(), 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Random randomGenerator = new Random();
long interval=60000; //1 minute in milliseconds
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(),interval,sender);
}
This is Intent_Service of type IntentService :
public class BackService extends IntentService
{
Context context=this;
//public Timer t=null;
public BackService()
{
super("myintentservice");
}
#Override
protected void onHandleIntent(Intent intent)
{
try
{
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
wl.acquire();
//..CPU will remain on during this section..
//make our network connections, poll the server and retrive updates
//Provide a notification if you want
wl.release();//Release the powerlock
}
}
}
But if you want instantaneous updates, then use Google Cloud Messaging Services. To know more about how it works see this
Hope this helps you.
After a long search I'm still confused about it although I found some related posts but they were not answering what I was looking for. in my scenario I want to send user's lat long at fixed intervals like every 5 minutes to a server. to do this I used a service with its own process so that it doesn't get killed when Activity destroyed and in service method onStartCommand I used a while loop having condition of always true and in that loop I update location to server and give delay by thread.sleep like shown below
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
While(true)
{
Location currentLocation = getLocation();
updateLocationToServer(currentLocation);
try
{
Thread.sleep(300000)
}
catch(Exception e)
{
e.printStackTrace()
}
}
return Service.START_STICKY;
here I cannot understand the return statement is unreachable then how can the service will be restarted automatically when it is destroyed and secondly using thread.sleep causing ANR (Application Not Responding) while service is a background process and I found that its directly running in UI thread these information are confusing me and in this case what is the best way to get desired functionality.
You should use and AlertManager instead!
AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, OnAlarmReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), PERIOD, pi);
http://justcallmebrian.com/?p=129
secondly using thread.sleep causing ANR (Application Not Responding) while service is a background process
from
http://developer.android.com/reference/android/app/Service.html
Note that services, like other application objects, run in the main thread of their hosting process.
Try using Alarm Manager instead, see this example of how to set it to repeat every 5 minutes
I'm reading a lot of conflicting information on this topic, so going to ask myself with some specific code examples. My Android app is getting "Network Unavailable" errors when trying to make an HTTP request from a background service, only when the phone is asleep. The phone is using the mobile network only when I get these errors (no wi-fi in the building).
I use this code to schedule my service:
static private void SchedulePoll(Context context,int minsFromNow)
{
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, minsFromNow);
Intent intent = new Intent(context, PSDroidBroadcastReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
}
My service acquires a PARTIAL_WAKE_LOCK and then calls:
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
At that point I'm getting a Network Not Available exception, only when phone in sleep mode.
Is it normal to have issues like this in sleep mode, or should I be able to make an Internet connection from my service? It seems like lots of apps check email and other things, so it should be normal and work most of the time?
I looked through the phones settings and made sure anything that was related to background connections was enabled. It is a Sprint HTC, Evo I think.
Turns out it was an application on the phone called "Juice Defender". I guess it is designed to save battery life, as soon as we disabled it, my app works. GMai also wasn't working with it enabled, so I feel pretty safe that there isn't much I could have done to design my app better... other than making the error message more intuitive.
Even with a Partial_Wake_Lock you need something like:
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY,
Settings.System.WIFI_SLEEP_POLICY_NEVER);
Taken from: How do I keep Wifi from disconnecting when phone is asleep?