I creating app using CapacitorJS and Svelte with php Backend, my problem is I fail to implement push notification while app is backgrounded (or killed)
here my Android manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<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:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBarLaunch"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FCM_PLUGIN_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
<service
android:name=".MyFirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
</application>
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
</manifest>
here my custom java class extending firebaseCloudMessaging
package com.appapp.omi;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import com.capacitorjs.plugins.pushnotifications.PushNotificationsPlugin;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginHandle;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.getcapacitor.Bridge;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginManager;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "PushNotificationService";
private static final String CHANNEL_ID = "default_channel";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String title = "Default Title";
String body = "Default Body";
JSObject dataObj = new JSObject();
if (remoteMessage.getNotification() != null) {
title = remoteMessage.getNotification().getTitle();
body = remoteMessage.getNotification().getBody();
} else if (remoteMessage.getData().size() > 0) {
// Handle custom data payload
title = remoteMessage.getData().get("title");
body = remoteMessage.getData().get("body");
}
if (MainActivity.bridge != null) {
PluginHandle pushPluginHandle = MainActivity.bridge.getPlugin("PushNotifications");
if (pushPluginHandle != null) {
PushNotificationsPlugin pushPlugin = (PushNotificationsPlugin) pushPluginHandle.getInstance();
pushPlugin.fireNotification(remoteMessage);
}
// MainActivity.bridge.triggerJSEvent("pushNotificationReceived", jsonString);
// MainActivity.bridge.triggerWindowJSEvent("pushNotificationReceived", data.toString());
} else {
Log.e("MyFirebaseService", "Bridge not initialized");
}
// Show notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(R.mipmap.ic_launcher) // Replace with your app's notification icon
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
notificationManager.notify(0, builder.build());
}
}
here my implementation pushnotif in capacitorjs
export async function registerPushNotifications() {
try {
PushNotifications.requestPermissions().then((status) => {
console.log({status})
if (status.receive === 'granted') {
PushNotifications.addListener(
"pushNotificationReceived",
(notification) => {
console.log()
// console.log({notification: JSON.parse(notification)});
addGNotif(notification);
},
);
// Listener for errors
PushNotifications.addListener("registrationError", (error) => {
console.error("Push registration error:", error);
});
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
console.log(action)
alert("clicked")
});
FCM.getToken()
.then((r) => {
saveToken(r.token);
})
.catch((err) => console.log(err));
}
})
} catch (error) {
console.error('Push notification setup failed:', error);
}
}
here my backend php
use KreaitFirebaseFactory;
use KreaitFirebaseMessagingCloudMessage;
function appapp_sendPushNotification($registrationTokens, $title, $body, $data = []) {
// Initialize Firebase
$factory = (new Factory)
->withServiceAccount(ABSPATH.DIRECTORY_SEPARATOR.'wp-content'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'firebase-service-account.json'); // Optional if using Realtime Database
$messaging = $factory->createMessaging();
// Create the message
$message = CloudMessage::new()
->withNotification([
'title' => $title,
'body' => $body,
])->withTarget('token', $registrationTokens)->withHighestPossiblePriority()->withAndroidConfig(array('priority' => 'high', 'notification' => [
'title' => $title,
'body' => $body,
], 'data' => $data));
try {
$response = $messaging->send($message);
// $response = $messaging->sendMulticast($message, $registrationTokens);
error_log(json_encode($response));
return $response;
} catch (Throwable $e) {
error_log($e->getMessage());
return $e->getMessage();
}
}
my capacitor version is v.6
"@capacitor/android": "^6.1.2",
"@capacitor/app": "^6.0.2",
"@capacitor/cli": "^6.1.2",
"@capacitor/core": "^6.1.2",
"@capacitor/inappbrowser": "^1.0.2",
"@capacitor/keyboard": "^6.0.3",
"@capacitor/local-notifications": "^6.1.1",
"@capacitor/preferences": "^6.0.2",
"@capacitor/push-notifications": "^6.0.3",
my capacitor config
{
"appId": "com.appapp.omi",
"appName": "OMI App",
"webDir": "dist/client",
"allowNavigation": ["wa.me", "api.whatsapp.com", "orbitalmedika.co.id"],
"plugins": {
"PushNotifications": {
"presentationOptions": ["badge", "sound", "alert"]
},
"Keyboard": {
"resize": "none"
}
}
}
while app in foreground, notification is received but not while in background