Background operations when app is killed? (Android API 23+) - android

To learn something new, I'm developing an Android APP (min SDK version API 23 and Target SDK Version API 28) that allows me and my family to create and share a virtual shopping list through HTTP requests and JSON responses on a free Web. Everything works fine, but I want to add a feature: I would like to get notified when someone makes a change even when the app is killed or has never been launched. I know what the task could do to compare the changes made on the list and I also know that it is something to be done once every 5 minute (for example), but I don't know how to perform background operations when the app is no longer running and it has been killed from the recent tasks list. I gave the Service class a try, but when the app is killed it stops. So I looked for a solution and I found the BroadcastReceiver and made it able to receive a message whenever the Service stops in order to restart it. But from Android API 26 the BroadcastReceiver must be (I guess..) contex-registered.
So this is what I my main Activity does when the onCreate method is called:
ReceiverCall receiver = new ReceiverCall();
registerReceiver(receiver, new IntentFilter("com.dadex.familyapp.startServiceRequest"));
My ReceiverCall which extends the BroadcastReceiver Class:
public class ReceiverCall extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try{
String action = intent.getAction();
if (action.equals("com.dadex.familyapp.startServiceRequest"))
context.startService(new Intent(context, CheckListService.class));
}
catch (Exception e){
Log.e("ERROR", e.getMessage());
}
}
}
And this is my CheckListService onDestroy method:
#Override
public void onDestroy() {
Intent intent = new Intent("com.dadex.familyapp.startServiceRequest");
sendBroadcast(intent);
}
It works fine when the app is launched, but as soon as I kill it, the receiver won't receive anything. So my question is: what is the best way to perform such background operations? Are there other classes I need to learn first? Thanks a lot!

You need a background service, with a notification to keep it alive.
startForegorund()
Search for startForegorund with notification and you will find what you need.

Related

OnTaskRemoved in Android O

In my android app, I have a Service that starts when the app goes in background. OnStartCommand begins long running task that analyzes and checks device and app status.
Now, I am preparing the app for Android O. First issue that i faced is Services, I rework them to JobServices.
Now I am facing another issue. When user removes my app from application stack JobService.OnTaskRemoved doesn't get called.
Before, when I used Service calling of Service.OnTaskRemoved worked fine for me.
Now I see only way. I need My old Service for handlingService.OnTaskRemoved and new JobServices for executing task.
Am I wrong? May be some one can give me good advice?
You are implementing the wrong concepts.., which creates problem.., To tackle it .. you are again implementing wrong things.. Please offload all...
In my android app, I have a Service that starts when the app goes in background..
The Problem ;
In android O there is no background execution allowed at all.. Even a single line of code is not guaranteed to execute..!!
And you want it to execute long running service..!!
The Solution;
The same service can be started whenever App is opened first time... On acquiring all runtime permissions. As :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, YourLongRunningService.class));
}
else
{
context.startService(new Intent(context, YourLongRunningService.class));
}
OnStartCommand begins long running task that analyzes and checks device and app status.
The Problem ;
OnStartCommand is not meant to be coded the long running procedures / statements of code..
Nor it is meant to be coded at all........
The Solution;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("RUNNER : ", "\nPERFORMING....");
return START_STICKY;
}
Above single line tells android to keep alive ALL THE TIME UNTIL DEVELOPER STOPS IT ON HIS OWN VIA CODE STOPSELF Even removed from background or from recents; It gets re-created automatically by android os
Then where should i write the code.... ??
Wait... its too early to code yet....!!! patience
begins long running task that analyzes and checks device and app status
Your question is un clear and in my brain there is a gradle error ... I can not resolve your symbols :
analyzes
checks device
app status
But i know that these your broadcasts definitely .. And you need to implement broadcast-receivers... to receive it...!!
I will implement Broadcast receivers... Its too easy...
The Problem ;
Wait... Android O do not allows you to implement many broadcast receivers from static receivers like we does... And even we are not allowed to call that receivers on specific intent-actions from manifest.xml
The Solution;
Implement runtime receivers in your above created service YourLongRunningService in onCreate like :
IntentFilter myFilter = new IntentFilter();
myFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
this.registerReceiver(mCallBroadcastReceiver, CallFilter);
CONNECTIVITY_CHANGE is an example and it would be your intent action / broadcast you want to listen for...!!
What is mCallBroadcastReceiver and all...
These are runtime registration of receivers... and needed to be unregistered from onDestroy like :
#Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
super.onDestroy();
}
No.... No... No.... I do not want to un-register it... I want it always working..
Our service is START_STICKY Even if it is destroyed; gets started automatically and registers mCallBroadcastReceiver in onCreate again..
Where is the receiver then....???
In this case mCallBroadcastReceiver is receiver defined in class area where we declares the variables and constants :
public class YourLongRunningService extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// All your receiver code goes here...
}
};
// your constructor
// your onStartcommand
// your ondestroy
}
What notification Manager is doing here....???
In and above O you can not run foreground service without proper Ongoing task notification... It will go in your onCreate which will call Startforeground with the notification to start this service as a foreground service
What below android O...?
It works below Android O too... Just call with normal startservice its code it given on very start...!!
Where is my long running code goes then....???
From receiver receive broadcast you want and start a intentservice or a job or a alarm class or whatever you want...
I will make a simple class which takes context in constructor and defines a public method named LongRunningCode may be of one crore lines of code....
And on receiving broadcast in receiver , I will make a object of that class by passing context of receiver and will simply call LongRunningCode method with that object
Hope it helps

Android update Activity from a Service

I'm so lost with all that workflow of notifications and services in Android. My sceneario is this:
I have an Android application that communicate to a MySQL database through a web-service using JSON-RPC. The data retrieved from the service will be displayed in the application.
The data will get updated over time, so the application needs to listen for changes of this and, if a change occur, show a notification and update the data displayed in the app.
To listen for changes I will need to run an "infinite"(until the app is destroyed or maybe until the app destroys it) thread that from time to time will call a method on th web-service which will return the changes since the last check.
UPDATE: Ok, I have been trying using Service and IntentService, but non of them fits my needs: a Service execute in the Main Thread, so If I perform an infinite loop there my app will freeze, IntentService has it's own worker thread but there is no comunication with the App, and I need it, or at least I need a way to know if the app is in foreground (in this case the notification will not popup but the data will be passed and updated) or in background (int this case the notification will pop up and on click it will direct the user to the app with the updated data)
#1 You can fire a broadcast message from your Service and define a Broadcast receiver in your Activity to receive this broadcast.
SEND BROADCAST-from Service
Intent i = new Intent("ALERT_CHANGE");
i.putExtra("DATA","News");
sendBroadcast(i);
RECEIVE BROADCAST-in Activity
registerReceiver(uiUpdated, new IntentFilter("ALERT_CHANGE"));
private BroadcastReceiver uiUpdated= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
String DATA = i.getStringExtra("Data");
txt.settext(DATA);
}
};
Ok, after a lot of testing and thanks to the info given here I finally found a way to handle with the issue, so I will share it here:
On the IntentService I have a public static AtomicBoolean to control the end of the loop and be able to stop the service.
Then to determine if the Activity is in foreground or not I use the method suggested here https://stackoverflow.com/a/5504711/3107765
With the difference that I use the static modifier there, so I can check it from the service.
if the activity is in foreground I send a broadcast as it was suggested here by Eu. Dr. otherwise I use a notification that once clicked will let the user to the activity.

Android sendBroadcast - waiting for BroadcastReceiver to finish

I'm using a BroadcastReceiver in my Android app which simply contains the following piece of code:
public BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
GcmIntentService.isHandled = true;
Toast.makeText(context, "broadcast receiver test", Toast.LENGTH_SHORT).show();
}
}
I'm using this receiver to determine if my activity is running and carry out some updates in a ListView without having any notifications produced by GcmIntentService.
With the code being simple so far, only creating a toast message, I'm unable to catch the boolean value from GcmIntentService.isHandled as soon as the sendBroadcast is invoked.
Is it possible in any way to determine if the code for my receiver has finished running. I understand that sendBroadcast is an asynchronous call, and I'm making use of Thread.sleep(1000) so far to wait for the isHandled value, but it would be nice if there is a more reliable method on achieving this.
Any thoughts?
Your question can be divided to two parts:
1.How to know that if there is a receiver actually received the broadcast.
2.How should the receiver notify the service that message is been handled.
It seems difficult to achieve the first goal through standard Intent api, instead I suggest you may try the "observer pattern".
You may create a global Observable object in your Application and make your Activity implements Observer, register itself in onCreate() and unRegister in onDestory().Inside the Service you can check if there is an Activity running through countObservers() and then simply notify it.

Android - calling startActivity() from LocationListener.onLocationChanged(), Is this really what I want?

I am writing a foreground service to receive GPS notifications, send system notifications and make calls. The application has no Activity attached to it, only a service that is launched from a boot receiver. When I was trying to start the calling activity from within onLocationChanged() of the service, I got:
Calling startActivity() from outside of an Activity context requires
the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
Fearing the skeptical question, I decided to look at stackOverFlow, where I found these:
Calling startActivity() from outside of an Activity context, Android: Make phone call from service, android start activity from service - all suggesting to do this exact thing.
So, my question is: Why is it inadvisable to use this flag (something about the history stack)? Is it OK to do it in my case?
A simplified code:
public class CallService extends Service implements LocationListener {
#Override
public void onCreate() {
super.onCreate();
startForeground(1, NotificationGenerator.getNotification());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public synchronized void onLocationChanged(Location loc) {
String url = "tel:xxxxxxxxxx";
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
...
}
The answer to that lies purely in User Experience (UX) domain. Android devices are usually personal devices and you should put that in mind while coding your app.
Users are maybe playing a game or making a phone call, launching your activity without any notification is rude and I would uninstall any app that would do that.
Also if the phone is locked your activity will not actually launch instead it will wait until the user unlocks the phone.
Notifications on the other hand are made to tell the user that the app wants to show you something. So use them instead.
Unless you are building a private app then you know what is better for your requirements.

Calling an Activity from a broadcastreceiver, but keep it in the background

I have an alarm set to trigger every n minutes, and it works fine.
However I discovered that reading the application's SharedPreferences from a broadcast receiver caused some problems (It read an older version of those preferences, probably due to a different PID)
I were told that to do what I needed to do, I should call an Activity, that solved the SharedPreferences problem, but created a new one.
The activity must run in the background exclusively. It is essentially a heartbeat, sending off some information to a Presence solution, keeping the users presence alive.
The Alarm Receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent alarmIntent = new Intent(context, AlarmActivity.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(alarmIntent);
}
}
The activity in the manifest
<activity android:name=".AlarmActivity" android:theme="#android:style/Theme.Translucent.NoTitleBar"/>
The Alarm Activity only sends an HTTP update, but even if I remove all but the super.onCreate line, it still forces the application into the foreground, and focus. But it only happens if the application itself is only "minimized" via the home button. If I close it with the back button, it won't get forced into focus, while the heartbeat still fires just fine in the background.
How can I prevent this?
I'm developing for API version 7 (Android 2.1), but can update to API 8 if needed.
Consider using Service for performing background tasks.

Categories

Resources