How to keep service alive when remove app from stack - android

I want to show notification every minute using Alarm Manager, I have implemented below code, it's working fine but the problem is when I remove app from stack the service is not running.
I want keep alive, I have tried START_STICKY in onStartCommand and also used onTaskRemoved but it's same.
I also tried to implement using WakefulIntentService but the problem is same. My code is below.
In MainActivity
Intent myIntent = new Intent(NotificationDemo.this, MyReceiver.class);
myIntent.putExtra("title", "2 minutes");
Random random = new Random();
int m = random.nextInt(9999 - 1000) + 1000;
Log.d("m::: In Notification", m + "");
myIntent.putExtra("id", m);
pendingIntent = PendingIntent.getBroadcast(NotificationDemo.this, m, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
// alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),alarmManager.Inte pendingIntent);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
1 * 60 * 1000,
pendingIntent);
MyService
public class MyAlarmService extends Service {
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String title = intent.getStringExtra("title");
int id = intent.getIntExtra("id", 0);
mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(), MainActivity.class);
Notification notification = new Notification(R.mipmap.ic_launcher, title, System.currentTimeMillis());
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Log.d("id::", id + "");
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(), id, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
// notification.setLatestEventInfo(this.getApplicationContext(), "AlarmManagerDemo", "This is a test message!", pendingNotificationIntent);
NotificationCompat.Builder builder = new NotificationCompat.Builder(MyAlarmService.this);
notification = builder.setContentTitle(title)
.setContentText("Hellooo...")
.setTicker("Good Evening...")
.setSmallIcon(android.R.drawable.ic_btn_speak_now)
.setVibrate(new long[]{1000, 1000, 1000, 100})
.setLights(5, 5, 5)
.setContentIntent(pendingNotificationIntent).build();
mManager.notify(id, notification);
startForeground(1337, notification);
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// sendBroadcast(new Intent("IWillStartAuto"));
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// sendBroadcast(new Intent("IWillStartAuto"));
// Intent intent = new Intent(getApplicationContext(),MyReceiver.class);
// sendBroadcast(intent);
}
}
and this is my receiver
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String title = intent.getStringExtra("title");
int id = intent.getIntExtra("id", 0);
Intent service1 = new Intent(context, MyAlarmService.class);
service1.putExtra("title", title);
service1.putExtra("id", id);
context.startService(service1);
}
}
In Manifest
<receiver android:name=".MyReceiver">
<!--<intent-filter>
<action android:name="IWillStartAuto"/>
</intent-filter>-->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".MyAlarmService"
android:enabled="true"
android:stopWithTask="false" />

You need to start your service in foreground.
You are missing something this in your service OnCreate() method.
startForeground(1337, notification);
return START_STICKY;
And don't stop your service in your activities or fragments onDestroy() methods.

I tested this code on my phone with android 6.0 and on emulator with android 7.0 in both is working fine, even removing the application from the stack. The notification still working even removing the receiver code.

You can try with receiver configuration process=":remote" to keep receiver alive. I faced with this problem and here is my solution.

Did you try the code with any other output statements? Notifications are, off-late, not being fired for me either - I might blame Instant Run, nevertheless could you try replacing the notification-firing code snippet with maybe something like a Toast? Since Toasts don't work in services, maybe you could try creating a file in your external storage directory whenever the service starts to know that maybe it's up and running?

Related

Run Android Notifications when App is closed without GCM/Firebase

I am working on an App where I want to show Push Notifications. Please note that since it is my client's requirement NOT to use any third party services, so using GCM/Firebase is out of question.
I am successfully able to show the notification from Service using the below code.
public class SendNotificationService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
CharSequence title = "Notification Title";
CharSequence message = "This is a test notification.";
Drawable drawable= ContextCompat.getDrawable(this,R.drawable.brand_icon_color);
Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.brand_icon_small_color)
.setLargeIcon(bitmap)
.setAutoCancel(true)
.setContentTitle(title)
.setOngoing(false);
mBuilder.setContentText(message);
mBuilder.setTicker(message);
mBuilder.setWhen(System.currentTimeMillis());
NotificationManager notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(), 0);
mBuilder.setContentIntent(pendingIntent);
notificationManager.notify(0, mBuilder.build());
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Notifications Stopped...", Toast.LENGTH_LONG).show();
}
}
I am starting this service through my AsyncTask onPostExecute method.
Intent intentService = new Intent(context, SendNotificationService.class);
context.startService(intentService);
I created this following a number of tutorials and found that if I will go to my Running Apps in Android Settings, I will be able to see this service running. But I was unable to locate any such service.
Now the problem is when I close my Application, the notification also disappears. I want it to stay until the user takes any action.
In addition to this, I want this service to start with phone startup even if the app is not started.
1) Add the permission to the manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2) Add a receiver to the manifest to run on boot:
<receiver android:name="com.example.MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
In MyBroadcastReceiver.java:
package com.example;
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, MyService.class);
context.startService(startServiceIntent);
}
}

Non protected broadcast causes crash on starting of app

I made a service for receiving notification, every time data is updated at the back end. Here's the code for the service:
public class FeedbackService extends IntentService {
public FeedbackService() {
super("FeedbackService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("MyService", "About to execute feedback call");
feedbackCheckCall(this);
}
private void feedbackCheckCall(final Context context){
//Call for getting checking data from backend.
}
private void sendNotification(Context context) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher_icon)
.setContentTitle("Feedback Reply")
.setContentText("You've a reply waiting for your feedback!")
.setVibrate(new long[]{500,500,500});
Intent notificationIntent = new Intent(context, navHomeActivity.class );
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Add as notification
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
}
Here's the code for the reciever :
public class FeedbackRecieiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent dailyUpdater = new Intent(context, FeedbackService.class);
context.startService(dailyUpdater);
Log.d("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive");
}
}
Here's the code from where I call it:
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getDefault());
updateTime.set(Calendar.HOUR_OF_DAY,0);
updateTime.set(Calendar.MINUTE, 0);
updateTime.set(Calendar.SECOND, 0);
long intervalTime = 2*60*60*1000; //in milliseconds format is : h*m*s*1000
Intent intent = new Intent(context, FeedbackRecieiver.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intent,PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,updateTime.getTimeInMillis(),intervalTime,pendingIntent);
My manifest declarations are :
<service android:name=".navFragments.feedbackSuppport.FeedbackService"/>
<receiver android:name=".navFragments.feedbackSuppport.FeedbackRecieiver"/>
The app is crashing when I use a signed copy with this error on startup:
Sending non-protected broadcast com.motorola.motocare.INTENT_TRIGGER from system 6836:com.motorola.process.system/1000 pkg com.motorola.motgeofencesvc
java.lang.Throwable
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18179)
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18779)
at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:512)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2905)
at android.os.Binder.execTransact(Binder.java:565)
Can someone please help me out with this? I'm really stuck here. Thanks in advance.
So, there was no issue with broadcast receiver or the service. The issue was while using proguard. I was not using it correctly. I had disabled it in the debug variant and enabled it in the release variant. The app was crashing due to that.

Notification created in BroadcastReceiver doesn't work, on app close

This is my code. It works fine, if I use this in a separate Android studio project. But when I integrate the code to another project it is causing a problem.
If app is open I am able to receive the notifications. But on app close, the notifications are not received.
Also I have observed one thing - I set my alarm at 1:10 (let's say) and close, and re-open the app at 1.09. I am receiving the notification at 1.10 !!.
I am not able to identify what's happening. Please tell me even if am doing silly mistake, Thank you.
public class BroadCast {
public void broadcastIntent(int selected, Context context, long userMilli) {
Intent intent = new Intent(context.getApplicationContext(), ReminderReceiver.class);
Bundle bundle = new Bundle();
bundle.putInt("selected", selected);
intent.putExtras(bundle);
intent.setAction("android.media.action.DISPLAY_NOTIFICATION");
intent.addCategory("android.intent.category.DEFAULT");
Calendar calendar = Calendar.getInstance();
long curMilli = calendar.getTimeInMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), selected, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + (userMilli-curMilli), pendingIntent);
else
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + (userMilli-curMilli), pendingIntent);
}
}
Above code creates an intent and broadcast using alarmManager.
public class ReminderReceiver extends BroadcastReceiver {
public ReminderReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
int selected = bundle.getInt("selected");
sendNotification(context, selected);
}
private void sendNotification(Context context, int selected) {
String notificationContentText = "String to display";
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.alarm)
.setContentTitle("Title")
.setPriority(Notification.PRIORITY_MAX)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentText(notificationContentText)
.setColor(Color.rgb(58,95,205));
notificationManager.notify(selected, builder.build());
}
}
Above code building the notification
This is my AndroidManifest file
<receiver
android:name=".ReminderReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
It was not the problem of BroadcastReceiver or the Service. I had to change my notification settings in my mobile. I use Asus, there you have to check power management option. If it is in power saving mode then the notifications are denied on app close.

Android service gets killed on swiping out the application

I have an Android Service class the code for which is as follows:
public class LoginService extends Service {
BroadcastReceiver wifiStateChangeReciever;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("AndroidLearning", "Service onStartCommand Started.");
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("AndroidLearning", "Service Started.");
final IntentFilter intentFilter = new IntentFilter();
// intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
intentFilter.addAction("android.net.wifi.STATE_CHANGE");
wifiStateChangeReciever = new WifiStateChangeReciever();
this.registerReceiver(wifiStateChangeReciever, intentFilter, null, null);
Log.i("AndroidLearning", "Reciever Registered.");
}
#Override
public void onDestroy() {
Log.i("AndroidLearning", "Service Destroyed.");
this.unregisterReceiver(wifiStateChangeReciever);
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.w("AndroidLearning", "On Task Remove: FLAG_STOP_WITH_TASK - "
+ ServiceInfo.FLAG_STOP_WITH_TASK);
this.unregisterReceiver(wifiStateChangeReciever);
Intent restartServiceIntent = new Intent(getApplicationContext(),
this.getClass()); restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(
getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
Log.w("AndroidLearning", "End on task removed");
super.onTaskRemoved(rootIntent);
}
}
It registers a BroadcastReciever. The Activity which starts this service has the following code:
Intent intent = new Intent(this, LoginService.class);
startService(intent);
However whenever the Activity is swiped out from the task list (recent) the service is also stopped. I over rode the onTaskRemoved to remedy it but it still does not seem to work and the AlarmManager never starts the pendingIntent. I have tries using both method: set and setExact for the AlarmManager.
I also tried adding the following options to <service> tags
android:stopWithTask="false"
android:process=":remote"
but to no avail.
What am I doing wrong here? Thanks for the help.
I finally found the answer to my own problem. It seems this was a problem with the particular flavor of android that I was running on my phone (Mi UI). There was a separate setting regarding each application whether it needed to be allowed to be restarted or not.
Unless this setting is configured no amount of changing permissions and setting Alarms helped me.
This is a different approach from you but I recently fixed this by adding a notification when the service was running
private void showNotification(){
NotificationCompat.Builder builer = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("Service active")
.setContentText("Your service keeps running")
.setOngoing(true);
mNotificationManager.notify(NOTIFICATION_ID, builer.build());
}
The notification is shown in onStartCommand and dismissed in the service ondestroy method.
You need to start service in foreground if you don't want android to shut it down.
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
http://developer.android.com/guide/components/services.html#Foreground
If you try this on some devices, sadly, it won't work.
Some OEMs decided to change the normal behavior of what happens when you remove an app from the recent tasks, so they become semi-disabled:
https://issuetracker.google.com/issues/122098785
https://dontkillmyapp.com/

Android Notification with AlarmManager, Broadcast and Service

this is my code for menage a single notification:
myActivity.java
public class myActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
cal = Calendar.getInstance();
// it is set to 10.30
cal.set(Calendar.HOUR, 10);
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 0);
long start = cal.getTimeInMillis();
if(cal.before(Calendar.getInstance())) {
start += AlarmManager.INTERVAL_FIFTEEN_MINUTES;
}
Intent mainIntent = new Intent(this, myReceiver.class);
pIntent = PendingIntent.getBroadcast(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager myAlarm = (AlarmManager)getSystemService(ALARM_SERVICE);
myAlarm.setRepeating(AlarmManager.RTC_WAKEUP, start, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pIntent);
}
}
myReceiver.java
public class myReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent i) {
Intent myService1 = new Intent(c, myAlarmService.class);
c.startService(myService1);
}
}
myAlarmService.java
public class myAlarmService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
displayNotification();
}
#Override
public void onDestroy() {
super.onDestroy();
}
public void displayNotification() {
Intent mainIntent = new Intent(this, myActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pIntent)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_noti)
.setTicker(getString(R.string.notifmsg))
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.notifmsg));
nm.notify(0, builder.build());
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
...
...
...
<service android:name=".myAlarmService" android:enabled="true" />
<receiver android:name=".myReceiver"/>
IF the time has NOT past yet everything works perfectly. The notification appears when it must appear.
BUT if the time HAS past (let's assume it is 10.31 AM) the notification fires every time... when I close and re-open the app, when I click on the notification... it has a really strange behavior.
I can't figure out what's wrong in it. Can you help me please (and explain why, if you find a solution), thanks in advance :)
Place display notification inside an if statement , such that compare the current time with the notification set time and if the current time is before the set time then display notification, else do nothing.
int temp = calTemp.getTime().compareTo(calendar.getTime());
if(temp > 0){
}else{
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(),
pendingIntent1);
}
here calTemp gives current time and calender gives the time i want to fire the alarm. So according to above code if the time has already past then the notification will not fire for sure .
Hi I've had the same problem and found a solution in this SO post, basically the idea is to rely on AlarmManager, Receiver but avoid usage of Service.
Since you are using the Service just to build and display the notification you may find useful my approach.
Let me know.

Categories

Resources