AndroidManifest.xml
<service
android:name=".CustomFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
My service:
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import org.tokend.template.BuildConfig
class CustomFirebaseMessagingService : FirebaseMessagingService() {
private val TAG = CustomFirebaseMessagingService::class.java.name
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
if (BuildConfig.DEBUG)
Log.d(TAG, "onMessageReceived:")
...
}
And when app is running and FCM is received then success called method onMessageReceived
Nice.
But when app is not running then method onMessageReceived is not called.
From server send different message type: data, notification. Not help. Not call onMessageReceived when app is NOT RUNNING
Related
i'm trying to send notification from android using retrofit and i followed the offical documentation from firebase.
i setup retrofit with https://fcm.googleapis.com/fcm/send and when i post notifications retrofit returns response but the message dosen't appear in my logs. i think my service is not working after the message was posted.
MainActivity
const val TOPIC = "MyTopic"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
FirebaseMessaging.getInstance().subscribeToTopic(TOPIC)
val btnSend = findViewById<Button>(R.id.btnSend)
btnSend.setOnClickListener {
FirebaseNotificationData(
NotificationData("Notification title", "Notification message"),
TOPIC
).also {
postNotification(it)
}
}
}
private fun postNotification(notification: FirebaseNotificationData) =
CoroutineScope(Dispatchers.IO).launch {
val response = RetrofitInstance.api.postNotification(notification)
if (response.isSuccessful)
Log.d("Retrofit", "Message was posted")
else
Log.e("Retrofit", response.errorBody().toString())
}
}
Service
class FirebaseNotificationService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
Log.d("onMessageReceived","message received")
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.firebasenotification">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<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/Theme.FirebaseNotification">
<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=".FirebaseNotificationService"
android:permission="com.google.android.c2dm.permission.SEND"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
</intent-filter>
</service>
</application>
</manifest>
onMessageReceived is provided for most message types, with the
following exceptions:
Notification messages delivered when your app is in the background. In
this case, the notification is delivered to the device’s system tray.
A user tap on a notification opens the app launcher by default.
Messages with both notification and data payload, when received in the
background. In this case, the notification is delivered to the
device’s system tray, and the data payload is delivered in the extras
of the intent of your launcher Activity.
While testing, make sure the app is in background, when you send FCM notifications.
https://firebase.google.com/docs/cloud-messaging/android/receive
I have the following Broadcast Receiver
class ShutdownReceiver(): BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (Intent.ACTION_SHUTDOWN == intent?.action) {
HiddenFileUtility.appendLogs("ACTION_SHUTDOWN: true")
ApplicationGlobalContext.setShutDownState(true)
}
}
}
I register the ShutdownReceiver through the AndroidManifext.xml like this:
<receiver android:name=".BroadcastReceivers.ShutdownReceiver">
<intent-filter android:priority="1">
<action android:name="android.intent.action.BOOT_COMPLETED" android:priority="999"/>
</intent-filter>
</receiver>
And i never receive the ACTION_SHUTDOWN intent.
In the Android official documentation states that As of Build.VERSION_CODES#P this broadcast is only sent to receivers registered through Context.registerReceiver link here
The solution is to delete the ShutdownReceiver from the AndroidManifest.xml and register it using Context.registerReceiver like this:
val shutdownReceiver = ShutdownReceiver();
val bootIntentFilter = IntentFilter(Intent.ACTION_SHUTDOWN);
context.registerReceiver(shutdownReceiver, bootIntentFilter);
I want to use FirebaseMessagingService to handle push notifications from the server. But there is not called onCreate function at the start. I thought that this service is initialized automatically when the app starts. Also, I started to send testing notification from firebase cloud messaging but it didn't work.
class PushNotificationService: FirebaseMessagingService() {
private lateinit var app: App
override fun onCreate() {
super.onCreate()
App.log("FireBaseMsg: starting service")
app = application as App
}
override fun onMessageReceived(msg: RemoteMessage?) {
super.onMessageReceived(msg)
App.log("FireBaseMsg: onMessageReceived")
val pNotification = msg?.notification
if (pNotification != null){
val title = pNotification.title
val text = pNotification.body
if (!title.isNullOrEmpty() && !text.isNullOrEmpty()){
val p = PushNotification(app, NOTIFICATION_CHANNEL_ID_PUSH, title = title, text = text)
p.fireNotification(NOTIFICATION_ID_PUSH)
}
}
}
override fun onNewToken(token: String) {
App.log("FireBaseMsg: Received token: $token")
//REGISTER TOKEN
app.regPushNotification(token, ::onNewTokenCallback)
}
private fun onNewTokenCallback(err: ApiCallError?){
if (err == null){
app.showToast(app.getString(R.string.notification_push_token_failed))
}
}
}
Manifest:
<service
android:name=".services.PushNotificationService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
I was in same problem while i am implementing FirebaseMessagingService class
My solution
Manifest.xml
<service
android:name=".MyFirebaseMessagingServices"
android:enabled="true"
android:permission="com.google.android.c2dm.permission.SEND"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
If everything ok in your manifest service section then
Uninistall your application
File -> Invalidate Caches / Restart....
Run your application
I want to do some work when user unlock their phone
I define a receiver in AndroidManifest.xml
<receiver
android:enabled="true"
android:name=".service.ScreenReceiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
and Receiver
class ScreenReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
}
private fun checkClearSavedNote(context: Context) {
AppPref.getInstance(context).putString(AppPref.KEY_ID_CURRENT_NOTE, "")
Log.e("Quang", "clear note")
}
}
But it was not called when fired
I've tried using Service and registerBroadcastReceiver inside
and start it when application start
class MyApplication : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
instance = this
MultiDex.install(applicationContext)
try {
startService(Intent(this, NoteService::class.java))
} catch (e: IllegalStateException) {
e.printStackTrace()
}
}
}
but it work only with Android API < 8.0 because background execution limit
You can set your targetSdk < 26 to leverage implicit broadcasts. Otherwise you have to change your design according to latest list of exempted broadcasts.
Maybe stupid question, but I have already spent to many hours on this.
I have my Kotlin listener:
package pl.bmideas.michal.bmnotifier
public class MyNotificationListener : NotificationListenerService() {
private var apiService :BackendApi? = null;
override fun onCreate() {
Log.i("MyNotificationListener" , "Creating NotificationListenerService service")
super.onCreate()
(.........SOMETHING ELSE..............)
}
override fun onDestroy() {
super.onDestroy()
Log.i(TAG, "DESTROING")
(.........SOMETHING ELSE..............)
}
override fun onNotificationRemoved(sbn: StatusBarNotification) {
val sbnInfo = StatusBarNotificationExtended(sbn)
Log.i(TAG, "REMOVED")
}
override fun onNotificationPosted(sbn: StatusBarNotification) {
Log.i(TAG, "RECIVED`")
(.........SOMETHING ELSE..............)
}
companion object {
var TAG = "MyNotificationListener"
}
}
and my config looks looks this:
<service
android:enabled="true"
android:name="pl.bmideas.michal.bmnotifier.MyNotificationListener"
android:label="#string/service_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
I'm not doing anything special in Activity.
Yes - I've checked security option and my app has access to notifications.
Yes - I've tried pointing to service by dot instead of full package
In logcat I can only see:
12-23 12:56:54.989 889-889/? V/NotificationListeners: enabling notification listener for 0:
ComponentInfo{pl.bmideas.michal.bmnotifier/pl.bmideas.michal.bmnotifier.MyNotificationListener}
I cant get instance unless i will bidn to this service in Activity wchich creates the service but still I get no info in logcat about notifications.
Can you guys help?
Holly....
after rewriting this code to pure Java it works..... but why?