How to receive Firebase notifications in the background in Android?

senanur incekara - Oct 9 - - Dev Community

I am developing an Android application that uses Firebase Cloud Messaging (FCM) to send notifications for incoming calls. I want to ensure that notifications are received even when the app is in the background. I have noticed that notifications only appear when the app is in the foreground. They do not show up when the app is running in the background

when android in backgorund . Logcat :

win=Window{f06d548 u0 com.example.tr/com.example.tr.MainActivity} destroySurfaces: appStopped=true cleanupOnResume=false win.mWindowRemovalAllowed=false win.mRemoveOnExit=false win.mViewVisibility=8 caller=com.android.server.wm.ActivityRecord.destroySurfaces:6862 com.android.server.wm.ActivityRecord.destroySurfaces:6843 com.android.server.wm.ActivityRecord.activityStopped:7528 com.android.server.wm.ActivityClientController.activityStopped:310 android.app.IActivityClientController$Stub.onTransact:702 com.android.server.wm.ActivityClientController.onTransact:175 android.os.Binder.execTransactInternal:1380
Enter fullscreen mode Exit fullscreen mode
<?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"
        android:usesCleartextTraffic="true">

        <!-- Firebase Messaging Service -->
        <service
            android:name=".MyFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

         <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="incoming_calls" />


            <activity android:name=".IncomingCallActivity"></activity>




        <!-- Main Activity -->
        <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>
        </activity>

        <!-- File Provider for handling file URIs -->
        <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
                android:name="com.google.firebase.messaging.default_notification_icon"
                android:resource="@mipmap/ic_launcher_round" />
            <meta-data
                android:name="com.google.firebase.messaging.default_notification_color"
                android:resource="@color/colorAccent" />
        </provider>

    </application>

    <!-- Permissions -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <!-- Incoming Call Permissions Start -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <permission
        android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
        android:protectionLevel="signature" />
    <!-- Incoming Call Permissions End -->



</manifest>
Enter fullscreen mode Exit fullscreen mode

MyFirebaseMessagingService.java



package com.example.tr;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.content.Context;
import android.os.Vibrator;
import androidx.core.app.NotificationCompat;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "MyFirebaseMsgService";
    private static final int NOTIFICATION_ID = 0;
    private static final int MISSED_CALL_NOTIFICATION_ID = 1;

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        if (remoteMessage.getData().size() > 0) {
            sendNotification(remoteMessage);
        }

         if (remoteMessage.getNotification() != null) {
            sendNotification(remoteMessage);
        }

    }

    private void sendNotification(RemoteMessage remoteMessage) {
        String title = "INCOMING CALL ";
        String body = remoteMessage.getData().get("callerName") + "Sizi arıyor ";


        //-->
       Intent intent = new Intent(this, IncomingCallActivity.class);

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.putExtra("callerName", remoteMessage.getData().get("callerName"));
        intent.putExtra("callId", remoteMessage.getData().get("callId"));

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        Intent acceptIntent = new Intent(this, IncomingCallActivity.class);

        acceptIntent.putExtra("callAction", "accept");
        acceptIntent.putExtra("callerName", remoteMessage.getData().get("callerName"));
        acceptIntent.putExtra("callId", remoteMessage.getData().get("callId"));

        Intent declineIntent = new Intent(this, IncomingCallActivity.class);
        declineIntent.putExtra("callAction", "decline");
        declineIntent.putExtra("callerName", remoteMessage.getData().get("callerName"));
        declineIntent.putExtra("callId", remoteMessage.getData().get("callId"));

       PendingIntent acceptPendingIntent = PendingIntent.getActivity(this, 1, acceptIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
       PendingIntent declinePendingIntent = PendingIntent.getActivity(this, 2, declineIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "incoming_calls")
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setAutoCancel(true)
                .addAction(R.drawable.ic_accept, "Answer", acceptPendingIntent)
                .addAction(R.drawable.ic_decline, "Decline", declinePendingIntent)
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setCategory(NotificationCompat.CATEGORY_CALL)
                .setVibrate(new long[]{0, 1000, 800})
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setFullScreenIntent(pendingIntent, true);

        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("incoming_calls", "Incoming Calls", NotificationManager.IMPORTANCE_HIGH);
            notificationManager.createNotificationChannel(channel);
        }

        notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());

        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        if (vibrator != null) {
            vibrator.vibrate(new long[]{0, 1000, 800}, 0);
        }

        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                notificationManager.cancel(NOTIFICATION_ID);
                sendMissedCallNotification(remoteMessage.getData().get("callerName"));

                if (vibrator != null) {
                    vibrator.cancel();
                }
            }
        }, 3000);
    }

    private void sendMissedCallNotification(String callerName) {
        String title = "Missed Call";
        String body = "You missed a call from " + callerName;

        NotificationCompat.Builder missedCallBuilder = new NotificationCompat.Builder(this, "missed_calls")
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH);

        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("missed_calls", "Missed Calls", NotificationManager.IMPORTANCE_HIGH);
            notificationManager.createNotificationChannel(channel);
        }

        notificationManager.notify(MISSED_CALL_NOTIFICATION_ID, missedCallBuilder.build());
    }
}
Enter fullscreen mode Exit fullscreen mode


package com.example.tr;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.os.Bundle; 
import com.getcapacitor.BridgeActivity;
import com.google.firebase.FirebaseApp; 

public class MainActivity extends BridgeActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    FirebaseApp.initializeApp(this);

    createNotificationChannel();
  }

  private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      NotificationChannel channel = new NotificationChannel(
        "incoming_calls", // Channel ID
        "Incoming Calls",  // Channel name
        NotificationManager.IMPORTANCE_HIGH 
      );
      channel.setDescription("Channel for incoming call notifications");
      NotificationManager manager = getSystemService(NotificationManager.class);
      if (manager != null) {
        manager.createNotificationChannel(channel);
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
IncomingCallActivity.java


package com.example.tr;

import android.widget.Button;
import android.widget.TextView;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Vibrator;
import android.util.Log;

public class IncomingCallActivity extends AppCompatActivity {

    private Vibrator vibrator;

    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_incoming_call);

        Intent intent = getIntent();
        String callerName = intent.getStringExtra("callerName");
        String callId = intent.getStringExtra("callId");
        String callAction = intent.getStringExtra("callAction");

        TextView callerNameTextView = findViewById(R.id.caller_name);
        callerNameTextView.setText(callerName);

        vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);

        Button acceptButton = findViewById(R.id.answer_button);
        acceptButton.setOnClickListener(v -> {
            Log.d("IncomingCallActivity", "Kabul butonuna tıklandı");
            // finish();
            if (vibrator != null) {
                vibrator.cancel();
            }
        });

        Button declineButton = findViewById(R.id.decline_button);
        declineButton.setOnClickListener(v -> {
            Log.d("IncomingCallActivity", "Reddet butonuna tıklandı");
            // finish();
            if (vibrator != null) {
                vibrator.cancel();
            }
        });
    }
}
Enter fullscreen mode Exit fullscreen mode
api.service.ts:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  static sendNotification(deviceToken: string) {
    throw new Error("Method not implemented.");
  }
  private apiUrl = '';
  private accessToken =""
      constructor(private http: HttpClient) {}


  sendNotification(token: string ): Observable<any> {
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${this.accessToken}`
    });

    console.log("send push noti token ->",token)
    const notificationData = {
      token: token, 
      // notification: {
      //   title: 'Incoming Calls',
      //   body: 'aramanız varr',
      // },
      data: {
        title: 'Incoming Call',
        body: 'Cevapsız aramanız var ',
        callType: 'incoming',
        callerName: 'John Doe',
        callId: '12345',
        priority: 'high'
      },
      android: {
        priority: 'high',
        notification: {
          channel_id: 'incoming_calls',
          sound: 'default',
          // full_screen_intent: true,  
        },
      },
    };


    const body = {
      message: notificationData
    };

    return this.http.post<any>(this.apiUrl, body, { headers });
  }


}```




`Home.page.ts`

``
import { Component } from "@angular/core";
import {
  FirebaseMessaging,
  GetTokenOptions,
} from "@capacitor-firebase/messaging";
import { Capacitor } from "@capacitor/core";
import { IonicModule } from "@ionic/angular";
import { environment } from "src/environments/environment";

import { NotificationService } from '../services/notification.service';
import { ApiService } from "../api/api.service";

@Component({
  selector: "app-home",
  templateUrl: "home.page.html",
  styleUrls: ["home.page.scss"],
  standalone: true,
  imports: [IonicModule],
})
export class HomePage {
  public token = "";

  constructor(
    private notificationService: NotificationService,
    private apiService: ApiService  
  ) {

    FirebaseMessaging.addListener("notificationReceived", (event) => {
      console.log("notificationReceived: ", { event });
    });
    FirebaseMessaging.addListener("notificationActionPerformed", (event) => {
      console.log("notificationActionPerformed: ", { event });
    });
    if (Capacitor.getPlatform() === "web") {
      navigator.serviceWorker.addEventListener("message", (event: any) => {
        console.log("serviceWorker message: ", { event });
        const notification = new Notification(event.data.notification.title, {
          body: event.data.notification.body,
        });
        notification.onclick = (event) => {
          console.log("notification clicked: ", { event });
        };
      });
    }
  }

  public async requestPermissions(): Promise<void> {
    const result = await FirebaseMessaging.requestPermissions();
    if (result.receive === 'granted') {
      console.log('Push notifications permission granted');
    }
  }


  public async getToken(): Promise<void> {
    const options: GetTokenOptions = {
      vapidKey: environment.firebase.vapidKey,
    };
    if (Capacitor.getPlatform() === "web") {
      options.serviceWorkerRegistration =
        await navigator.serviceWorker.register("firebase-messaging-sw.js");
    }
    const { token } = await FirebaseMessaging.getToken(options);
    this.token = token;
  }



  sendPushNotification() {
    const deviceToken = "fIuEs9LlRwO6J06ahgWCtC:APA91bF5VnhsCYAyHxudm1de2s4sVYfUWkenKl8zvOxbjHa2_eOv5MlU2FNTogrPYu4bCJKKiNxM7LpQvc7w_iW59fKGoevE0OjYnYPrxHjj8x5T7uvqdW3_j3HXpTj3F_DrLYeBVpX4"
    console.log("Device token is here -> : ", deviceToken);

    if (!deviceToken) {
      console.error('No device token available. Unable to send notification.');
      return;
    }

    this.apiService.sendNotification(deviceToken).subscribe(
      (response: any) => {
        console.log('Push notification sent:', response);
      },
      (error: any) => {
        console.error('Error sending notification:', error);
        console.error('Full error response:', JSON.stringify(error.error));
      }
    );
  }


}
```
Enter fullscreen mode Exit fullscreen mode
.
Terabox Video Player