I'm trying to run a one time job with WorkManager. I don't know why but if I close my application from recent app menu job does not start until I start the application :/. Tried with samsung galaxy s9+. Android 9 Pie. Any help would be appreciated. As far as I know workmanager should work even when phone is restarted.
val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.NOT_REQUIRED).build()
val request = OneTimeWorkRequestBuilder<NotificationJob>()
.addTag(item.uniqueId)
.setInputData(data)
.setConstraints(constraints)
//TODO revert
// .setInitialDelay(warrantyItem.reminderDate - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.setInitialDelay(1, TimeUnit.MINUTES)
.build()
WorkManager.getInstance(this#MainActivity).enqueue(request)
job is pretty simple. Just notification:
override fun doWork(): Result {
// Get the input
val uniqueId = inputData.getString(JOB_KEY)
if (uniqueId != null) {
sendNotification(uniqueId, "title", "subtitle")
}
return Result.success()
}
private fun sendNotification(uniqueId: String, title: String, subtitle: String) {
val intent = Intent(applicationContext, MainActivity::class.java)
intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
intent.putExtra(NOTIFICATION_ID, id)
val notificationManager =
applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val bitmap = applicationContext.vectorToBitmap(R.drawable.ic_warranty_icon)
val titleNotification = "$title"
val subtitleNotification = subtitle
val pendingIntent = getActivity(applicationContext, 0, intent, 0)
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
.setLargeIcon(bitmap).setSmallIcon(R.drawable.ic_warranty_icon)
.setContentTitle(titleNotification).setContentText(subtitleNotification)
.setDefaults(DEFAULT_ALL).setContentIntent(pendingIntent).setAutoCancel(true)
notification.priority = PRIORITY_MAX
if (SDK_INT >= O) {
notification.setChannelId(NOTIFICATION_CHANNEL)
val ringtoneManager = getDefaultUri(TYPE_NOTIFICATION)
val audioAttributes = AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE)
.setContentType(CONTENT_TYPE_SONIFICATION).build()
val channel =
NotificationChannel(NOTIFICATION_CHANNEL, NOTIFICATION_NAME, IMPORTANCE_HIGH)
channel.enableLights(true)
channel.lightColor = RED
channel.enableVibration(true)
channel.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
channel.setSound(ringtoneManager, audioAttributes)
notificationManager.createNotificationChannel(channel)
}
with(NotificationManagerCompat.from(applicationContext)) {
// notificationId is a unique int for each notification that you must define
notify(uniqueId, ID, notification.build())
}
}
Related
I am working on a parental control app which notify parent multiple times but when I try to create notification with a background service it generates only one 1.
Here is how I do it:
fun createNotification(parent_name: String, notificationText:String, id: Int){
val MchannelId = channelId+id.toString()
if (Build.VERSION.SDK_INT >= 26) {
val channel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel(
MchannelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT
)
} else {
TODO("VERSION.SDK_INT < O")
}
(getSystemService(NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(
channel
)
}
val notificationIntent = Intent(this, TabbedActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
id, notificationIntent, 0
)
val notification: Notification = NotificationCompat.Builder(this, "$MchannelId")
.setContentTitle("Hi $parent_name")
.setContentText(notificationText)
.setSmallIcon(R.drawable.icon_child)
//.setContentIntent(pendingIntent)
.build()
startForeground(random_number, notification)
}
My Full-Service Class:
const val TAG2 = "Child Service"
class ParentService: Service() {
val db = FirebaseFirestore.getInstance()
private val channelId = "Notification from Service"
var parent_name = userName
override fun onBind(intent: Intent?): IBinder? = null
//OnBind Function Implementation
init {
Log.d(TAG2, "Started Service!")
}
//onCreate Method Implementation
override fun onCreate() {
super.onCreate()
}
//OnStartCommand Override
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Thread{
while (true){
checkStatus()
Thread.sleep(PARENT_CHECK_TIME)
}
}.start()
return START_STICKY
}
private fun checkStatus() {
var listOfNames = ""
var i = 1
val calendar: Calendar = Calendar.getInstance()
var list = ArrayList<String>()
db.collection(LINKED_CHILDS)
.whereEqualTo(USER_PHONE, userPhone)
.get()
.addOnSuccessListener { documents ->
for (document in documents){
val startTime: Long = calendar.getTimeInMillis()
val diff = startTime - (document.data[ACTIVE_STATUS] as Long)
Log.d("TAG", "Time Difference : $diff")
Log.d("TAG", "${document.data[USER_NAME].toString()}")
if (diff> MAX_GAP_TIME){
Log.d("TAG", "Entered IFF")
list.add(document.data[USER_NAME].toString())
}
}
for (name in list){
listOfNames = listOfNames + "$i. Your child $name is not active\n"
i++
createNotification(parent_name, listOfNames, i)
Log.d("TAG Notification ID:", "ID: $i")
}
Log.d("TAG: ", "$listOfNames")
}
}
fun createNotification(parent_name: String, notificationText:String, id: Int){
val MchannelId = channelId+id.toString()
if (Build.VERSION.SDK_INT >= 26) {
val channel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel(
MchannelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT
)
} else {
TODO("VERSION.SDK_INT < O")
}
(getSystemService(NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(
channel
)
}
val notificationIntent = Intent(this, TabbedActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
id, notificationIntent, 0
)
val notification: Notification = NotificationCompat.Builder(this, "$MchannelId")
.setContentTitle("Hi $parent_name")
.setContentText(notificationText)
.setSmallIcon(R.drawable.icon_child)
//.setContentIntent(pendingIntent)
.build()
startForeground(id, notification)
}
}
Kinldy let me know how I can create multiple Notifications using this background service. Thank You so much in advance!
Kinldy let me know how I can create multiple Notifications using this background service. Thank You so much in advance!
Kinldy let me know how I can create multiple Notifications using this background service. Thank You so much in advance!
If you create a non-persistent notification, it will show your notifications. The permanent notification will be used for your service to run in the background.
#RequiresApi(Build.VERSION_CODES.O)
private fun createNotification() {
val intent = Intent(this, TabbedActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent =
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.icon_child)
.setContentTitle("Hi $parent_name")
.setContentText(notificationText)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
with(NotificationManagerCompat.from(this)) {
notify(notifManagerId, notification.build())
notifManagerId++
}
parmanentNotification()
}
this is a permanent notification will not be lost and destroyed will keep the service running permanently
private fun parmanentNotification() {
val notification=NotificationCompat.Builder(this,channelId)
.setSmallIcon(R.drawable.icon_child)
.setContentTitle("Hi $parent_name")
.setContentText("Application service running in the background")
.build()
startForeground(1,notification)
}
you aren't creating a common Notification in this scenario, you are running a Service, which must have a foreground representation on screen. So Activity visible or sticked, fixed Notification, and you are showing it
Now you can have much Notifications using similar code, but don't show them using startForeground, instead use NotificationManager, preferably compat version
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(uniqueId, notification);
or just like you are using it already when creating channel inside if: (getSystemService(NOTIFICATION_SERVICE) as NotificationManager).notify(...)
foreground-related Notification is sticky and lives as long as Service works in background, they are "tied". other Notifications may be configured to be sticky or swipeable, also should be posted on some own Channel (per child? per action?). Note that if you show yet another sticky Notification then you have to release it by own through code, just killing Service won't dismiss it as it does with foreground-related Notification
some DOC in here, read carefully, all answers are there
I'm firing a notification after posting data to fcm , when i receive data back the notification is shown no problem but it has no sound no vibration even though i made sure that my sound and vibraton are enable in my phone , i'm not sure if i'm doing something wrong , please help me figure it out , thank you .
This is my application class code where i set the notification channel for oreo +
override fun onCreate() {
super.onCreate()
Timber.plant(Timber.DebugTree())
setUpNotification()
}
private fun setUpNotification(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
val notificationChannel = NotificationChannel(
getString(R.string.channelid),getString(R.string.channelstring),
NotificationManager.IMPORTANCE_DEFAULT)
val ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
notificationChannel.description = "Notifications"
notificationChannel.enableLights(true)
notificationChannel.enableVibration(true)
notificationChannel.lightColor = Color.BLUE
notificationChannel.setSound(ringtone,audioAttributes)
val notificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as
NotificationManager
notificationManager.createNotificationChannel(notificationChannel)
}
}
This is my notification code
private fun FireNotification(title : String, body : String, isVibrationEnabled : Boolean,
notificationchannelid : String){
val intent = Intent(applicationContext,MainActivity::class.java)
val taskBuilder = TaskStackBuilder.create(applicationContext).run {
addNextIntentWithParentStack(intent)
getPendingIntent(1,PendingIntent.FLAG_UPDATE_CURRENT)
}
val vibratePattern = longArrayOf(1000L, 1000L, 1000L, 1000L)
val notification = NotificationCompat.Builder(applicationContext, notificationchannelid)
notification.apply {
setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
setContentTitle(title)
setContentText(body)
setContentIntent(taskBuilder)
setSmallIcon(R.drawable.ic_baseline_notifications_active_24)
addAction(R.drawable.default_icon,"Snooze",taskBuilder)
addAction(R.drawable.default_icon,"Action",taskBuilder)
priority = NotificationCompat.PRIORITY_HIGH
if(isVibrationEnabled){
notification.setVibrate(vibratePattern)
}
}
NotificationManagerCompat.from(applicationContext).notify(counter++,notification.build())
}
The solution to my issue was to simply set default sound as following
setDefaults(NotificationCompat.DEFAULT_SOUND)
I want to display a notification while a Worker is running in the background. I can do that with something like the code below:
override suspend fun doWork(): Result {
val manager = NotificationManagerCompat.from(applicationContext)
val channel = "some_channel"
val id = 15
val builder = NotificationCompat.Builder(applicationContext, channel)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
manager.createNotificationChannel(NotificationChannel(channel, "DefaultName", NotificationManager.IMPORTANCE_LOW))
builder
.setOnlyAlertOnce(true)
.setOngoing(true)
.setAutoCancel(false)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setTicker("Background Task")
.setContentText("Starting")
.setProgress(0, 0, true)
setForeground(ForegroundInfo(id, builder.build()))
delay(500)
manager.notify(id, builder.setContentText("Progress A").setProgress(20, 0, false).build())
for (i in 1..20) {
delay(100)
manager.notify(id, builder.setProgress(20, i, false).build())
}
delay(500)
manager.notify(id, builder.setContentText("Progress B").setProgress(2, 0, false).build())
delay(1000)
manager.notify(id, builder.setProgress(2, 1, false).build())
delay(1000)
manager.notify(id, builder.setProgress(2, 2, false).build())
delay(1000)
manager.notify(id, builder.setContentText("Done!").setProgress(0, 0, false).build())
delay(500)
return Result.success()
}
But I also want to display the result of the worker in the notification and keep it until the user sees and clears it, yet the notification is always cleared at the end of the work.
How can I keep the notification alive? .setOngoing(true) and .setAutoCancel(false) didn't help.
A much simpler way I think I found is to either notify the final notification with a different id (use .setOngoing(false)):
manager.notify(
id + 1,
builder.setContentText("Done!")
.setAutoCancel(true)
.setOngoing(false)
.build()
)
return Result.success()
Or, send it after a bit of delay:
CoroutineScope(Main).launch {
delay(200)
manager.notify(
id,
builder.setContentText("Done!")
.setAutoCancel(true)
.setOngoing(false)
.build()
)
}
return Result.success()
A workaround that I found, is to have a BroadcastReceiver that takes the final notification and shows it. This is possible because Notification extends Parcelable. Note: have the NotificationReceiver use a different notification id than the one your Worker is using, otherwise the Worker will close the notification.
class NotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == ACTION_SEND_NOTIFICATION) {
val notification = intent.getParcelableExtra<Notification>(EXTRA_NOTIFICATION)
val id = intent.getIntExtra(EXTRA_ID, DEFAULT_ID)
if (notification == null)
Log.e(TAG, "EXTRA_NOTIFICATION ($EXTRA_NOTIFICATION) was not provided!")
else
NotificationManagerCompat.from(context).notify(id, notification)
}
}
companion object {
const val TAG = "NotificationReceiver"
const val ACTION_SEND_NOTIFICATION = "intent.action.SEND_NOTIFICATION"
const val EXTRA_NOTIFICATION = "notification_parcel"
const val EXTRA_ID = "notification_id"
const val DEFAULT_ID = 1010
}
}
<receiver android:name=".NotificationReceiver" android:enabled="true" />
// At the end of doWork, before returning
applicationContext.sendBroadcast(
Intent(applicationContext, NotificationReceiver::class.java).setAction(
NotificationReceiver.ACTION_SEND_NOTIFICATION
).putExtra(NotificationReceiver.EXTRA_NOTIFICATION, builder.build())
)
Tried Searching With no Luck yet
i am testing on API 24
whats wrong with this code? the notification is showing correctly but is not a heads-up notification though i specified the priority to high and added vibration and sound correctly.
Please any help would be appreciated
Here is my code:
private fun sendNotification(title: String, message: String) {
val mNotificationCompatBuilder = mNotificationUtils.getNotificationBuilder(
title,
message,
false,
R.drawable.ic_logo,
NotificationUtils.ALERT_MESSAGES_ID
)
mNotificationCompatBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(message))
mNotificationUtils.openTopActivityOnClick(mNotificationCompatBuilder, FTApplication.applicationContext())
mNotificationUtils.setSoundAndVibrate(mNotificationCompatBuilder)
val mNotificationManager = mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.notify((title+message).hashCode(), mNotificationCompatBuilder.build())
}
fun getNotificationBuilder(title: String, body: String, onGoing: Boolean, icon: Int, id: String): NotificationCompat.Builder {
val largeIcon = BitmapFactory.decodeResource(
context.resources,
R.drawable.ic_logo
)
return NotificationCompat.Builder(context, id)
.setSmallIcon(icon)
.setLargeIcon(largeIcon)
.setBadgeIconType(icon)
.setContentTitle(title)
.setContentText(body)
.setOngoing(onGoing)
.setAutoCancel(!onGoing)
.setWhen(System.currentTimeMillis())
}
fun setSoundAndVibrate(builder: NotificationCompat.Builder) {
#Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) builder.priority = NotificationManager.IMPORTANCE_HIGH
else builder.priority = Notification.PRIORITY_HIGH
builder.priority = NotificationCompat.PRIORITY_HIGH // heads-up test
val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
builder.setSound(alarmSound)
builder.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
builder.setDefaults(Notification.DEFAULT_ALL)
}
here is the channel im creating (which is not used since as mentioned i am testing now on API 24)
#RequiresApi(Build.VERSION_CODES.O)
private fun createAlertMessageChannel() {
if (getManager()!!.getNotificationChannel(ALERT_CHANNEL_NAME) != null) {
return
}
// create alert channel
val alertChannel = NotificationChannel(
ALERT_MESSAGES_ID,
ALERT_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH
)
alertChannel.description = "For Alerting User of Events"
alertChannel.setShowBadge(false)
alertChannel.enableLights(true)
alertChannel.enableVibration(true)
//alertChannel.setSound(null, null)
// Sets the notification light color for notifications posted to this channel
alertChannel.lightColor = Color.GREEN
// Sets whether notifications posted to this channel appear on the lock screen or not
alertChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
getManager()!!.createNotificationChannel(alertChannel)
}
I have a problem with notifications (NotificationManager class) in my android app. I made channel and notification. I read about the problem with 26 build and made a channel for notifications, but it doesn't solve my problem. But I have the next error in logcat.
E/NotificationService: No Channel found for pkg=com.gmail.mtswetkov.ocrraces,
channelId=com.google.MTsvetkov.CHANNEL_ID, id=103, tag=null,
opPkg=com.gmail.mtswetkov.ocrraces, callingUid=10087, userId=0,
incomingUserId=0, notificationUid=10087,
notification=Notification(channel=com.google.MTsvetkov.CHANNEL_ID
pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x0
color=0x00000000 vis=PRIVATE)
class NotificationsJobScheduler : JobService() {
private lateinit var mNotification: Notification
private lateinit var alarmIntent: PendingIntent
private lateinit var prefs: SharedPreferences
val gson = Gson()
private var notificationManager: NotificationManager? = null
lateinit var channel : NotificationChannel
private lateinit var notifList: MutableList<LocalNotification> //= mutableListOf(LocalNotification(0, Date(2017, 6, 11), "", ""))
companion object {
var started: Boolean = false
const val CHANNEL_ID = "com.google.MTsvetkov.CHANNEL_ID"
var notificationID = 101
const val CHANNEL_NAME = "Sample Notification"
const val CHANNEL_DISC = "Example News Channel"
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
override fun onStartJob(params: JobParameters?): Boolean {
createNotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
CHANNEL_DISC)
sendNotification()
jobFinished(params, false)
return true
}
fun sendNotification() {
val intent = Intent(this, MainActivity::class.java)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
//Get Notification list from SharedPreferences
prefs = this.getSharedPreferences(ShowSingleRaceActivity().PREFS_FILENAME, 0)
val jsonPerf: String = prefs.getString(ShowSingleRaceActivity().NOTIFICATION_OBJECTS, "")
if (jsonPerf != "") notifList = gson.fromJson(jsonPerf, object : TypeToken<MutableList<LocalNotification>>() {}.type)
//Check the date
val today = Calendar.getInstance()
for (notif in notifList) {
if (today.equals(notif.notifDate)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d("JSON", Build.VERSION.SDK_INT.toString())
mNotification = Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.yelbell)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
notificationID++
} else {
mNotification = Notification.Builder(this)
.setSmallIcon(R.drawable.yelbell)
.setAutoCancel(true)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
}
notificationManager?.notify(notificationID, mNotification)
}
}
}
private fun createNotificationChannel(id: String, name: String,
description: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_LOW
channel = NotificationChannel(id, name, importance)
channel.description = description
channel.enableLights(true)
channel.lightColor = Color.RED
channel.enableVibration(true)
channel.vibrationPattern =
longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
notificationManager?.createNotificationChannel(channel)
}
}
}
it was necessary to move channel creation block into the cycle (where I created notification)
createNotificationChannel(CHANNEL_ID, CHANNEL_NAME,CHANNEL_DISC) --->
---->or (notif in notifList) {
if (today.equals(notif.notifDate)) {
**createNotificationChannel(CHANNEL_ID, CHANNEL_NAME,CHANNEL_DISC)**
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d("JSON", Build.VERSION.SDK_INT.toString())
mNotification = Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.yelbell)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
notificationID++
} else {
mNotification = Notification.Builder(this)
.setSmallIcon(R.drawable.yelbell)
.setAutoCancel(true)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
}