What does requestCode represent? - android

I thought requestCode was some kind of indentifier for which Intent was just called for or something like that, please correct me if i'm wrong. But if this is the case, why is that if the requestCode for my pendingintent is 2, it acts differently when I have pass the requestcode as 0. I don't have another pendingintent in which is passed 2 as the requestcode.
Say I start my app and then I get a notification, when I click this notification ...
requestCode = 2
...a new activity is created and brought to the foreground, when I press the back button I go back to the activity I was on in the same state before backing out of the app
requestCode = 0
...I go straight back to the activity I was on in the same state before backing out of the app. No new activity is created
This isn't really a big issue, I could just pass 0 and the app will work how I want it to but I just wanna know why this happens.
In MainActivity.kt
private fun startAlarm (cal : Calendar){
val alarmManager :AlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent (this, AlertReceiver().javaClass)
val pendingIntent : PendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0)
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
}
}
AlertReceiver.kt
class AlertReceiver(): BroadcastReceiver() {
#RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context?, intent: Intent?) {
val notificationObj : Notification = Notification(context)
val notif : NotificationCompat.Builder = notificationObj.createNotification()
notificationObj.getManager().notify(1, notif.build())
}
}
In Notification.kt
fun createNotification(): NotificationCompat.Builder{
val main: Intent = Intent (this, MainActivity().javaClass).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
//-------------------talking about this line--------------------------------
val pendingMain: PendingIntent = PendingIntent.getActivity(this, 2, main, 0)
val notif : NotificationCompat.Builder = NotificationCompat.Builder(applicationContext, channelID)
.setSmallIcon(R.drawable.ic_android_black_24dp)
.setContentTitle("test:")
.setContentText("testing")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingMain)
.setAutoCancel((true))
return notif
}

When you are passing data from multiple Fragments to an Activity using onActivityResult(), that Activity identifies the child Fragment via request code

Related

Alarm Pending intent returns null when app started again after killing from background

I am trying to check if a repeating alarm already exist. I am testing in MIUI 11 (OS v8.1) device, where i have set an alarm then removed the application from background. If i again opens the app a new alarm is created again
Here is my code to set a repeating alarm
private fun startAlarm() {
val CUSTOM_INTENT = "com.test.intent.action.ALARM"
val intent = Intent(this, AlarmHelper::class.java)
intent.action = CUSTOM_INTENT
val pendingIntent: PendingIntent =
getBroadcast(this, 101, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
System.currentTimeMillis()+60*60*1000, pendingIntent)
}
This checks if an alarm already exist then i will not create a new one.
private fun isAlarmExist() :Boolean =
PendingIntent.getBroadcast(this, 101,
Intent(this, AlarmHelper::class.java),
PendingIntent.FLAG_NO_CREATE) != null
Already tried this
private fun isAlarmExist() :Boolean =
PendingIntent.getBroadcast(this, 101,
Intent("com.example.dozemodepoc.MY_UNIQUE_ACTION"),
PendingIntent.FLAG_NO_CREATE) != null
// this didnot work either
Already gone through
How to check if AlarmManager already has an alarm set?
When force stopped the application and started the app again, new instance is again created. Any kind of help will be highly appreciated!!.
I did a silly mistake in my isAlarmExist()
private fun isAlarmExist() :Boolean {
val CUSTOM_INTENT = "com.test.intent.action.ALARM"
val intent = Intent(this#MainActivity, AlarmHelper::class.java)
intent.action = CUSTOM_INTENT
return getBroadcast(this#MainActivity, 101, intent, PendingIntent.FLAG_NO_CREATE)!=null
}
This pending intent should be exact of the pending intent which was created when alarm was set up.

SetAlarmClock not showing alarm in notification

According to the docs:
The expectation is that when this alarm triggers, the application will
further wake up the device to tell the user about the alarm -- turning
on the screen, playing a sound, vibrating, etc. As such, the system
will typically also use the information supplied here to tell the user
about this upcoming alarm if appropriate.
SetAlarmClock docs
Is this done automatically? or I have to add a service with a notification.
I have read about setAlarmClock including a visible notification, or has the default behaviour been changed?
val activityIntent = Intent(requireContext(), AlarmClickedActivity::class.java)
pendingIntent =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(
requireContext(),
0,
activityIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
} else {
PendingIntent.getActivity(
requireContext(),
0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT
)
}
val alarmClockInfo = AlarmManager.AlarmClockInfo(alarm.timeInMilliSecond, null)
alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)
This only opens a new activity (AlarmClickedActivity) when the alarm goes off.
I don't get the notification of 'Current Alarm' or 'Upcoming Alarm' as mentioned in the docs
Firstly go to your app setting and give notification permission then run again and set a alarm then check.
If still having problem then use my code
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
Log.d("this", "notify")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val intent = Intent(context, AlarmActivity2::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
val builder = NotificationCompat.Builder(context, "111")
.setSmallIcon(R.drawable.blue_stringart)
.setContentTitle("Alarm is running")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setDefaults(NotificationCompat.DEFAULT_SOUND)
.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.addAction(R.drawable.ic_baseline_stop_24,"Stop",pendingIntent)
.setContentIntent(pendingIntent)
val notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
val r = RingtoneManager.getRingtone(context, notification)
r.play()
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.notify(123, builder.build())
}
}
}
Then go to activity class and set your alarm in a method.
private fun setAlarm1() {
var calender: Calendar
calender = Calendar.getInstance()
calender.set(Calendar.HOUR_OF_DAY, PUT_YOUR_ALARM HOUR)
calender.set(Calendar.MINUTE, PUT_YOUR_ALARM MINUTE)
calender.set(Calendar.SECOND, 0)
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val thuReq: Long = Calendar.getInstance().timeInMillis + 1
var reqReqCode = thuReq.toInt()
if (calender.timeInMillis < System.currentTimeMillis()) {
calender.add(Calendar.DAY_OF_YEAR, 1)
}
val alarmTimeMilsec = calender.timeInMillis
val intent = Intent(this, AlarmReceiver::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
val pendingIntent = PendingIntent.getBroadcast(this, reqReqCode, intent, 0)
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calender.timeInMillis,
24 * 60 * 60 * 1000,
pendingIntent
)
Note -
1.alarmManager.setRepeating here you can use your alarm type as your wish.
2.requestcode must be unique for each alarm.
3. you must take a alarm time and keep in calender.timeInMillis which is you expecting alarm time.
still problem comments below

Old intent in activity started from notification

I'm creating intent like this
val tapIntent = Intent(context, TaskActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val id = createID()
tapIntent.putExtra("timestamp", currentTime)
val notificationIntent: PendingIntent = PendingIntent.getActivity(context, 0, tapIntent, 0)
val builder = NotificationCompat.Builder(context, "com.task")
.setSmallIcon(R.drawable.ic_android_black_24dp)
.setContentTitle(context.resources.getString(R.string.new_task_available))
.setContentIntent(notificationIntent)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_MAX)
with(NotificationManagerCompat.from(context)) {
notify(id, builder.build())
}
This notifications are generated few times a day.
And when testing it, I've found out that if I'm not closing activity, but just swiping out of it, next time I open this activity from intent, I see that intent stores timestamp of a previous notification and not a current one.
Code for reading data from intent is quite simple:
val timestamp = intent.getLongExtra("timestamp", System.currentTimeMillis())
val hourFormatter = SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault())
Toast.makeText(this, hourFormatter.format(Date(timestamp)), LENGTH_LONG).show()
As far as I understand Intent.FLAG_ACTIVITY_CLEAR_TASK should clear all the old info. So I don't understand why this is happening.
What sould I do to receive current intent instead of the original one?
When generating the PendingIntent for the Notification, you need to do this:
PendingIntent.getActivity(context, 0, tapIntent,
PendingIntent.FLAG_UPDATE_CURRENT)
Otherwise you will just be using the previous (old) PendingIntent instead of creating a new one.

Pass data with PendingIntent and retrieve with onNewIntent when app launches

I have an Android application which will receive push notification. The notification have wearable support hence the notification will also be visible in Android wear with action button.
I am looking to pass data when the notification reaches onMessageReceived in FirebaseMessagingService class. Tried setting data in Intent and passed that with Pending Intent.
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.data = Uri.parse("12345")
intent.putExtra("user_id", "USER ID")
intent.putExtra("date", "DATE")
val pendingIntent = PendingIntent.getActivity(
applicationContext,
System.currentTimeMillis().toInt() , intent,
0
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel =
NotificationChannel(CHANNEL_ID,
CHANNEL_NAME,
CHANNEL_IMPORTANCE)
val notificationManager =
this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(notificationChannel)
val notificationBuilder = NotificationCompat.Builder(this,CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(body)
.setAutoCancel(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.extend(NotificationCompat.WearableExtender()
.addAction(NotificationCompat.Action(R.drawable.icon,
"Explore",
pendingIntent))
)
notificationManager.notify(0, notificationBuilder.build())
}
When click on the notification from Wear, capturing the intent in onNewIntent to get the data passed. But couldn't find the data which were passed.
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent)
// intent.getStringExtra("date")
// intent.extras.getString("date")
// intent.extras.get("date")
// intent.data
}
Couldn't get the data. Is there any way to get the intent passed with the pending intent ? Or how to get the values passed with Pending Intent.
My assumption is that onNewIntent() is not being called.
If you specify FLAG_ACTIVITY_CLEAR_TOP and your app is already running and there is an instance of MainActivity in the task stack, Android will remove the existing instance of MainActivity and create a new one. The Intent with "extras" will then be delivered in onCreate() and onNewIntent() will not be called.
If your app is not running, tapping the notification will start your app and create a new instance of MainActivity and the Intent with the "extras" will be delived in onCreate() and onNewIntent() will not be called.
Also, since the Intent that you put in the PendingIntent will be used by Android to launch an Activity from a non-Activity context, you need to specify Intent.FLAG_ACTIVITY_NEW_TASK.
Also, you should always specify FLAG_UPDATE_CURRENT when getting a PendingIntent with "extras", because if you do not, you may get an existing PendingIntent with some old "extras" or maybe none at all. Using FLAG_UPDATE_CURRENT will ensure that your Intent "extras" are copied into the PendingIntent even if it already exists. Like this:
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.data = Uri.parse("12345")
intent.putExtra("user_id", "USER ID")
intent.putExtra("date", "DATE")
val pendingIntent = PendingIntent.getActivity(
applicationContext,
System.currentTimeMillis().toInt() , intent,
PendingIntent.FLAG_UPDATE_CURRENT
)

Open activity after click in notification in alarmmanager and broadcast Kotlin

I set on my application the notification every 7 hours in this way:
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmBroadcastReceiver::class.java)
pendingIntent = PendingIntent.getBroadcast(this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
// Setting the specific time for the alarm manager to trigger the intent, in this example, the alarm is set to go off at 23:30, update the time according to your need
val calendar = Calendar.getInstance()
val next= calendar.get(Calendar.HOUR_OF_DAY) + 7
calendar.timeInMillis = System.currentTimeMillis()
calendar.set(Calendar.HOUR_OF_DAY, next)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
// Starts the alarm manager
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
with this class AlarmBroadcastReceiver :
class AlarmBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel
val name = "Alarme"
val descriptionText = "Detalhes do Alarme"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val mChannel = NotificationChannel("AlarmId", name, importance)
mChannel.description = descriptionText
val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
}
// Create the notification to be shown
val mBuilder = NotificationCompat.Builder(context!!, "AlarmId")
.setSmallIcon(R.mipmap.ic_food)
.setContentTitle("Synchronize Fitbit")
.setContentText("Synchronize Fitbit data and log-in SugarFree for don't lose daily data")
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Get the Notification manager service
val am = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Generate an Id for each notification
val id = System.currentTimeMillis() / 1000
// Show a notification
am.notify(id.toInt(), mBuilder.build())
The notifications working well, I enter in the application, set the alarm and after 7 hours arrive the notification and so on. I wish that when arrive the notification i can click on it and open the app (maybe in my current home activity) so this alarm wish set automatically after 7 hours.
I saw that I must modify the pendingIntent with my home intent... but I have a
val intent = Intent(this, AlarmBroadcastReceiver::class.java)
that need to call the Alarm Receiver class.
Can anyone help me out?
All you need is to add .setContentIntent in your notification builder.
// Create the notification to be shown
val mBuilder = NotificationCompat.Builder(context!!, "AlarmId")
.setSmallIcon(R.mipmap.ic_food)
.setContentTitle("Synchronize Fitbit")
.setContentText("Synchronize Fitbit data and log-in SugarFree for don't lose daily data")
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(
context, // Context from onReceive method.
0,
Intent(context, HomeActivity::class.java), // Activity you want to launch onClick.
0
)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build()
You can find out more here the docs have more information about how to handle tasks such as only single Activity opens at a time.
You need create and set pending intent -
// Create an Intent for the activity you want to start
val resultIntent = Intent(this, YourMainActivity::class.java)
// Create the TaskStackBuilder
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
// Add the intent, which inflates the back stack
addNextIntentWithParentStack(resultIntent)
// Get the PendingIntent containing the entire back stack
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
and then set it -
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
setContentIntent(resultPendingIntent)
...
}
with(NotificationManagerCompat.from(this)) {
notify(NOTIFICATION_ID, builder.build())
}
Hope this will work for you.

Categories

Resources