I have been trying to get the Service to run in the background for that I have implemented the foreground approach still its killing the app.
I need this service to return me the location of the user even if the application is killed.
MainActivity.kt
private fun kickStartService(){
var intent = Intent(this , LocationService::class.java)
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra("extra" , "extra")
ContextCompat.startForegroundService( this , intent)
// startService( intent)
}
LocationService.kt
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
myNotification(intent)
mGoogleApiClient = GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build()
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
if (!mGoogleApiClient!!.isConnected) {
mGoogleApiClient!!.connect()
}
return START_NOT_STICKY
}
fun myNotification( intent : Intent?){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
var extra = intent?.getStringExtra("extra")
var pendingIntent: PendingIntent =
Intent(this, MainActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, 0)
}
var notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Notification Title")
.setContentText(extra)
.setSmallIcon(R.drawable.notification_icon_background)
.setContentIntent(pendingIntent)
.setTicker("Ticker Text")
.build()
startForeground(1, notification)
}
}
Well, My bad, I was using Xiaomi Mi Mix 2 and so it happens that Mi does not let you start a foreground service if you have auto start off from the app settings in app manager. Once I turned it on, my foreground service is working like a charms.
Related
I am writing an Android Wear app that uses a foreground service.
I have verified that the foreground service wokrs, and the code inside the service executes as needed (SensorEventListener) and I even use intents to display information in the UI.
However, the notification for the service is not posting in the list of notifications. I use a Galaxy Watch4 for testing.
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
broadcaster = LocalBroadcastManager.getInstance(this)
val notificationIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, FLAG_IMMUTABLE)
val notificationChannel = NotificationChannel(foregroundChannelId, "Foreground Service", NotificationManager.IMPORTANCE_HIGH)
notificationChannel.lightColor = Color.BLUE
notificationChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(notificationChannel)
val notification = NotificationCompat.Builder(this, foregroundChannelId).setOngoing(true)
.setContentTitle("Monitoring sensors").setContentText("app_name is actively monitoring your biosensors.")
.setContentIntent(pendingIntent).setCategory(Notification.CATEGORY_SERVICE).setSmallIcon(R.mipmap.ic_launcher).build()
startForeground(1, notification)
prepareSensors()
return START_NOT_STICKY
}
There is no sticky notification in the notification panel.
I've tried removing the .setOngoing.
Maybe it was delayed in showing, as the operation was too quick ?
Try adding this:
builder.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
I'm developing a health application that record the user's steps.
I'm really searching for a couple of weeks how to run this in the background and I have no solution yet.
runing service for long time without draing battery and system resource was hardest thing i faced in programming and finally today i found the best solution for my idea
thank to Coding in Flow channel
StepsService::class
class MainActivity() : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
"background_service"
).setMethodCallHandler(
MethodCallHandler { call: MethodCall, result:
MethodChannel.Result ->
if ((call.method == "start")) {
//start Service.
val i: Intent = Intent(
getApplicationContext(),
StepsService::class.java
)
ContextCompat.startForegroundService(this, i)
}
result.success(1)
}
//start Service.
)
}
}
StepsService::class
/** The service is starting, due to a call to startService() */
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
Log.v("Service", "Start")
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
stepCounterSensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
stepDetectorSensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)
sensorManager!!.registerListener(this, stepCounterSensor, 0)
sensorManager!!.registerListener(this, stepDetectorSensor, 0)
//currentStepCount = 0;
currentStepsDetected = 0
stepCounter = 0
newStepCounter = 0
// --------------------------------------------------------------------------- \\
// ___ (3) start handler ___ \\
// remove any existing callbacks to the handler
handler.removeCallbacks(updateBroadcastData)
// call our handler with or without delay.
handler.post(updateBroadcastData) // 0 seconds
// ___________________________________________________________________________ \\
val notificationIntent = Intent(
this,
MainActivity::class.java
)
val pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent, 0
)
val notification : Notification;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notification = Notification.Builder(this, channelId)
.setContentTitle("$currentStepsDetected Steps")
.setContentText("Target Steps 7500")
.setSmallIcon(R.mipmap.ic_notification)
.setContentIntent(pendingIntent)
.setVisibility(Notification.VISIBILITY_PRIVATE)
.build()
}else{
notification = Notification.Builder(this)
.setContentTitle("Example Service")
.setContentText("description")
.setSmallIcon(R.mipmap.ic_notification)
.setContentIntent(pendingIntent)
.setVisibility(Notification.VISIBILITY_PRIVATE)
.build()
}
startForeground(1, notification)
return START_NOT_STICKY
}
reference
Need to silence a notification that is shown by a foreground service. To silence the notification I have used many suggested solution from SO. But nothing seems to silence the annoying notification sound. It is silenced on SDK25. But on SDK 29 emulator it is not silenced. What can be the solution?
Code:
//service
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
createNotificationChannel()
val notificationIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent, 0
)
val notification: Notification =
NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("app_name")
.setContentText("Updating database.")
.setSmallIcon(R.drawable.logo)
.setContentIntent(pendingIntent)
.build()
startForeground(1, notification)
thread() {
Thread.sleep(3000)
stopSelf()
}
return START_NOT_STICKY
}
override fun onDestroy() {
super.onDestroy()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = SettingsHelper.KEY_NOTIFICATION_channel_name_service
val description = SettingsHelper.KEY_NOTIFICATION_CH_ID_SERVICE
val channel = NotificationChannel(
SettingsHelper.KEY_NOTIFICATION_CH_ID,
name,
NotificationManager.IMPORTANCE_NONE
)
channel.description = description
channel.setSound(null, null)
val manager = getSystemService(
NotificationManager::class.java
)
manager.createNotificationChannel(channel)
}
}
Could you use setSilent() from NotificationCompat.Builder
If true, silences this instance of the notification, regardless of the sounds or vibrations set on the notification or notification channel. If false, then the normal sound and vibration logic applies. Defaults to false.
Note, that if you are changing notification settings, I recommend you to uninstall and re-install the app everytime since it might not be updated the settings you set in the new run.
I am starting a background service which receives data in the background, so for this, I have used android foreground service, the service works perfectly in some mobiles (MI A2 Stock Android), but in some mobiles when I remove the application from background tray the service gets destroyed.
class MyService : Service() {
private val CHANNEL_ID = "ForegroundService"
companion object {
fun stopService(context: Context) {
val stopIntent = Intent(context, MyService::class.java)
context.stopService(stopIntent)
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// I get some data from intent
// My code which runs in the background
createNotificationChannel()
val notificationIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent, 0
)
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("App is syncing")
.setContentText("")
.setPriority(2)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setContentIntent(pendingIntent)
.build()
startForeground(190, notification)
return START_NOT_STICKY
}
override fun onBind(intent: Intent): IBinder? {
return null
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val serviceChannel = NotificationChannel(
CHANNEL_ID, "Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(NotificationManager::class.java)
manager!!.createNotificationChannel(serviceChannel)
}
}
}
This how I start the service
val serviceIntent = Intent(this, MyService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
} else {
startService(serviceIntent)
}
So my question is how can I make my service running even when the APP is removed from the background tray.
Do these things
1) Restart the service when app is closed by overriding this method in
your service class , copy and paste this
override fun onTaskRemoved(rootIntent: Intent?) {
val restartServiceIntent = Intent(applicationContext, this.javaClass)
restartServiceIntent.setPackage(packageName)
val restartServicePendingIntent = PendingIntent.getService(
applicationContext,
1,
restartServiceIntent,
PendingIntent.FLAG_ONE_SHOT
)
val alarmService =
applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmService[AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000] =
restartServicePendingIntent
super.onTaskRemoved(rootIntent)
}
2) Change this START_NOT_STICKY to START_STICKY
3) Ask user to enable autorun permission from settings , this feature
is provided in custom os like mini devices, vivo,huawei and oppo etc.
4) and you forgot to restart the service on device boot up like you
need to use a broadcast receiver to restart service when the device
restarts
I'm trying to create a foreground service that check devices location every minute and I've managed to make it work. But I have some problems regarding the obligatory notification about the service being active.
I can't get the notification badge to stop showing and I can't make the notification minimized programatically.
Here are the relevant parts:
class LocationPollingService : Service() {
companion object {
const val NOTIF_ID = 2
const val NOTIF_CHANNEL_ID = "background_service_notification"
const val NOTIF_CHANNEL_NAME = "Background service"
}
#Nullable
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(
intent: Intent?,
flags: Int,
startId: Int
): Int {
createBackgroundNotifChannel()
startForeground()
requestLocation()
return super.onStartCommand(intent, flags, startId)
}
private fun startForeground() {
val notificationIntent = Intent(this, SplashActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this, 0,
notificationIntent, 0
)
val notification = NotificationCompat.Builder(
this,
NOTIF_CHANNEL_ID
)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_app_icon)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.im_watching_you))
.setContentIntent(pendingIntent)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIF_ID, notification.build())
} else {
notification.priority = NotificationCompat.PRIORITY_MIN
startForeground(NOTIF_ID, notification.build())
}
}
private fun createBackgroundNotifChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelBackground = NotificationChannel(
NOTIF_CHANNEL_ID,
NOTIF_CHANNEL_NAME,
NotificationManager.IMPORTANCE_LOW
).apply {
description = getString(
R.string.notification_channel_background_description
)
enableLights(false)
enableVibration(false)
setShowBadge(false)
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channelBackground)
}
}
}
If I understand correctly, IMPORTANCE_LOW is supposed to be used for this kind of notification and it is supposed to make it minimized by default. The notification is never minimized nor can I minimize it by clicking. The only way I can make it minimized is by manually changing notification channel settings in device settings (setting Notification style to Silent and minimized, instead of just silent, which is the default). I tried setting the importance to IMPORTANCE_MIN and IMPORTANCE_NONE, but that didn't change anything.
As mentioned, the second problem is that the badge is shown (the notification counter displayed on app icon), despite of setShowBadge(false).
What am I missing?
You need to notify notification after build notification like below :
notificationManager.notify(NOTIF_ID , notification.build());
for hiding notification badge from statusbar
you should change notification channel priority:
val channelBackground = NotificationChannel(
NOTIF_CHANNEL_ID,
NOTIF_CHANNEL_NAME,
NotificationManager.IMPORTANCE_MIN