Android Notifications by Service - android

I have been trying to develop this features for days and just keep getting errors and bugs. I am making an app that will notify users when it's time to pray. I have all the prayer times inside a db downloaded from a server in json format. The data is all correct as I have checked multiple times.
I have created a Service that will set Alarm using AlarmManager.
Then I bind my MainActivity to the Service. From the main activity I set Alarm using a method from the service called setAlarmAccordingToDB().
The problem is when I bind my service. The service gets destroyed when app is closed. Upcoming notifications are not notified.
Then I tried to start the service and bind it to my activity.Called setAlarmAccordingToDB(). What happened was setAlarmAccordingToDB was called repeatedly. It kept setting up new alarms non-stop.
Any advice on how upcoming notifications should be set?

You probably need to use a Wakeful service, so the device/process wakes up when the alarm is called.
I have used this code for a while in my app (not the project, just modified my code from Mark's examples) with great results.
https://github.com/commonsguy/cwac-wakeful

I tried to use a separate class for broadcastReceiver and it seems to work. I just used Alarm Manager and BroadcastReceiver. After the revised code, my app could fire the notifications even when the phone screen is turned off and app closed.
Before this i used:-
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
displayNotification();
}
};
Now, I created a class:-
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager;
notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
displayNotification(context);
}
}
In the AndroidManifest.xml I added
<receiver android:name=".Receiver" android:process=":remote"></receiver>

Related

How to make an activity start without clicking notification even when the app is closed?

I have an app where users can call each other through an SDK. Everything is working fine. I just need to be able to make calls like fabebook and whatsapp even when the app is closed. It should be able to start a particular activity even when the app is completely closed. I've followed some stackoverflow questions and I tried using the notification receiver but Its not working.
NotificationReceiver:
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent intentNotification = new Intent();
intentNotification.setAction("com.start.app");
context.sendBroadcast(intentNotification);
}
}
Manifest:
<receiver
android:name=".Notifications.NotificationReceiver"
android:enabled="true"
android:exported="false"></receiver>
What exactly you looking for ..
This can be done by creating a broadcast receiver class and send a broadcast when message received and on your broadcast receivers onReceive method call the specific activity you wish to open.
Dont forget to add the reciever in your manifest
Not tested but i think it will work..

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: Reminder concept with Alarm Manager

I tried to make reminder application for Android, followed tutorial from this website Set Notification for Specific Date. Basically it used Alarm Manager to create a reminder.
This code used to call alarm manager and show notification on specific date.
reminderClient.setAlarmForNotification(calendar, uniqueid, interval);
I save all of the reminder in SQLite Database. So when this code (above) called, new record will be inserted to database and when notification show up, that record will be deleted.
The problem is whenever device restart, alarm manager stopped.
So I create a new BroadcastReceiver that receive event when device turned on.
<application ... >
<receiver android:name=".ReminderReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</intent-filter>
</receiver>
</application>
public class ReminderReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//do stuff
}
}
Is it OK to get all record from database, and call setAlarmForNotification again inside OnReceive like this?
public class ReminderReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
List<MyReminder> reminders = database.getAllReminder();
Calendar cal = Calendar.getInstance();
for (int i=0; i<reminders.size(); i++) {
cal.setTime(parseStringDateToDate(reminders.get(i).getDateTime());
reminderClient.setAlarmForNotification(
cal,
reminders.get(i).getUniqueID(),
reminders.get(i).getInterval()
);
}
}
}
Or is there a better way?
BroadcastReceiver's onReceive() is called on UI thread so in common case it's not right to access a database or do any other file I/O in this method. For this task you need two things: background thread to give the system an ability to make its stuff in parallel and a Service to tell the system that it should not kill your process when onReceive() is finished. There is a component that gives you both things - IntentService. It's a Service and a working thread that finishes and stops a Service when return from onHandleIntent().
Also posibly you will need a WakeLock to ensure that all your calculations are finished and alarms are properly set. Look at WakefulBroadcastReceiver that is written just for this case.
NOTE: Actually in your case file I/O is really minimal and system boot probably is not a moment when every hundred milliseconds are crucial. But there is really no reason not to do things right.

How to automatically restart a service even if user force close it?

I want a service to run all the time in my application. So I want to restart it even if it is force closed by user. There is definitely a way to do it as apps like facebook are doing it. It's not done using push notification, facebook restarts its service even if internet is off.
First of all, it is really very bad pattern to run service forcefully against the user's willingness.
Anyways, you can restart it by using a BroadcastReceiver which handles the broadcast sent from onDestroy() of your service.
StickyService.java
public class StickyService extends Service
{
private static final String TAG = "StickyService";
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
sendBroadcast(new Intent("YouWillNeverKillMe"));
}
}
RestartServiceReceiver.java
public class RestartServiceReceiver extends BroadcastReceiver
{
private static final String TAG = "RestartServiceReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "onReceive");
context.startService(new Intent(context.getApplicationContext(), StickyService.class));
}
}
Declare the components in manifest file:
<service android:name=".StickyService" >
</service>
<receiver android:name=".RestartServiceReceiver" >
<intent-filter>
<action android:name="YouWillNeverKillMe" >
</action>
</intent-filter>
</receiver>
Start the StickyService in a Component (i.e. Application, Activity, Fragment):
startService(new Intent(this, StickyService.class));
OR
sendBroadcast(new Intent("YouWillNeverKillMe"));
You have to create a sticky service with overriding onTaskRemoved method, where you can set an alarm service to trigger your code again.
public class BackgroundService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
//create an intent that you want to start again.
Intent intent = new Intent(getApplicationContext(), BackgroundService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
super.onTaskRemoved(rootIntent);
}
}
Also in some devices like Xiaomi, Huwaei the app gets force closed once it's removed from recent apps. This is because the manufacturers have task manager features which improve ram/battery performance.
You can check this link for more information: https://stackoverflow.com/a/41360159/2798289
As per the Android document
Starting from Android 3.1, the system's package manager keeps track of applications
that are in a stopped state and provides a means of controlling their launch from
background processes and other applications.
Note that an application's stopped state is not the same as an Activity's stopped
state. The system manages those two stopped states separately.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped applications in the
list of potential targets to resolve against.
FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped applications from the
list of potential targets.
When neither or both of these flags is defined in an intent, the default behavior is to
include filters of stopped applications in the list of potential targets.
Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
It does this to prevent broadcasts from background services from inadvertently or
unnecessarily launching components of stopped applications. A background service
or application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped applications.
On Force stop of app, Android just kill the process ID. No warnings, callbacks are given to service/activities. As per the Android document, When the app is killed there are chances that it calls onPause().
When I tried in my app, even onPause() was not called. I think the only way is use to FLAG_INCLUDE_STOPPED_PACKAGES intent flag and send it from another app
If I understand correctly, then actually this is not possible, Android feature to force close application was designed to allow user to get rid of unwanted applications, so it disallows any activities from it until user again starts any of its Activity.
Restart the service even if app is force-stopped and Keep running service in background even after closing the app How?
Whenever a service is killed, its onDestroy method is always called.
Its better to use a BroadcastReceiver to start your service when it is killed.
Here is a sample code illustrating its implementation:-
#Override
public void onDestroy() {
Intent in = new Intent();
in.setAction("StartkilledService");
sendBroadcast(in);
Log.d("debug", "Service Killed");
}
Then register a receiver in AndroidManifest.xml:-
<receiver android:name=".app.ServiceDestroyReceiver" >
<intent-filter>
<action android:name="StartKilledService" >
</action>
</intent-filter>
</receiver>
Finally,create a BroadcastReceiver,and start your service in the onReceive method:-
#Override
public void onReceive(Context context, Intent intent) {
Log.d("debug", "ServeiceDestroy onReceive...");
Log.d("debug", "action:" + intent.getAction());
Log.d("debug", "Starting Service");
ServiceManager.startService();
}
Hope this helps.
on the service's startCommand method return START_STICKY. generally it tell the OS to start the service when it is killed.
If the situation allows to use 'root' it's usually possible to implement Humpty-Dumpty paradigm.
Your application (1st) installs another application (2nd, taking APK from assets) and runs the service of the 2nd app.
2nd app's service bind to the 1st app service and rebinds when disconnected. The 1st app does the same.
Sure it will not help when all apps are killed by some Free RAM or similar application but when Android kills either of those two, the other one will restart its counterpart.
The only real solution for keeping services alive ist to call Service.startForeground(...) with a provided Notification. This will be the only valid solution, every other one will be very dependent on how Google will change the behaviour of it's system. With every API update, Google could prevent every other hack.
This also keeps the user aware, that your app is performing some background task which will keep the app alive and the user has to stop this. If you provide the user the ability to stop it is part of your application, though.
See the Documentation:
void startForeground (int id, Notification notification)
Make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state. By default services are background, meaning that if the system needs to kill them to reclaim more memory (such as to display a large page in a web browser), they can be killed without too much harm. You can set this flag if killing your service would be disruptive to the user, such as if your service is performing background music playback, so the user would notice if their music stopped playing.
There is a very hacky solution to keep service running even you force stop it. I do not recommend that because it is against user willingness. You can define a broadcast receiver to receive intent with action X. onStartCommand handler of your service, broadcast X (if the service is not started yet). on broadcast receiver upon receipt of X, first start the service, then, sleep for some minutes, and finally re-broadcast X.
I think the only foolproof solution here is to have 2 services in separate processes (android:process="somecustomprocessname" in manifest, in the service entry) that both listen to broadcasts and restart each other, because currently the UI doesn't let users kill multiple processes in one action. You can then set up a pinger thread in each service that checks if the other service is running every 100 milliseconds or so, and if not, attempts to restart it. But this is starting to look more and more like malware...

A service will always receive the Broadcast Action that registered for?

I have created a service which is supposed to receive the android.bluetooth.device.action.ACL_DISCONNECTED/ACL_CONNECTED events.
I am aware that services in android may be restarted/stopped when android decides.
However, I am wondering whether a service is always guaranteed to receive the events it registered for, even it has been killed by android?
I assume this means that android will need to restart a killed service which has registered to listen to events when that event takes place.
Is the above assumption correct ?
Thank you very much for the quick reply.
Let me give some more information, sample of the code follows:
public class my_service extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
IntentFilter filterDisconnected = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiverDisconnected, filterDisconnected);
...
}
private final BroadcastReceiver mReceiverDisconnected = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
...
}
}
...
}
So with this code the BroadcastReceiver is implemented within the service class.
This code is working fine under normal cirmustances but are you saying that this is not proper and a different class (BroadcastReceiver ) is needed ?
If the above is proper, i am wondering if this service class is stopped for any reason, when the relevant event is raised, the class will be restarted and the BroadcastReceiver will get the event.
Hi all, i have created a service which is supposed to receive the android.bluetooth.device.action.ACL_DISCONNECTED/ACL_CONNECTED events.
That should not be possible. Those are documented as being broadcast actions; if true, then they can only be picked up by a BroadcastReceiver.
However, i am wondering whether a service is always guaranteed to receive the events it registered for, even it has been killed by android ?
Again, services should never "receive" those events directly.
However, if you create a BroadcastReceiver and put it in the manifest with an <intent-filter> for your desired broadcasts, then that BroadcastReceiver is "guaranteed to receive the events it registered for", and that BroadcastReceiver can call startService() to send a command to an IntentService if desired.

Categories

Resources