I want open special activity when the app is closed and user tap on notification. But the special didnt open. When user will click to notification i want open TestActivity but instead of this MainActivity opening all time.
In the manifest i have this code:
<service
android:name=".services.firebase.notification.AppFirebaseMessaging"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
.
.
.
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
.
.
.
<activity android:name=".TestActivity"
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true"/>
this is my AppFirebaseMessaging
class AppFirebaseMessaging : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
// here parsing RemoteMessage object,
sendNotification("title", "description")
}
private fun sendNotification(title: String, description: String) {
val random = System.currentTimeMillis().toInt()
val notificationBuilder: NotificationCompat.Builder = notificationBuilder(title, description)
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager?.createNotificationChannel(getChannel(title))
}
notificationManager?.notify(random, notificationBuilder.build())
}
private fun notificationBuilder(title: String, description: String): NotificationCompat.Builder {
val random = System.currentTimeMillis().toInt()
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notifyIntent = Intent(this, TestActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val notifyPendingIntent = PendingIntent.getActivity(
this, 0, notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(this, random.toString())
.setSmallIcon(R.drawable.icon_notification)
.setContentTitle(title)
.setContentText(description)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.apply {
setContentIntent(notifyPendingIntent)
}
return notificationBuilder
}
}
When user will click to notification, MainActivity will be open, dont understand why
Tapping on Notification will always open the activity that has the following intent filter attributes.
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
If you can't make the 'TestActivity' the Main activity, you could try as follows.
Keep the MainActivity as the Main.
There set the launch mode to singleTop in MainActivity.
<activity
android:name=".MainActivity"
android:launchMode="singleTop"/>
Then Override the 'onNewIntent' inside MainActivity,
#Override
protected void onNewIntent(#NonNull Intent intent) {
super.onNewIntent(intent);
// here send intent to open TestActivity
}
Related
I'm trying to show a notification that when clicked will open ChatScreen. It does open ChatScreen but started as a different activity, so there's 2 MainActivity in the back stack.
I use Compose Destinations, a wrapper library for Compose Navigations.
I have tried singleTop, singleTask, singleInstance launch mode, nothing works.
ChatScreen:
#Destination(deepLinks = [DeepLink(uriPattern = "https://mantools/chats")])
#Composable
fun ChatScreen(
navigator: DestinationsNavigator,
viewModel: ChatViewModel = hiltViewModel()
) {
//contents
}
Manifest
<application
android:name=".MainApplication"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/Theme.Mantools"
android:hardwareAccelerated="true"
android:usesCleartextTraffic="${usesCleartextTraffic}"
tools:targetApi="31">
<activity
android:name=".features.MainActivity"
android:launchMode="singleInstance"
android:exported="true"
android:theme="#style/Theme.Mantools.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:scheme="https" android:host="mantools"/>
</intent-filter>
</activity>
</application>
Notification
private fun showChatNotification(message: RemoteMessage) {
val data = message.data
showNotification(
data["title"] ?: "",
data["text"] ?: "",
TAG_CHAT,
Intent(Intent.ACTION_MAIN, "https://mantools/chats".toUri(), this.applicationContext, MainActivity::class.java)
)
}
fun showNotification(
title: String,
message: String,
tag: String,
intent: Intent
) {
val pendingIntent = getPendingIntent(intent)
val builder = NotificationCompat.Builder(context, GENERAL_CHANNEL_ID)
.setLargeIcon(context.getDrawable(R.mipmap.ic_launcher)?.toBitmap())
.setSmallIcon(R.drawable.app_logo)
.setColor(ContextCompat.getColor(context, R.color.primary))
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
notificationManager.notify(tag, System.currentTimeMillis().toInt(), builder.build())
}
private fun getPendingIntent(intent: Intent) = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(intent)
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
I have the following structure:
Main Class
private fun scheduleNotification()
{
val intent = Intent(applicationContext, Notification::class.java)
val title = binding.titleET.text.toString()
val message = binding.messageET.text.toString()
intent.putExtra(titleExtra, title)
intent.putExtra(messageExtra, message)
val pendingIntent = PendingIntent.getBroadcast(
applicationContext,
1 + (Random.nextInt(1, 100)),
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val time = getTime()
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
time,
pendingIntent
)
showAlert(time, title, message)
}
Notification Class
class Notification : BroadcastReceiver(){
override fun onReceive(context: Context, intent: Intent)
{
val notification = NotificationCompat.Builder(context, channelID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(intent.getStringExtra(titleExtra))
.setContentText(intent.getStringExtra(messageExtra))
.build()
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.notify(notificationID, notification)
}
}
Android Manifest
<receiver
android:name=".Notification"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
With this I am able to SCHEDULE a NOTIFICATION with DATE and TIME. But when the device is restarted all scheduled notifications are erased.
I tried to solve it by adding:
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Indeed it "works" but I get an empty notification and outside the scheduled time and I understand that it is an Android behavior, but is there any solution?
I am trying to implement how to push notifications from firebase. I have added the dependencies and made a project in my firebase account and connected my app. It initially worked fine but I changed the firebase account that is associated with the app to another(2nd account) then I saw that I did not receive any notification so I deleted my project on the 2nd account and replaced my json files with the first one and reconnected to it again but I am not receiving any notification which was working previously. Here is my reference https://www.geeksforgeeks.org/how-to-push-notification-in-android-using-firebase-cloud-messaging/
Here is my code for notification service
package com.crazy.pushnotifications
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.os.Build
import android.widget.RemoteViews
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class FirestoreNotification : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (remoteMessage.getNotification() != null) {
// Since the notification is received directly from
// FCM, the title and the body can be fetched
// directly as below.
showNotification(
remoteMessage.notification!!.title!!,
remoteMessage.notification!!.body!!
)
}
}
private fun getCustomDesign(title: String, message: String): RemoteViews {
val remoteViews = RemoteViews(
applicationContext.packageName,
R.layout.layout_notification
)
remoteViews.setTextViewText(R.id.title, title);
remoteViews.setTextViewText(R.id.message, message);
remoteViews.setImageViewResource(
R.id.icon,
R.drawable.ic_baseline_fingerprint_24
);
return remoteViews;
}
private fun showNotification(title: String, body: String) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val channelId = "notification_channel"
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
var builder = Notification.Builder(applicationContext, channelId)
.setSmallIcon(R.drawable.ic_baseline_fingerprint_24)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder = builder.setContent(
getCustomDesign(title, body)
);
} else {
builder = builder.setContentTitle(title)
.setContentText(body)
.setSmallIcon(R.drawable.ic_baseline_fingerprint_24)
}
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
// Check if the Android Version is greater than Oreo
// Check if the Android Version is greater than Oreo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
channelId, "CTQ",
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(notificationChannel)
notificationManager.notify(0, builder.build())
}
}
}
and main activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.crazy.pushnotifications">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Pushnotifications"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".FirestoreNotification"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
I want to know if I made any mistake cause i didnot get any error but I didnot get any notification either.
NOTE: I have checked my gradle files and I am not missing any dependencies
I'm writing a time tracker app that starts an unbound foreground service to keep the user informed about the elapsed time.
The service runs smoothly and everything works like a charm... EXCEPT for one thing!
When the user clicks on the notification the apps main activity should start.
According to Androids documentation (https://developer.android.com/training/notify-user/navigation) this code should work, but it just starts the Android Settings Activity for the app.
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "Started")
isRunning = true
val channelID = createNotificationChannel()
val pendingIntent: PendingIntent = Intent(this, MainActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, FLAG_UPDATE_CURRENT)
}
val notification: Notification = NotificationCompat.Builder(this, channelID)
.setContentTitle(CHANNEL_NAME)
.setContentText("My wonderful Text")
.setPriority(PRIORITY_LOW)
.setContentIntent(pendingIntent)
.build()
startForeground(FOREGROUND_ID, notification)
timer.scheduleAtFixedRate(TimedTask(), 0, 1000)
return super.onStartCommand(intent, flags, startId)
}
private fun createNotificationChannel(): String{
val chan = NotificationChannel(CHANNEL_ID,
CHANNEL_NAME, NotificationManager.IMPORTANCE_NONE)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
return CHANNEL_ID
}
The manifest.xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.maybe.tima">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<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
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".TimerService"
android:label="#string/app_name"
/>
</application>
</manifest>
Any ideas why this happens? Your help is very appreciated :)
The only change I've done to make your code work - is to add method "setSmallIcon" to your notificationBulider (but I couldn't find in official documentation any mention about such kind of affection of this method):
val notification: Notification = NotificationCompat.Builder(this, channelID)
.setContentTitle(CHANNEL_NAME)
.setContentText("My wonderful Text")
.setPriority(PRIORITY_LOW)
.setSmallIcon(R.drawable.ic_launcher_background) // line added
.setContentIntent(pendingIntent)
.build()
I'm trying to save Firebase notification into the Room Dao when app in the background. Send notification with Postman, but onMessage received called only when app is foreground and message have notification : {} body. Can any help me with this problem please :3
My FirebaseMessagingService implementation :
class NotificationService : FirebaseMessagingService() {
override fun onMessageReceived(p0: RemoteMessage) {
val title = p0.notification?.title ?: return
val message = p0.notification?.body ?: return
Log.e("TAG","Notification: $title: $message")
Log.e("TAG","Data from notification : ${p0.data["key_1"]}")
Log.e("TAG","MessageReceived")
CoroutineScope(Dispatchers.IO).launch {
NotificationApp.db?.notificationDao()?.setNotification(Notification(data = p0.data["key_1"]))
}
showNotification(p0)
}
fun showNotification(data: RemoteMessage) {
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_input_get)
.setContentTitle(data.notification?.title)
.setContentText(data.notification?.body)
.setContentIntent(pendingIntent)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(CHANNEL_ID, "test_notification_channel_id", NotificationManager.IMPORTANCE_HIGH)
manager.createNotificationChannel(channel)
}
manager.notify(0, notificationBuilder.build())
}
Manifest :
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_launcher_background" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorPrimary" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/notification_main_chanel_id" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotificationService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/notification_main_chanel_id" />
And notification example in Postman :
{
"data": {
"title": "I'd tell you a chemistry joke",
"message": "but I know I wouldn't get a reaction",
"image-url":
"https://docs.centroida.co/wp-content/uploads/2017/05/notification.png",
"key_1" : "Heh message"
},
"to": "DEVICE_TOKEN",
"priority": "high"
}