Send Daily Notification at a scheduled time android - android

I am trying to send notification daily at 10am.
The code works fine when app is running and in background, but it does not work when the app is terminated/Killed.
Here is what I am doing,
In Manifest:
<receiver
android:name=".ReminderBroadcast"
android:exported="true"
android:enabled="true"/>
My BroadcastReceiver:
public class ReminderBroadcast extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
context.startService(new Intent(context, NotifyService.class));
}
}
My Service inside onCreate:
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), "notifyHackhshieldPP")
.setSmallIcon(R.drawable.logopp)
.setContentTitle("Hello")
.setContentText("Notification Test")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
notificationManager.notify(200, builder.build());
Then calling it:
private void setnotificationSendService()
{
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//creating a new intent specifying the broadcast receiver
Intent i = new Intent(this, ReminderBroadcast.class);
//creating a pending intent using the intent
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
//setting the repeating alarm that will be fired every day
Calendar alarmStartTime = Calendar.getInstance();
alarmStartTime.set(Calendar.HOUR_OF_DAY, 20);
alarmStartTime.set(Calendar.MINUTE, 5);
alarmStartTime.set(Calendar.SECOND, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, (alarmStartTime.getTimeInMillis()), AlarmManager.INTERVAL_DAY, pi);
}

Monday, August 30, 2021
According to official documents, you can use alarmMgr.setInexactRepeating() but due to the system being busy it does not work properly I found another way to do this work. Use alarmMgr.set() for this purpose this will Wake up the device to fire a one-time (non-repeating) alarm. But when it triggers the device give it next date and time. It works properly when the app is terminated/Killedwork I am describing both methods just follow which one you want
SourceCode
Method 1
NotificationUtils.kt
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
class NotificationUtils(context:Context) {
private var mContext = context
private lateinit var notificationBuilder: NotificationCompat.Builder
val notificationManager = NotificationManagerCompat.from(mContext)
private val CHANNEL_ID = "My_Notification_Channel"
init {
createNotificationChannel()
initNotificationBuilder()
}
fun launchNotification(){
with(NotificationManagerCompat.from(mContext)) {
// notificationId is a unique int for each notification that you must define
notificationManager.notify(0, notificationBuilder.build())
}
}
private fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Channel Name"
val descriptionText = "Channel Description"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
// Register the channel with the system
val notifiManager: NotificationManager =
mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notifiManager.createNotificationChannel(channel)
}
}
private fun initNotificationBuilder() {
// Create an explicit intent for an Activity in your app
val sampleIntent = Intent(mContext, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(mContext, 0, sampleIntent, 0)
/***
* Notice that the NotificationCompat.Builder constructor requires that you provide a channel ID.
* This is required for compatibility with Android 8.0 (API level 26) and higher,
* but is ignored by older versions.
*/
notificationBuilder = NotificationCompat.Builder(mContext, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Notification Title")
.setContentText("Notification Body Text, Notification Body Text")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
// Automatically removes the notification when the user taps it.
.setAutoCancel(true)
}
}
AlarmUtils.kt
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import java.util.*
class AlarmUtils(context: Context) {
private var mContext = context
private var alarmMgr: AlarmManager? = null
private var alarmIntent: PendingIntent
init {
alarmMgr = mContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(mContext, AlarmReceiver::class.java).let { mIntent ->
// if you want more than one notification use different requestCode
// every notification need different requestCode
PendingIntent.getBroadcast(mContext, 100, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
fun initRepeatingAlarm(){
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, 10)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
}
alarmMgr?.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
alarmIntent
)
}
}
AlarmReceiver.kt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class AlarmReceiver:BroadcastReceiver() {
override fun onReceive(context: Context?, mIntent: Intent?) {
val notificationUtils = NotificationUtils(context!!)
notificationUtils.launchNotification()
}
}
AndroidManifest.xml
<receiver android:name=".AlarmReceiver" />
MainActivity.kt
val alarmUtils = AlarmUtils(this)
alarmUtils.initRepeatingAlarm()
Method 2
NotificationUtils.kt
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
class NotificationUtils(context:Context) {
private var mContext = context
private lateinit var notificationBuilder: NotificationCompat.Builder
val notificationManager = NotificationManagerCompat.from(mContext)
private val CHANNEL_ID = "My_Notification_Channel"
init {
createNotificationChannel()
initNotificationBuilder()
}
fun launchNotification(){
with(NotificationManagerCompat.from(mContext)) {
// notificationId is a unique int for each notification that you must define
notificationManager.notify(0, notificationBuilder.build())
}
}
private fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Channel Name"
val descriptionText = "Channel Description"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
// Register the channel with the system
val notifiManager: NotificationManager =
mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notifiManager.createNotificationChannel(channel)
}
}
private fun initNotificationBuilder() {
// Create an explicit intent for an Activity in your app
val sampleIntent = Intent(mContext, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(mContext, 0, sampleIntent, 0)
/***
* Notice that the NotificationCompat.Builder constructor requires that you provide a channel ID.
* This is required for compatibility with Android 8.0 (API level 26) and higher,
* but is ignored by older versions.
*/
notificationBuilder = NotificationCompat.Builder(mContext, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Notification Title")
.setContentText("Notification Body Text, Notification Body Text")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
// Automatically removes the notification when the user taps it.
.setAutoCancel(true)
}
}
AlarmUtils.kt
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import java.util.*
class AlarmUtils(context: Context) {
private var mContext = context
private var alarmMgr: AlarmManager? = null
private var alarmIntent: PendingIntent
init {
alarmMgr = mContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(mContext, AlarmReceiver::class.java).let { mIntent ->
// if you want more than one notification use different requestCode
// every notification need different requestCode
PendingIntent.getBroadcast(mContext, 100, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
fun initRepeatingAlarm(calendar: Calendar){
calendar.apply {
set(Calendar.HOUR_OF_DAY, 10)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
}
alarmMgr?.set( AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
alarmIntent)
}
AlarmReceiver.kt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import java.util.*
class AlarmReceiver:BroadcastReceiver() {
override fun onReceive(context: Context?, mIntent: Intent?) {
val notificationUtils = NotificationUtils(context!!)
notificationUtils.launchNotification()
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_YEAR, 1)
val daysNextCalendar = calendar
val alarmUtils = AlarmUtils(context)
alarmUtils.initRepeatingAlarm(daysNextCalendar)
}
}
AndroidManifest.xml
<receiver android:name=".AlarmReceiver" />
MainActivity.kt
val calendar = Calendar.getInstance()
val alarmUtils = AlarmUtils(this)
alarmUtils.initRepeatingAlarm(calendar)
Reboot Device
If you want the alarm should work after rebooting the device you should do the following thing.
AlarmBootReceiver.kt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import java.util.*
class AlarmBootReceiver : BroadcastReceiver(){
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == "android.intent.action.BOOT_COMPLETED") {
val calendar = Calendar.getInstance()
val alarmUtils = AlarmUtils(context)
alarmUtils.initRepeatingAlarm(calendar)
}
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".AlarmBootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

Related

How to stop getting notification on every launch of application in kotlin?

package com.greenhcm.android
import android.app.*
import android.app.Notification.*
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Bundle
import androidx.core.app.NotificationCompat
import kotlinx.android.synthetic.main.fragment_profile.*
class AlarmBroadcastReceiver: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
showNotification(context)
}
internal fun showNotification(context: Context) {
val CHANNEL_ID = "1"// The id of the channel.
val name = context.getResources().getString(R.string.app_name)// The user-visible name of the channel.
val mBuilder: NotificationCompat.Builder
val intent = Intent()
val manufacturer = android.os.Build.MANUFACTURER
when(manufacturer) {
"xiaomi" ->
intent.component=
ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity")
"oppo" ->
intent.component =
ComponentName("com.coloros.safecenter",
"com.coloros.safecenter.permission.startup.StartupAppListActivity")
"vivo" ->
intent.component =
ComponentName("com.vivo.permissionmanager",
"com.vivo.permissionmanager.activity.BgStartUpManagerActivity")
"samsung" ->
intent.component =
ComponentName(
"com.samsung.android.lool",
"com.samsung.android.sm.ui.battery.BatteryActivity")
"asus" ->
intent.component =
ComponentName(
"com.asus.mobilemanager",
"com.asus.mobilemanager.MainActivity"
)
}
val list = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (list.size > 0) {
context.startActivity(intent)
}
val notificationIntent = Intent(context, GreenHCMActivity::class.java)
val bundle = Bundle()
notificationIntent.putExtras(bundle)
//notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
//val contentIntent = PendingIntent.getActivity(
// context,
//1,
//notificationIntent,
//PendingIntent.FLAG_UPDATE_CURRENT
//)
var contentIntent = PendingIntent.getActivity(context, 1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//mNotificationManager.cancel(1)
mNotificationManager.cancelAll()
if (android.os.Build.VERSION.SDK_INT >= 26)
{
val mChannel = NotificationChannel(
CHANNEL_ID,
name,
NotificationManager.IMPORTANCE_HIGH
)
mNotificationManager.createNotificationChannel(mChannel)
mBuilder = NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setLights(Color.RED, 300, 300)
.setChannelId(CHANNEL_ID)
.setDefaults(DEFAULT_ALL)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000))
.setAutoCancel(true)
// Overrides ContentTitle in the big form of the template.
.setContentTitle("Selamat Pagi Jangan Lupa Untuk Absensi ")
.setContentIntent(contentIntent);
//.setContentTitle("Selamat Pagi Jangan Lupa Untuk Absensi ")
}
else
{
mBuilder = NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setPriority(Notification.PRIORITY_HIGH)
//.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentTitle("Title")
}
mBuilder.setContentIntent(contentIntent)
.setDefaults(DEFAULT_ALL)
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round)
val note = mBuilder.build()
mBuilder.setContentText("Mohon melakukan absensi pagi ini,Terima kasih")
.setStyle(
NotificationCompat.BigPictureStyle()
// Provide the bitmap to be used as the payload for the BigPicture notification.
.bigPicture(BitmapFactory.decodeResource(context.resources, R.drawable.absence))
// Override the large icon when the big notification is shown.
.bigLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.mipmap.ic_launcher_round
)
)
// Set the first line of text after the detail section in the big form of the template.
//.setSummaryText("Mohon melakukan absensi pagi ini,Terima kasih")
)
mNotificationManager.notify(1, mBuilder.build())
}
}
Above My Receiver like this,
Below in oncreate activity
val _intent = Intent(this, AlarmBroadcastReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 1, _intent, 0)
val alarmManager = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val calendar = Calendar.getInstance()
calendar.setTimeInMillis(System.currentTimeMillis())
calendar.set(Calendar.HOUR_OF_DAY, 7)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.set(Calendar.AM_PM,Calendar.AM);
//alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() , 24*60*60*1000, pendingIntent)
//alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis()/1000 ,AlarmManager.INTERVAL_DAY, pendingIntent)
//alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis()/1000 ,AlarmManager.INTERVAL_DAY, pendingIntent)
//alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis()/1000 ,AlarmManager.INTERVAL_DAY , pendingIntent)
//alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent)
alarmManager.cancel(pendingIntent)
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY,
pendingIntent
)
I'm new to android development... trying to build application which send notification at specific time daily. But after that if I open application it shows notification every time on launch.. how to stop showing it again? please help me thank you
Iqbal,
you are sending an Alarm on
calendar.getTimeInMillis(),
It will return your current time in milliseconds. Hence alarm whenever you run on create. i.e. whenever you open the app. try different times. Or add 1000 * 60 * (min) in millis.

AlarmManager with Notification in Android does not show any notifications

I try to create daily notification for my application. In order to test the application I set the interval for the notifications to 15 minutes. Unfortunately, no notification is shown. Neither when the application is running nor when it is closed. I tried to inspire myself with these solutions:
https://stackoverflow.com/questions/33055129/how-to-show-a-notification-everyday-at-a-certain-time-even-when-the-app-is-close
https://developer.android.com/codelabs/android-training-alarm-manager#0
https://github.com/google-developer-training/android-fundamentals-apps-v2/tree/master/StandUp (repository for the previous link)
I added uses-permissions and receiver to the manifest file.
manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ovu">
<uses-permission android:name = "android.permission.VIBRATE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<!-- Permission to start Alarm on device reboot -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
...
</activity>
<receiver android:name= ".DailyNotificationReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>
This class extends BroadcastReceiver class and overrides onReceive method.
DailyNotificationReceiver
class DailyNotificationReceiver : BroadcastReceiver() {
companion object {
// Notification ID.
private const val NOTIFICATION_ID = 0
// Notification channel ID.
private const val PRIMARY_CHANNEL_ID = "primary_notification_channel"
}
private lateinit var mNotificationManager: NotificationManager
private val notificationContent = "Please measure your temperature and cervical mucus"
private val contentTitle = "Provide me your temperature and cervical mucus!"
override fun onReceive(context: Context, intent: Intent) {
mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Deliver the notification.
deliverNotification(context);
}
private fun deliverNotification(context: Context) {
val contentIntent = Intent(context, MainActivity::class.java)
val contentPendingIntent = PendingIntent.getActivity(context, NOTIFICATION_ID, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)
// Build the notification
val builder = NotificationCompat.Builder(context, PRIMARY_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_dialog_alert)
.setContentTitle(contentTitle)
.setContentText(notificationContent)
.setContentIntent(contentPendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
// Deliver the notification
mNotificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
In this activity, instance of AlarmManager should set daily repeating.
ActivityNotification
class ActivityNotification : AppCompatActivity() {
companion object {
// Notification ID.
private const val NOTIFICATION_ID = 0
// Notification channel ID.
private const val PRIMARY_CHANNEL_ID = "primary_notification_channel"
}
private lateinit var mNotificationManager: NotificationManager
private fun notifyUser(){
val notifyIntent = Intent(this, DailyNotificationReceiver::class.java)
val notifyPendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_ID, notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val repeatInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES
val triggerTime = (SystemClock.elapsedRealtime()
+ repeatInterval)
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerTime, repeatInterval,
notifyPendingIntent)
// Create the notification channel.
createNotificationChannel();
Toast.makeText(this, "Alarm's set", Toast.LENGTH_LONG).show()
}
private fun createNotificationChannel() {
// Create a notification manager object.
mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
// Notification channels are only available in OREO and higher.
// So, add a check on SDK version.
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.O) {
// Create the NotificationChannel with all the parameters.
val notificationChannel = NotificationChannel(PRIMARY_CHANNEL_ID,
"Stand up notification",
NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.enableVibration(true)
notificationChannel.description = "Notifies every 15 minutes to " +
"stand up and walk"
mNotificationManager.createNotificationChannel(notificationChannel)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notification)
editTextNotificationHour = findViewById(R.id.editTextChangedNotification)
mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
}
fun changeNotificationHour(view: View){
notifyUser()
val intent = Intent(this, ProfileActivity::class.java)
startActivity(intent)
finish()
}
I'd be really happy if you guys can help me to find the solution.
Firstly, let's start by enabling our BroadcastReceiver in Manifest by changing our code to this:
<receiver
android:name= ".DailyNotificationReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Secondly, I am a bit unsure of the purpose of the ActivityNotification Activity.
It would be more than enough to create a simple class like Alarms.
From there you can define all the methods you need to set up an alarm. Something like this:
class InternetDaysLeftAlarm #Inject constructor(
#ApplicationContext val context: Context
) {
/**
* Function is used to schedule one-time Alarm that will trigger on specific time.
*
* #param hourOfDay -> parameter defines what o'clock should the alarm be triggered at. (24-hour)
* default value is:
* #see INTERNET_DAYS_LEFT_ALARM_DEFAULT_TRIGGER_HOUR
*/
fun scheduleAlarm(hourOfDay: Int = INTERNET_DAYS_LEFT_ALARM_DEFAULT_TRIGGER_HOUR) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, InternetDaysLeftReceiver::class.java)
intent.action = INTENT_ACTION_INTERNET_DAYS_LEFT_ALARM
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
val msUntilTriggerHour: Long = TimeUnit.MINUTES.toMillis(minutesUntilOClock(hourOfDay))
// Calculating and adding jitter in order to ease load on server
val jitter: Long = TimeUnit.MINUTES.toMillis(Random.nextInt(0, 420).toLong())
val alarmTimeAtUTC: Long = System.currentTimeMillis() + msUntilTriggerHour + jitter
// Enabling BootReceiver
val bootReceiver = ComponentName(context, BootReceiver::class.java)
context.packageManager.setComponentEnabledSetting(
bootReceiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
/**
* Schedules the Alarm based on Android Version.
*
* As per AlarmManager documentation to guarantee Alarm execution at specified time we use following methods:
*
* #see AlarmManager.setExactAndAllowWhileIdle -> Android.M [API 23] and above.
* #see AlarmManager.setAlarmClock -> Everything below Android M.
*/
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeAtUTC, pendingIntent)
} else {
alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(alarmTimeAtUTC, pendingIntent), pendingIntent)
}
}
Notifications can be handle by:
Creating a separate Notifications class
or
Handling all the notification things like creating channel and sending them inside BroadcastReceiver when you receive an Alarm.

Firebase notifications not shown on foreground

I'm trying to manage notifications, but I am not able to do nothing with them when app is in foreground.
When app is minimified or completly closed, the notification is correctly shown, but if app is in foreground it is not seen.
I have test variations of this code, but nothing works. The notifications with app closed or minimified works wit any modification of this code, or with any this code at all:
(EDITED following comments indications, same result)
import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Looper
import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import PACKAGE_NAME.ContenedorPrincipal
import PACKAGE_NAME.R
import PACKAGE_NAME.general.General
import java.text.SimpleDateFormat
import java.util.*
//import java.util.concurrent.atomic.AtomicInteger
class ServicioNotificaciones: FirebaseMessagingService()
{
//private val c = AtomicInteger(0)
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
try{
val uniqueID = Integer.parseInt(SimpleDateFormat("ddHHmmss", Locale.getDefault()).format(Date()))
val mNotificationManager: NotificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
"notificationChannelID",
"notificationChannelName",
NotificationManager.IMPORTANCE_HIGH)
mNotificationManager.createNotificationChannel(notificationChannel)
}
val mBuilder: NotificationCompat.Builder = NotificationCompat.Builder(applicationContext, "notify_001")
val ii = Intent(applicationContext, ContenedorPrincipal::class.java)
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, ii, 0)
val bigText = NotificationCompat.BigTextStyle()
bigText.bigText(remoteMessage.notification?.body ?: "")
bigText.setBigContentTitle(remoteMessage.notification?.title ?: "")
bigText.setSummaryText(remoteMessage.notification?.body ?: "")
mBuilder.setContentIntent(pendingIntent)
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round)
mBuilder.setContentTitle(remoteMessage.notification?.title ?: "")
mBuilder.setContentText(remoteMessage.notification?.body ?: "")
#Suppress("DEPRECATION")
mBuilder.priority = Notification.PRIORITY_MAX
mBuilder.setStyle(bigText)
val buildedNotification = mBuilder.build()
//mNotificationManager.notify(c.incrementAndGet(), buildedNotification)
mNotificationManager.notify(uniqueID, buildedNotification)
/*Looper.prepare()
General.mostrarConfirmacion(
remoteMessage.notification?.title ?: "",
remoteMessage.notification?.body ?: "",
AlertDialog.Builder(this)
)*/
}
catch (ex: Exception){
Log.wtf("onMessageReceivedEX", ex.message.toString())
}
}
}
And manifest:
<service
android:name="PACKAGE_NAME.servicios.ServicioNotificaciones"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
EDIT 2:
I finnaly make it work with this code:
val intent2 = Intent(this, MainActivity::class.java)
intent2.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingintent2 = PendingIntent.getActivity(this, 0, intent2, PendingIntent.FLAG_ONE_SHOT)
val channelId = "Default"
val builder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(remoteMessage.notification?.title)
.setContentText(remoteMessage.notification?.body).setAutoCancel(true)
.setContentIntent(pendingintent2)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
"Default channel",
NotificationManager.IMPORTANCE_DEFAULT
)
manager.createNotificationChannel(channel)
}
manager.notify(uniqueID, builder.build())
Thanks you all!
You have to use notification channel:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
"notify_001",
getString(R.string.notification_channel_name),
NotificationManager.IMPORTANCE_HIGH)
mNotificationManager.createNotificationChannel(notificationChannel)
}
I Don't see where do you create the notification channel (Since Android O it is a must).
Create and Manage Notification Channels
i think this issue related to sent notification not to receive notification try to sent notification like this
"data": {
"data_title": "test",
"data_body" : "test"
}

Android Notification Not Appearing As Heads Up

I am using the following to present notifications to users on Android which currently works fine but I am having an issue that the notification appears in the status bar but does not come up as a heads up like a Facebook or WhatsApp notification does on the device? I get the notification but have to pull down on the status bar to view it. I am wondering is there a way to make this appear on the top of the screen in bubble format or is this something that varies between phone settings?
Code is attached below:
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addNotification(10,"eventname","roomname");
addNotification(25,"eventname2","roomname2");
}
public void addNotification(int test, String test2, String test3){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("test",test2);
intent.putExtra("test2",test3);
final int _id = 50;
Random random = new Random();
final int randomInt = random.nextInt();
System.out.println("random integer:" + randomInt);
PendingIntent appIntent = PendingIntent.getBroadcast(this, randomInt, intent,PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, test);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), appIntent);
}
}
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver{
private static final String CHANNEL_ID = "com.singhajit.notificationDemo.channelId";
#Override
public void onReceive(Context context, Intent intent) {
Intent notificationIntent = new Intent(context, NotificationActivity.class);
String passed = intent.getStringExtra("test");
String passed2 = intent.getStringExtra("test2");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(NotificationActivity.class);
stackBuilder.addNextIntent(notificationIntent);
String messageBody = "Your event " + passed + " is about to start in 15 minutes, in room "+passed2;
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context);
builder.setStyle(new Notification.BigTextStyle(builder)
.bigText(messageBody)
.setBigContentTitle("UA Reloaded Event Starting")
.setSummaryText("Tap To View Info"))
.setContentText(messageBody)
.setSmallIcon(R.drawable.ic_launcher)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setPriority(Notification.PRIORITY_MAX);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(CHANNEL_ID);
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String name = "NotificationDemo";
String description = "NotificationDemo";
int importance = NotificationManager.IMPORTANCE_HIGH; //Important for heads-up notification
NotificationChannel channel = new NotificationChannel("1", name, importance);
channel.setDescription(description);
channel.setShowBadge(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
// NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0, builder.build());
}
}
If you still need an answer or for anyone else in order to show the notification as heads-up you have to add your channel id to the Builder.
.setChannelId(CHANNEL_ID)
like so:
val notification = NotificationCompat.Builder(getContext(), CHANNEL_ID)
.setSmallIcon(...)
.setContentTitle(getContext().getString(R.string.app_name))
...
.setChannelId(CHANNEL_ID)
...
.build()
And don't forget about the NotificationChannel importance and notification priority (set them to high/max if needed)
You updated your channel importance, which is not possible as stated in the documentation (https://developer.android.com/training/notify-user/channels#CreateChannel).
So your problem should be resolved by changing the channelId to something other than "1", as the ids for Channels must be unique.
Here is my kotlin class all you need is to call notificate(title: String, text: String) method, if you want it in java you can convert it
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationManager
import android.content.Context
import android.support.v4.app.NotificationCompat
import beacon.geisoft.org.beacontrakerkotlin_rebuild.R
import android.os.Build
import android.support.annotation.RequiresApi
import android.support.v4.content.ContextCompat.getSystemService
import android.app.NotificationChannel
import android.app.PendingIntent
import android.content.Intent
import android.graphics.Color
import android.media.RingtoneManager
import android.support.v4.content.ContextCompat.getSystemService
import android.support.v4.app.NotificationManagerCompat
import beacon.geisoft.org.beacontrakerkotlin_rebuild.activities.MainActivity
import android.preference.PreferenceManager
import android.content.SharedPreferences
class Notifications (var context: Context){
/**
* Send notification to the client device
* #param text String
*/
#SuppressLint("PrivateResource")
private fun notificate(title: String, text: String, id: Int, notificationManager: NotificationManager) {
val intent1 = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 123, intent1, PendingIntent.FLAG_UPDATE_CURRENT)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel("beacon.geisoft.org.beacontraker_rebuild") == null) {
val chan2 = NotificationChannel("beacon.geisoft.org.beacontraker_rebuild", "Pazienti", NotificationManager.IMPORTANCE_HIGH)
chan2.lightColor = Color.BLUE
chan2.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
notificationManager.createNotificationChannel(chan2)
/*
notificationManager.createNotificationChannel(NotificationChannel("beacon.geisoft.org.beacontraker_rebuild",
"Pazienti", NotificationManager.IMPORTANCE_HIGH))*/
}
val builder = NotificationCompat.Builder(context, "beacon.geisoft.org.beacontraker_rebuild")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setContentTitle(title) // required
.setContentText(text) // required
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.beaconicon32) // required
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.beaconicon64))
.setSound(defaultSoundUri)
}else {
builder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setContentTitle(title)
.setContentText(text)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.beaconicon32) // required
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.beaconicon64))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSound(defaultSoundUri)
}
notificationManager.notify(id, builder.build());
}
fun notificate(title: String, text: String, id: Int){
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
notificate(title, text, id, notificationManager!!)
}
fun notificate(title: String, text: String){
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
var num: Int
do {
num = (Math.random() * 100).toInt()
} while (notificationExist(notificationManager!!, num))
notificate(title, text, num, notificationManager)
}
fun notificationExist(notificationManager: NotificationManager, id: Int): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val notifications =
notificationManager.activeNotifications
for (notification in notifications) {
if (notification.getId() == id) {
return true
}
}
}
return false
}
}

How to create a time triggered Notification that works on all Android Devices

I'm trying to make a notification that get triggered after a certain amount of time has passed. In an attempt to achieve this I have this AlarmReceiver class that inherits from BroadCast receiver and works on devices running up to about API 23. It doesn't work on my emulator currently running API 27. Any clue what I'm doing wrong?
class AlarmReceiver : BroadcastReceiver() {
companion object {
val PRIMARY_CHANNEL = "dj"
}
override fun onReceive(context: Context, intent: Intent) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationIntent = Intent(context, NotificationActivity::class.java)
val stackBuilder = TaskStackBuilder.create(context)
stackBuilder.addParentStack(NotificationActivity::class.java)
stackBuilder.addNextIntent(notificationIntent)
val pendingIntent = stackBuilder.getPendingIntent(100, PendingIntent.FLAG_UPDATE_CURRENT)
if (android.os.Build.VERSION_CODES.O <= android.os.Build.VERSION.SDK_INT){
//I create the notification channel on the next line, but it doesn't seem to work
val notificationChannel = NotificationChannel(PRIMARY_CHANNEL,
"DailyJokes", NotificationManager.IMPORTANCE_DEFAULT)
notificationChannel.lightColor = Color.GREEN
notificationChannel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
notificationManager.createNotificationChannel(notificationChannel)
val notification = Notification.Builder(context, PRIMARY_CHANNEL)
.setContentIntent(pendingIntent)
.setChannelId("dj")
.setContentText("KDW")
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("CCC")
.build()
notificationManager.notify(1,notification)
} else {
var builder = NotificationCompat.Builder(context, "dj")
val sound = Uri.parse("android.resource://" + context.packageName + "/" + "raw/drumroll")
builder = builder
.setSmallIcon(R.mipmap.ic_launcher_round)
.setColor(Color.BLUE)
.setContentTitle("Content Title")
.setTicker("TICKER Text")
.setContentText("KDW setContentText")
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setChannelId("dj")
.setSound(sound)
notificationManager.notify(1, builder!!.build())
}
}
}
Here's the code that triggers the notification, anything off here?
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notification)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val notificationIntent = Intent("android.media.action.DISPLAY_NOTIFICATION")
notificationIntent.addCategory("android.intent.category.DEFAULT")
val broadcast = getBroadcast(this, 100, notificationIntent, FLAG_UPDATE_CURRENT)
val cal = Calendar.getInstance()
cal.add(Calendar.SECOND, 5)
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, broadcast)
}
}
I also have a receiver in my Manifest:
<receiver android:name=".AlarmReceiver">
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Even with all this the bug still lurks. I'm new to Kotlin, today makes a week since I started. My swift experience prepared me well but I just can't seem to get a hold on notifications :/
From what I can tell from your code , you need to register the receiver in either the Manifest or a context.
https://developer.android.com/guide/components/broadcasts.html
is your channel even created ?
your comparison is in the wrong direction ->
android.os.Build.VERSION_CODES.O <= android.os.Build.VERSION.SDK_INT it should be >= instead
and only the channel creation needs to be guarded against O, not the notification creation.

Categories

Resources