iOS BackgroundFetch equivalent in Android - android

I would like to know if there is an Android counterpart for iOS BackgroundFetch feature.
I would like my Android app using Cordova to wake up every 15 minutes or so and check for updates and perform some other miscellaneous tasks.
In iOS, I was able to do this by using cordova-background-fetch plugin.
Since there is no Android version of that plugin, I am happy to write it myself; but I would first like to know how I would go about implementing such feature in Android. Any suggestions?

In Android you can set AlarmManger to wakes up every X milliseconds and run a PendingIntent.
This code looks something like this.
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()+60000,
PERIOD,
pi);
Android's default IntentService that runs in the background has some limitations.
You can also take a look at external libary WakefulIntentService (https://github.com/commonsguy/cwac-wakeful). I use that along with AlarmManager to run background tasks.
Updated:
OnAlarmReceiver class
public class OnAlarmReceiver extends BroadcastReceiver {
public static String TAG = "OnAlarmReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Waking up alarm");
WakefulIntentService.sendWakefulWork(context, YourService.class); // do work in the service class
}
}
YourService class
public class YourService extends WakefulIntentService {
public static String TAG = "YourService";
public YourService() {
super("YourService");
}
#Override
protected void doWakefulWork(Intent intent) {
Log.d(TAG, "Waking up service");
// do your background task here
}
}

You can use AlarmManager. Besides that you can also use AccountManager.

Related

Keep service alive after app has been destroyed

I'm developing an app that need to do some check in the server every certain amount of time. The check consist in verify if there are some notification to display. To reach that goal I implemented Service, Alarm Manager and Broadcast Reciever. This is the code that I'm using so far:
public class MainActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
setRecurringAlarm(this);
}
/**
*
* #param context
*/
private void setRecurringAlarm(Context context) {
Calendar updateTime = Calendar.getInstance();
Intent downloader = new Intent(context, MyStartServiceReceiver.class);
downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 60000, pendingIntent);
}
...
}
Receiver class
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent dailyUpdater = new Intent(context, MyService.class);
context.startService(dailyUpdater);
Log.e("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive");
}
}
Service class
public class MyService extends IntentService {
public MyService() {
super("MyServiceName");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("MyService", "Service running!");
// TODO Do the hard work here
this.sendNotification(this);
}
private void sendNotification(Context context) {
// TODO Manage notifications here
}
}
Manifest.xml
<!--SERVICE AND BROADCAST RECEIVER-->
<service
android:name=".MyService"
android:exported="false"/>
<receiver
android:name=".MyStartServiceReceiver"
android:process=":remote"/>
The code works fine, the task in the service will be excecuted periodically. The problem is that the service is destroyed when the app is forced to close. I need to keep alive the service, capable to execute the task, even if the user has closed the app, so the user can be updated via notifications. Thank you for your time!
You can't. If the app is forced closed, that means either its crashed (in which case the service has to be stopped as it may no longer work correctly) or the user force closed it in which case the user wants the app to stop- which means the user doesn't want the service to run. Allowing a service to be automatically restarted even if the user stops it would be basically writing malware into the OS.
In fact, Android went the exact opposite (and correct) way- if the user force stops an app, NOTHING of the app can run until the user runs it again by hand.
You may go through this. I hope this will solve your problem. If you want to keep awake your service it is practically not possible to restart the app which is forced close. So if you disable force stop your problem may be solved.

Using Alarm Manager to execute a task once

I am trying to execute an action once at a later time using AlarmManager. I followed the code and the question here and came up with this.
public class EmailAccountUpdater extends BroadcastReceiver
{
// Constructors
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION))
{
Log.v("Test", " Step 1 - Creating the alarm " );
// Place holder
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent newIntent = new Intent("com.test.EMAIL_ACCOUNTS_CHANGED");
PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, newIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.set( AlarmManager.RTC_WAKEUP, 35000, pendingIntent);
}
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver
{
// constructors
#Override
public void onReceive(Context context, Intent intent)
{
Log.v("Test","Step 2 - Alarm received");
if (intent.getAction().equals("com.test.EMAIL_ACCOUNTS_CHANGED"))
{
onAccountsUpdated();
}
}
public void onAccountsUpdated()
{
// do something
}
}
In the manifestManifest.xml
<receiver android:name="full.path.AlarmReceiver">
<intent-filter>
<action android:name="com.test.EMAIL_ACCOUNTS_CHANGED"/>
</intent-filter>
</receiver>
Basically what I wanted to do was to put the following in Placeholder (just below the first log statement).
Thread.sleep(35000);
onAccountsUpdated();
But according to this, it is not suggestible to use postDelayed and Thread.sleep in BroadcastReceiver. So I came up with this. What happens is I always get the Step 1 but never reach the step 2. What I am I doing wrong? Any help would be welcome.
The solution is (as per the thread you linked):
you want something to happen some time after the broadcast you can start a service, and that service wait the amount of time, or if the amount of time you want to wait is longer than a few seconds, you should just put the launch of this service in the AlarmManager and let the AlarmManager launch the service for you.
Your plan doesn't work because the context is destroyed after EmailAccountUpdater.onReceive returns.

A service in android which send SMS at regular interval

I want to make a service in android which run in background always and start as soon as I boot my phone and send message at a regular interval.I have writen my code as below
MainActivity.class
package test.sai;
public class MainActivity extends Activity {
Timer t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alrm();
Log.e("msg", "in main");
}
public void alrm() {
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
Log.e("msg", "in alrm");
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = v PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
Log.e("msg", "in alrm1");
//updateTime.setWhatever(0);
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, recurringAlarm); //you can modify the interval of course
}
}
This class is calling AlarmReceiver.class
package test.sai;
public class AlarmReceiver extends BroadcastReceiver
{
GPSTracker gps;
#Override
public void onReceive(Context context, Intent intent)
{
gps = new GPSTracker(context);
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context,MainActivity.class);
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(pushIntent);
Log.e("pro", "alrmmanager");
}
Intent myService = new Intent(context, FirstService.class);
myService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(myService);
Log.e("msg", "in alrmmanager1");
}
}
and finally AlarmReceiver is calling the service class
package test.sai;
public class FirstService extends Service{
Timer t;
int time = 0;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onStart(Intent intent, int startId) {
Log.e("time", time++ +"");
Toast.makeText(this, time+1+"", 500).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
Now I want to on GPS as soon as service starts and then I want to use GPS to track location of mobile and send a message to another mobile.I also have code for GPS and sms sending but I am not getting how to call and where to call those methodss,so that my service keep on running and sending messages at some perticular interval.please help.
You can use alarmManager for this... Because if you create your own timerTask, it is very much susceptible to get destroyed by the processor.
To answer your two part question:
First you need to learn how to handle onBoot within Android Framework. Refer to this Q/A Trying to start a service on boot on Android
Lastly you need to understand the SMSManager class. Refer to the documentation http://developer.android.com/reference/android/telephony/SmsManager.html
I don't think anyone should provide complete code for your request as your main problem/question is "How can I help myself and stop looking for others to fix all my problems".
Try registering a BroadcastReceiver with AlarmManager to receive an intent at your regular interval. You'll probably want two, one that listens for a BOOT_COMPLETED action, and another that the AlarmManager will start on interval. You can have the second receiver start a service if whatever you want to do will take a while to execute.
Here's a question on how to make the receiver run on boot so you can register the other receiver with AlarmManager:
Android BroadcastReceiver on startup
Here's another that wants pretty much the same thing you want, minus the SMS:
How to Autostart an AlarmManager to start a Scheduled Activity?

Android - Periodic Background Service - Advice

I am working on an app that will relay information about its location to a remote server. I am intending to do it by doing a simple HTTP post to the web-server and all is simple and fine.
But according to the spec, the app needs to execute itself from time to time, lets say once in every 30 mins. Be independent of the interface, meaning which it needs to run even if the app is closed.
I looked around and found out that Android Services is what needs to be used. What could I use to implement such a system. Will the service (or other mechanism) restart when the phone restarts?
Thanks in advance.
Create a Service to send your information to your server. Presumably, you've got that under control.
Your Service should be started by an alarm triggered by the AlarmManager, where you can specify an interval. Unless you have to report your data exactly every 30 minutes, you probably want the inexact alarm so you can save some battery life.
Finally, you can register your app to get the bootup broadcast by setting up a BroadcastReceiver like so:
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
// Register your reporting alarms here.
}
}
}
You'll need to add the following permission to your AndroidManifest.xml for that to work. Don't forget to register your alarms when you run the app normally, or they'll only be registered when the device boots up.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Here is a semi-different way to keep the service going forever. There is ways to kill it in code if you'd wish
Background Service:
package com.ex.ample;
import android.app.Service;
import android.content.*;
import android.os.*;
import android.widget.Toast;
public class BackgroundService extends Service {
public Context context = this;
public Handler handler = null;
public static Runnable runnable = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Service created!", Toast.LENGTH_LONG).show();
handler = new Handler();
runnable = new Runnable() {
public void run() {
Toast.makeText(context, "Service is still running", Toast.LENGTH_LONG).show();
handler.postDelayed(runnable, 10000);
}
};
handler.postDelayed(runnable, 15000);
}
#Override
public void onDestroy() {
/* IF YOU WANT THIS SERVICE KILLED WITH THE APP THEN UNCOMMENT THE FOLLOWING LINE */
//handler.removeCallbacks(runnable);
Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show();
}
}
Here is how you start it from your main activity or wherever you wish:
startService(new Intent(this, BackgroundService.class));
onDestroy() will get called when the application gets closed or killed but the runnable just starts it right back up.
I hope this helps someone out.
The reason why some people do this is because of corporate applications where in some instances the users/employees must not be able to stop certain things :)
http://i.imgur.com/1vCnYJW.png
EDIT
Since Android O (8.0) you have to use JobManager for scheduled tasks. There is a library called Android-Job by Evernote which will make periodic background work a breeze on all Android versions. I have also made a Xamarin Binding of this library.
Then all you need to do is the following:
In your application class:
public class MyApp extends Application {
#Override
public void onCreate() {
super.onCreate();
JobManager.create(this).addJobCreator(new MyJobCreator());
}
}
Create the following two classes YourJobCreator and YourSyncJob(Where all the work will be done. Android allocates time for all the background jobs to be run. For android versions < 8.0 it will still run with an Alarm manager and background service as per normal)
public class MyJobCreator implements JobCreator {
#Override
#Nullable
public Job create(#NonNull String tag) {
switch (tag) {
case MySyncJob.TAG:
return new MySyncJob();
default:
return null;
}
}
}
public class MySyncJob extends Job {
public static final String TAG = "my_job_tag";
#Override
#NonNull
protected Result onRunJob(Params params) {
//
// run your job here
//
//
return Result.SUCCESS;
}
public static void scheduleJob() {
new JobRequest.Builder(MySyncJob.TAG)
.setExecutionWindow(30_000L, 40_000L) //Every 30 seconds for 40 seconds
.build()
.schedule();
}
}
You should schedule your service with alarm manager, first create the pending intent of service:
Intent ii = new Intent(getApplicationContext(), MyService.class);
PendingIntent pii = PendingIntent.getService(getApplicationContext(), 2222, ii,
PendingIntent.FLAG_CANCEL_CURRENT);
Then schedule it using alarm manager:
//getting current time and add 5 seconds to it
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 5);
//registering our pending intent with alarmmanager
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), pi);
this will launch your service after 5 seconds of current time. You can make your alarm repeating.
You can use Alarm Manager to start Service at specified time and then repeat alarm in specified interval. When alarm goes on you can start service and connect to server and make what you want

Android-Broadcast Receiver

I am new to android. I what to know the difference between Intent and BroadcastReceiver. I am more confused with BroadcastReceiver than Intent.
Please help me out. Simple code will be helpful.
Ok, I will explain it with an example.
Let's suppose I want to create an app to check subway status from it's webpage. I also want a system notification if the subway is not working ok.
I will have:
An Activity to show results.
A Service to check if the subway is working and show a notification if it's not working.
A Broadcast Receiver called Alarm Receiver to call the service every 15 minutes.
Let me show you some code:
/* AlarmReceiver.java */
public class AlarmReceiver extends BroadcastReceiver {
public static final String ACTION_REFRESH_SUBWAY_ALARM =
"com.x.ACTION_REFRESH_SUBWAY_ALARM";
#Override
public void onReceive(Context context, Intent intent) {
Intent startIntent = new Intent(context, StatusService.class);
context.startService(startIntent);
}
}
Explanation:
As you can see you can set an alarm. and when the alarm is received we use an intent to start the service. Basically the intent is a msg which can have actions, an serialized stuff.
public class StatusService extends Service {
#Override
public void onCreate() {
super.onCreate();
mAlarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intentToFire = new Intent(AlarmReceiver.ACTION_REFRESH_ALARM);
mAlarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
}
#Override
public void onStart(Intent intent, int arg1) {
super.onStart(intent, arg1);
Log.d(TAG, "SERVICE STARTED");
setAlarm();
Log.d(TAG, "Performing update!");
new SubwayAsyncTask().execute();
stopSelf();
}
private void setAlarm() {
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
mAlarms.setInexactRepeating(alarmType, SystemClock.elapsedRealtime() + timeToRefresh(),
AlarmManager.INTERVAL_HALF_DAY, mAlarmIntent);
}
}
Explanation:
The service starts and:
Set the alarm for the next call. (Check the intent it's used. Just a msg)
Calls an AsyncTask which takes care of updating an notifying the Activity
It doesn't make sense to paste the AsyncTask but when it finished it calls:
private void sendSubwayUpdates(LinkedList<Subway> subways) {
Intent intent = new Intent(NEW_SUBWAYS_STATUS);
intent.putExtra("subways", subways);
sendBroadcast(intent);
}
This creates a new Intent with a certain NEW_SUBWAYS_STATUS action, put inside the intent the subways and sendBroadcast. If someone is interested in getting that info, it will have a receiver.
I hope I made myself clear.
PS: Some days ago someone explained broadcast and intents in a very cool way.
Someone wants to share his beer, so he sends a broadcast
with an intent having action:"FREE_BEER" and with an extra: "A glass of beer".
The API states:
A BroadcastReceiver is a base class for code that will receive intents sent by sendBroadcast().
An intent is an abstract description of an operation to be performed.
So, a BroadcastReceiver is just an Activity that responds to Intents. You can send your own broadcasts or even the Android Device can send these system wide broadcasts including things like the battery is low, or the device just booted-up.

Categories

Resources