skip to Main Content

When I completely close the app, receive an alarm, and click it, it goes into OnMessageReceived well,
Conversely, if you leave the app inactive in the background and receive an alarm and click it, it won’t work.

Well.. I tried to send an alarm by removing Notification and putting information only in Data, but nothing comes at all.

Unity script that handles messages.

using System.Collections.Generic;
using UnityEngine;
using Firebase.Messaging;
using Firebase;
using UnityEngine.Networking;
using Firebase.Auth;


public class FirebaseMessagingController : MonoBehaviour
{
    public static FirebaseMessagingController Instance { get; private set; }

    //public string firebaseFunctionsUrl;

    public FirebaseRealtimeDatabase firebaseRealtimeDatabase;

    public FirebaseUser currentUser;

    public string userId;

    public string userName;


    private void OnEnable()
    {
        SubscribeEvent();
    }

    private void OnDisable()
    {
        UnSubscribeEvent();
    }

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void SubscribeEvent()
    {
        FirebaseMessaging.TokenReceived += OnTokenReceived;
        FirebaseMessaging.MessageReceived += OnMessageReceived;
    }

    public void UnSubscribeEvent()
    {
        FirebaseMessaging.TokenReceived -= OnTokenReceived;
        FirebaseMessaging.MessageReceived -= OnMessageReceived;
    }

    public async void GetTokenAsync()
    {
        var task = FirebaseMessaging.GetTokenAsync();

        await task;

        if (task.IsCompleted)
        {
            Debug.Log("GET TOKEN ASYNC " + task.Result);
            firebaseRealtimeDatabase.StartCoroutineSaveUserIdToken(task.Result);
        }
    }

    // 디바이스 토큰 수신 이벤트 핸들러
    private void OnTokenReceived(object sender, TokenReceivedEventArgs token)
    {
        Debug.Log($"디바이스 토큰: {token.Token}");

        if (!PlayerPrefs.HasKey("Token"))
        {
            firebaseRealtimeDatabase.StartCoroutineSaveUserIdToken(token.Token);

            PlayerPrefs.SetString("Token", token.Token);
        }
    }


    private void OnMessageReceived(object sender, MessageReceivedEventArgs e)
    {
        Debug.Log("Received a new message");

        e.Message.Data.TryGetValue("click_action", out var clickAction);

        Debug.Log("clickAction : " + clickAction);

        if (clickAction == "********_MESSAGE")
        {
          
            Debug.Log("*********_MESSAGE");

            // 딥링크 처리
            if (e.Message.Data.TryGetValue("deep_link", out var deepLink))
            {
                Debug.Log("deepLink Process : " + deepLink);
                DynamicDeepLinkController.Instance.onDeepLinkActivated(deepLink);
                
            }
        }
    }

    public void SendMessage(string latitude, string longitude)
    {
        // Firebase Functions 엔드포인트 URL
        string url = "https://************.cloudfunctions.net/sendMessage";
        string message = $"{userName} left a message at {latitude},{longitude}";

        // 요청에 필요한 데이터 구성
        var formData = new WWWForm();
        formData.AddField("writerUid", DynamicDeepLinkController.Instance.writerUid);
        formData.AddField("userId", userId);
        formData.AddField("userName", userName);
        formData.AddField("latitude", latitude);
        formData.AddField("longitude", longitude);
        formData.AddField("message", message);

        // 요청 보내기
        UnityWebRequest request = UnityWebRequest.Post(url, formData);
        request.SendWebRequest();

        // 응답 처리
        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("Failed to send message: " + request.error);
        }
        else
        {
            if (request.responseCode >= 200 && request.responseCode < 300)
            {
                Debug.Log("Message sent successfully");
            }
            else
            {
                Debug.LogError("Failed to send message. Response code: " + request.responseCode);
            }
        }
    }
}

The typescript of the Firebase function is as follows.

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import serviceAccount from "../service-account.json";

// Firebase Admin SDK 초기화
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount as admin.ServiceAccount),
  databaseURL: "https://*********-default-rtdb.firebaseio.com/",
});

// FCM 인스턴스 가져오기
const fcm = admin.messaging();

export const sendMessage = functions.https.onRequest(async (req, res) => {
  const writerUid = req.body.writerUid as string;
  const userId = req.body.userId as string;
  const userName = req.body.userName as string;
  const latitude = req.body.latitude as string;
  const longitude = req.body.longitude as string;
  const receivedMessage = req.body.message as string;

  const userNameReplace = userName.replace(" ", "+");

  // 사용자 아이디를 기반으로 토큰 검색
  const tokenSnapshot =
  await admin.database().ref(`users/${writerUid}/token`).once("value");
  const token = tokenSnapshot.val();

  functions.logger.log(`writerUid : ${writerUid}`);
  functions.logger.log(`userId : ${userId}`);
  functions.logger.log(`userName : ${userName}`);
  functions.logger.log(`token : ${token}`);
  functions.logger.log(`latitude : ${latitude}`);
  functions.logger.log(`longitude : ${longitude}`);
  functions.logger.log(`receivedMessage : ${receivedMessage}`);
  functions.logger.log(`userNameReplace : ${userNameReplace}`);


  if (!token) {
    res.status(404).send("User token not found");
    return;
  }

  functions.logger.log(`click_action : ********://message?${latitude}?${longitude}?${userId}?${userNameReplace}`);

  // 메시지 페이로드 생성
  const message = {
    notification: {
      title: userName,
      body: receivedMessage,
    },
    data: {
      // title: userName,
      // body: receivedMessage,
      click_action: "********_MESSAGE",
      deep_link: `********://message?${latitude}?${longitude}?${userId}?${userNameReplace}`,
    },
    token: token,
  };

  // 메시지 보내기
  try {
    await fcm.send(message);
    functions.logger.log("메시지를 성공적으로 보냈습니다.");
    res.status(200).send("Message sent successfully");
  } catch (error) {
    functions.logger.log("메시지 보내기 중 오류가 발생했습니다:", error);
    res.status(500).send("Error sending message");
  }
});

2

Answers


  1. Chosen as BEST ANSWER

    When the app is alive and inactive in the background, the alarm comes, but it gave me a headache because it didn't return with OnMessageReceived. After asking ChatGPT for a day or two, it told me the code to find the deep_link item of Android intent and take it away, so I succeeded after several failures. I don't know why they divided the types of alarms like this in the first place. Each of them may have had their own circumstances, but this doesn't seem to be the case.

    public void CheckDeepLink()
        {
    
    #if UNITY_ANDROID
    
            Debug.Log("CheckDeepLink");
    
    
            AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
    
            AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>("getIntent");
            AndroidJavaObject extras = intent.Call<AndroidJavaObject>("getExtras");
    
            if (extras != null)
            {
                Debug.Log("extras != null");
    
                // 디버그용: extras 객체에 포함된 모든 키와 값을 출력합니다.
                AndroidJavaObject keySet = extras.Call<AndroidJavaObject>("keySet");
                AndroidJavaObject[] keys = keySet.Call<AndroidJavaObject[]>("toArray");
    
                foreach (AndroidJavaObject key in keys)
                {
                    string keyString = key.Call<string>("toString");
                    AndroidJavaObject value = extras.Call<AndroidJavaObject>("get", key);
    
                    string valueString = "null";
    
                    if (value != null)
                    {
                        valueString = value.Call<string>("toString");
                    }
    
                    Debug.Log("Key: " + keyString + ", Value: " + valueString);
                }
    
    
    
                if (extras.Call<bool>("containsKey", "deep_link"))
                {
                    Debug.Log("extras.Call<bool> containsKey, deep_link");
    
                    string deepLink = extras.Call<string>("getString", "deep_link");
                    DynamicDeepLinkController.Instance.onDeepLinkActivated(deepLink);
                }
            }
            else if (extras == null)
            {
                Debug.Log("extras == null");
            }
    #endif
        }
    

    I don't know what else to do with iOS. sick of it I'll post it later if I have time.


  2. Well.. I tried to send an alarm by removing Notification

    From the appearance of the following excerpt it seems the Notification field is still full. Is there another place where you are sending a message with no notification field? If so, please post it.

        // 메시지 페이로드 생성
      const message = {
        notification: {
          title: userName,
          body: receivedMessage,
        },
        data: {
          // title: userName,
          // body: receivedMessage,
          click_action: "********_MESSAGE",
          deep_link: `********://message?${latitude}?${longitude}?${userId}?${userNameReplace}`,
        },
        token: token,
      };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search