Oreo, foreground service stops when closed - android

I am using service as foreground one.
on android pre O versions everything works fine.
but in android Oreo when i close app, the foreground service also closed...
here how i start service:
val i = Intent(activity, MyService::class.java)
ContextCompat.startForegroundService(activity, i)
and than inside service onStart:
val builder = NotificationCompat.Builder(context, MY_CHANEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(resultPendingIntent)
val notification = builder.build()
startForeground(notificationId, notification)
service in manifest:
<service
android:name=".data.service.MyService"
android:exported="true"
android:enabled="true"
/>
any idea why it closed with app and how prevent it?
thanks!

Use JobIntentService instead of Service.
https://developer.android.com/reference/android/support/v4/app/JobIntentService.html

Related

Refresh activity from notification, without recreating it

i am trying to implement notifications in my android application.
when the user clicks on the notification i run the activity if it isn't already running .. but if the activity is already running i don't want to recreate it, i just want to refresh the data by intercepting the intent from the onNewIntent function.
the problem is that every time I click on the notification, the activity is recreated, and the onNewIntent function is not called.
the problem occurs when I create the notification from a service.
but when I create the notification from the same activity that I am going to run, everything works fine.
I searched the internet and tried all the solutions I found, but it still doesn't work
I tried several combinations of intent flags, but nothing works
this is my code
val intent : Intent = Intent(this, HomeActivity::class.java)
finalIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
val pendingIntentFlags : Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
{
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
}
else
{
PendingIntent.FLAG_UPDATE_CURRENT
}
val pendingIntent : PendingIntent? = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(finalIntent)
getPendingIntent(0, pendingIntentFlags)
}
val notification = NotificationCompat.Builder(context, type.channelId)
.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(Notification.CATEGORY_SERVICE)
.setDefaults(Notification.DEFAULT_ALL)
.setAllowSystemGeneratedContextualActions(true)
.setOnlyAlertOnce(true)
.setAutoCancel(true)
.setLocalOnly(true)
.setOngoing(false)
.setSilent(false)
.setSmallIcon(R.drawable.icon_notification)
.setContentIntent(pendingIntent)
.build()
notificationManager?.notify(NOTIFICATION_ID, notification)
Let your notification send a broadcast.
In your activity you should register a dynamic broadcast receiver.
This will allow you to refresh the content in the activity without reloading it.
For the case that the activity is not running, you should define a broadcast receiver in the manifest which starts the activity.
when your activity starts, disable the broadcast receiver and re-enable it when your activity stops.
You can just set launch mode attribute to singleInstance in the manifest on your activity and start it with FLAG_ACTIVITY_NEW_TASK only.

Show push notifications only when app is in background [duplicate]

This question already has answers here:
How to know if my application is in foreground or background, android?
(9 answers)
Closed 2 years ago.
I'm using pushy.me push notification service in my android app. It works fine, but I only want to show the push notification when this app is NOT running in foreground.
This are the lines where I build the notification:
// Prepare a notification with vibration, sound and lights
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setAutoCancel(true)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(notificationTitle)
.setContentText(notificationText)
.setLights(Color.RED, 1000, 1000)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, MyApp.class), PendingIntent.FLAG_UPDATE_CURRENT));
// Automatically configure a Notification Channel for devices running Android O+
Pushy.setNotificationChannel(builder, context);
// Get an instance of the NotificationManager service
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
// Build the notification and display it
notificationManager.notify(1, builder.build());
How can I check if the app is running in foreground?
Thanks!
You can achieve this at the activity level by having a flag that you set to true in onResume and set to false in onPause. It depends on the particular architecture of your application, but there is no way to know if an App is in the foreground, only if an Activity is.

startForegroundService - unable to use setContentIntent + addAction?

Unfortunately another question about my startForegroundService notification... I searched, really, I did:
I have a foreground service that is running perfectly. I would like to add a couple of actions to this notification. For one, make it so when the user clicks the notification they are sent to MainActivity as well as adding a "Quit" addAction.
Here is the snippet I am using to create the notification:
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String channelId = getNotificationChannel(notificationManager);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
Notification notification = notificationBuilder.setOngoing(true)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setSmallIcon(R.drawable.ic_notif_icon)
.setContentTitle("My app")
.setContentText("Background service is running...")
.setContentIntent(pendingIntent)
.build();
startForeground(13365, notification);
Using the above a notification shows up just fine, but click on it results in nothing. I also tried using addAction, also nothing. I am aware the syntax is a little bit different (....Action.Builder) when adding an addAction.
I am creating my notification in the onCreate handler of the foreground service. Running on SDK 26.
Can startForeground notifications have setContentIntent / addAction attached to them?
Thanks!
Solved : I had the notification replaced elsewhere in my application and was not adding the intents there.
Doh!

Override default Oreo Foreground Notification

As I correctly recall, with Android Oreo the system got more restrictive in terms of battery consumption, e.g., showing the user which app is currently running in the background draining the battery life.
This also shows in my app (scanning for BLE devices in the background, even if the app is not running in the foreground), stating
AppName is running in the background. Tap for Details on battery and
data usage
My question is, whether and how I would be able to exchange this text with a more user facing notification like
AppName is running in the background for reason XYZ
Even so with a notification with a specific icon, etc.
I already tried this by
Creating a custom notification channel in the application.
Starting the services with startForegroundService on Oreo devices.
From within the onCreate method of the service, I call
startForeground(1, NotificationCompat.Builder(applicationContext, "my_channel_id")
.setSmallIcon(R.drawable.some_icon)
.setContentTitle("Title")
.setContentText("AppName is running in the background for reason XYZ")
.build())
But all what happens is the same system-generated notification saying "AppName is running in the background".
Is it even possible to change this?
Thank you for sour suggestions in advance :)
In you service create the notification in onStartCommand() and set its priority. Don't forget to add android:enabled="true" in the manifest.
Service
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
ANDROID_CHANNEL_ID,
ANDROID_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, ANDROID_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("Test title")
.setContentText("Test content")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
startForeground(1, notification.build())
return Service.START_NOT_STICKY
}
AndroidManifest
<service android:name=".utils.AppService"
android:enabled="true"/>

FCM showing duplicate notification when app is in background

I implemented FCM in my project. Push notification is working as expected, onMessageReceived is called when a notification is received. This is true when app is in the foreground.
However, when the app is in the background, the system tray always display a duplicate notification when one arrives (e.g. when Notification A is received, system tray display 2 Notification A)
How to fix this?
EDIT: added code
I extended FirebaseMessagingService class and have this in the onMessageReceived method
This is the only part in the project where I used NotificationManager.
Also, I tried to add a log on this method. onMessageReceived is called when app is in foreground. It doesn't get called when app is in background
#Override
public void onMessageReceived(RemoteMessage remoteMessage)
{
RemoteMessage.Notification notification = remoteMessage.getNotification();
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String title = notification.getTitle();
String message = notification.getBody();
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
Same problem. I modified AndroidManifest.xml because i was requesting permissions to old GCM like this...
<uses-permission android:name="mypackage.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="mypackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
So, removing it from manifest and uninstalling and reinstalling the app my problem was solved.
To handle push notifications manually use handleIntent(intent) of FirebaseMessagingService.
This method gets called when application is in foreground, background and killed state. To avoid the duplication, do not call super.handleIntent(intent). This will prevent the automatic push notification when app in BG or killed state.
This worked for me.
I was having the exact same 'duplicate' problem. This may be just a workaround because I couldn't get notifications behaving when app was in foreground without the 'duplicate' problem happening. Instead I implemented a WakefulBroadcastReceiver, when toggling the android:exported to "false" it started behaving.
AndroidManifest.xml
<receiver
android:name="PACKAGE.MyWakefulBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
MyWakefulListenerService.java
public class MyWakefulBroadcastReceiver extends WakefulBroadcastReceiver {
private final String TAG = "MyWakefulListener";
public void onReceive(Context context, Intent intent) {
sendNotification(context);
}
}

Categories

Resources