ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [.NET MAUI, FCM] 안드로이드 앱 알림 보내기
    [.NET] 공부 기록/MAUI 2025. 6. 18. 14:00

    안녕하세요! Becca 입니다.

    오늘은 .NET MAUIFCM을 이용해서 안드로이드 앱을 만들고, 알림을 보내는 과정을 정리해보았습니다.


     

    🖥️ 개발 환경

     

    .NET MAUI (Multi-platform App UI)

    ◆ C#과 XAML을 사용하여 네이티브 모바일 및 데스크톱 앱을 만들기 위한 크로스 플랫폼 프레임워크

    ◆ 단일 공유 코드 베이스에서 Android, iOS, macOS, Windows에서 실행할 수 있는 앱 개발 가능

    Visual Studio 2022 17.12 이상 필요 (.NET 8.0)

     

    FCM (Firebase Cloud Messaging)

    ◆ 메시지를 안정적으로 전송할 수 있는 크로스 플랫폼 메시징 솔루션

    ◆ 알림 메시지/데이터 메시지 전송 기능

    Android 5.0, API Level 21(Lollipop) 이상 필요

     


     

    📑 프로젝트 만들기

    1. .NET MAUI 설치

     

    2. 새 프로젝트 만들기

     

    3. NuGet 패키지 설치

    ※ 플러그인 최신 버전은 Android 14.0, API 34부터 실행 가능

     

    Plugin.Firebase 설치 실패하는 경우

    1. Ctrl + `로 터미널을 열기

    2. 루트 프로젝트 디렉토리로 이동

    3. 'dotnet add package Plugin.Firebase'를 입력

     

    4. Mac Catalyst, Windows 삭제

    [ MauiAlarm.csproj ]

    <PropertyGroup>
    	<TargetFrameworks>net8.0-android;</TargetFrameworks>
    	<!-- 생략 -->
    	<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
    </PropertyGroup>

    ◆ 플러그인에서 Mac Catalyst, Windows를 지원하지 않음

    ◆ 이 프로젝트에서 iOS는 사용하지 않아 삭제

     


     

    ⚙️ Firebase Console 설정

    1. 프로젝트 만들기

    ◆ Firebase Console 접속 (구글 계정으로 로그인이 필요합니다!)

     

    2. Android 선택

     

    3. 앱 등록

    패키지 이름(Application ID)

    ◆ 기기와 Google Play 스토어에서 앱을 고유하게 식별하는 역할

    앱에서 실제로 사용 중인 패키지 이름을 입력해야 함

    ◆ Firebase 프로젝트에 등록한 후에는 변경 불가능

    ◆ MAUI 프로젝트에서는 반드시 .csproj의 ApplicationId를 사용해야 함 ⭐⭐⭐

    <ApplicationId>com.companyname.mauialarm</ApplicationId>

     

    4. google-services.json 파일 다운로드 후 추가

     

    ◆ google-service.json의 package_name이 ApplicationId와 같은지 확인 ⭐⭐⭐

    [ google-service.json ]

    "android_client_info": {
      "package_name": "com.companyname.mauialarm"
    }

    [ MauiAlarm.csproj ]

    <ApplicationId>com.companyname.mauialarm</ApplicationId>

     

     

    ◆ TargetFramework 추가

    [ MauiAlarm.csproj ]

    <ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
    	<GoogleServicesJson Include="google-services.json" />
    </ItemGroup>

     

     

    5. 설정 완료

     


     

    🔔 알림 보내기

    1. Firebase 초기화

    [ MauiProgram.cs ]

    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .RegisterFirebaseServices() // 추가
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
    
    #if DEBUG
        builder.Logging.AddDebug();
    #endif
    
        return builder.Build();
    }
    
    private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
    {
        builder.ConfigureLifecycleEvents(events => {
    #if ANDROID
            events.AddAndroid(android => android.OnCreate((activity, _) =>
            {
                CrossFirebase.Initialize(activity, CreateCrossFirebaseSettings()); // 초기화
            }));
    #endif
        });
    
        builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);
        return builder;
    }

     

    2. Cloud Messaging(푸시 알림) 활성화

    [ MauiProgram.cs ]

    private static CrossFirebaseSettings CreateCrossFirebaseSettings()
    {
        return new CrossFirebaseSettings(
            isAuthEnabled: true,
            isCloudMessagingEnabled: true);
    }

     

    3. 빌드 오류 방지를 위한 ItemGroup 추가

    [ MauiAlarm.csproj ]

    <ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
    	<PackageReference Include="Xamarin.Kotlin.StdLib.Jdk7" Version="1.9.23.3" ExcludeAssets="build;buildTransitive" />
    	<PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="1.9.23.3" ExcludeAssets="build;buildTransitive" />
    </ItemGroup>
    
    <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
    	<PackageReference Include="Xamarin.AndroidX.Core" Version="1.15.0.1" />
    	<PackageReference Include="Xamarin.AndroidX.Collection" Version="1.4.5.1" />
    	<PackageReference Include="Xamarin.AndroidX.Collection.Ktx" Version="1.4.5.1" />
    	<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.9.3.1" />
    	<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.8.0.7" />
    	<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core" Version="2.8.7.1" />
    	<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core.Ktx" Version="2.8.7.1" />
    </ItemGroup>

     

    4. Crashlytics 설정

    [ MauiProgram.cs ]

    private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
    {
        builder.ConfigureLifecycleEvents(events => {
    #if ANDROID
            events.AddAndroid(android => android.OnCreate((activity, _) =>
            {
                CrossFirebase.Initialize(activity, CreateCrossFirebaseSettings());
                CrossFirebaseCrashlytics.Current.SetCrashlyticsCollectionEnabled(true); // Crashlytics
            }));
    #endif
        });
    
        builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);
        return builder;
    }
    
    private static CrossFirebaseSettings CreateCrossFirebaseSettings()
    {
        return new CrossFirebaseSettings(
            isAuthEnabled: true,
            isCloudMessagingEnabled: true,
            isAnalyticsEnabled: true); // Crashlytics
    }

    ◆ Crashlytics: 실시간 비정상 종료 보고 도구

    ◆ 1, 2번 코드에서 Crashlytics 관련 코드를 추가

     

    5. strings.xml 추가

    [ strings.xml ]

    <?xml version="1.0" encoding="utf-8" ?>
    <resources>
    	<string name="com.google.firebase.crashlytics.mapping_file_id">none</string>
    </resources>

     

     

    6. Android 설정

    [ AndroidManifest.xml ]

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
    	<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
    		<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
    		<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" />
    				<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
    				<category android:name="${applicationId}" />
    			</intent-filter>
    		</receiver>
    	</application>
    	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    	<uses-permission android:name="android.permission.INTERNET" />
    	<uses-sdk android:minSdkVersion="21" />
    </manifest>

    [ MainActivity.cs ]

    [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    public class MainActivity : MauiAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            HandleIntent(Intent);
            CreateNotificationChannelIfNeeded();
        }
    
        protected override void OnNewIntent(Intent intent)
        {
            base.OnNewIntent(intent);
            HandleIntent(intent);
        }
    
        private static void HandleIntent(Intent intent)
        {
            FirebaseCloudMessagingImplementation.OnNewIntent(intent);
        }
    
        private void CreateNotificationChannelIfNeeded()
        {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                CreateNotificationChannel();
            }
        }
    
        private void CreateNotificationChannel()
        {
            var channelId = $"{PackageName}.general";
            var notificationManager = (NotificationManager)GetSystemService(NotificationService);
            var channel = new NotificationChannel(channelId, "General", NotificationImportance.Default);
            notificationManager.CreateNotificationChannel(channel);
            FirebaseCloudMessagingImplementation.ChannelId = channelId;
        }
    }

     

    7. 버튼 클릭으로 FCM 등록 토큰 얻기

    [ MainPage.xaml ]

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MauiAlarm.MainPage">
        <ScrollView>
            <VerticalStackLayout Padding="30,0" Spacing="25">
                <Button
                    x:Name="CounterBtn"
                    Text="GetToken"
                    Clicked="OnGetTokenBtnClicked"
                    HorizontalOptions="Center" />
            </VerticalStackLayout>
        </ScrollView>
    </ContentPage>

    [ MainPage.xaml.cs ]

    private async void OnGetTokenBtnClicked(object sender, EventArgs e)
    {
        await CrossFirebaseCloudMessaging.Current.CheckIfValidAsync();
        var token = await CrossFirebaseCloudMessaging.Current.GetTokenAsync();
        Console.WriteLine($"FCM token: {token}");
    }

     

    8. Firebase 알림 메시지 만들기

     

    9. 테스트 메시지 보내기

     


     

    ➕ 전체 코드

    [ MauiAlarm.csproj ]

    더보기
    <Project Sdk="Microsoft.NET.Sdk">
    	<PropertyGroup>
    		<TargetFrameworks>net8.0-android;</TargetFrameworks>
    
    		<OutputType>Exe</OutputType>
    		<RootNamespace>MauiAlarm</RootNamespace>
    		<UseMaui>true</UseMaui>
    		<SingleProject>true</SingleProject>
    		<ImplicitUsings>enable</ImplicitUsings>
    		<Nullable>enable</Nullable>
    
    		<!-- Display name -->
    		<ApplicationTitle>MauiAlarm</ApplicationTitle>
    
    		<!-- App Identifier -->
    		<ApplicationId>com.companyname.mauialarm</ApplicationId>
    
    		<!-- Versions -->
    		<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
    		<ApplicationVersion>1</ApplicationVersion>
    
    		<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
    	</PropertyGroup>
    
    	<ItemGroup>
    		<!-- App Icon -->
    		<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
    
    		<!-- Splash Screen -->
    		<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
    
    		<!-- Images -->
    		<MauiImage Include="Resources\Images\*" />
    		<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
    
    		<!-- Custom Fonts -->
    		<MauiFont Include="Resources\Fonts\*" />
    
    		<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
    		<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
    	</ItemGroup>
    
    	<ItemGroup>
    	  <None Remove="google-services.json" />
    	  <None Remove="Platforms\Android\Resources\values\strings.xml" />
    	</ItemGroup>
    
    	<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
    	  <GoogleServicesJson Include="google-services.json" />
    	</ItemGroup>
    
    	<ItemGroup>
    		<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
    		<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
    		<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
    		<PackageReference Include="Plugin.Firebase" Version="3.1.4" />
    		<PackageReference Include="Plugin.Firebase.Crashlytics" Version="3.1.1" />
    	</ItemGroup>
    
    	<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
    		<PackageReference Include="Xamarin.AndroidX.Core" Version="1.15.0.1" />
    		<PackageReference Include="Xamarin.AndroidX.Collection" Version="1.4.5.1" />
    		<PackageReference Include="Xamarin.AndroidX.Collection.Ktx" Version="1.4.5.1" />
    		<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.9.3.1" />
    		<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.8.0.7" />
    		<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core" Version="2.8.7.1" />
    		<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core.Ktx" Version="2.8.7.1" />
    	</ItemGroup>
    
    	<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
    		<PackageReference Include="Xamarin.Kotlin.StdLib.Jdk7" Version="1.9.23.3" ExcludeAssets="build;buildTransitive" />
    		<PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="1.9.23.3" ExcludeAssets="build;buildTransitive" />
    	</ItemGroup>
    </Project>

     

    [ MauiProgram.cs ]

    더보기
    using Microsoft.Extensions.Logging;
    using Microsoft.Maui.LifecycleEvents;
    using Plugin.Firebase.Auth;
    using Plugin.Firebase.Bundled.Shared;
    using Plugin.Firebase.Crashlytics;
    #if ANDROID
    using Plugin.Firebase.Bundled.Platforms.Android;
    #endif
    
    namespace MauiAlarm
    {
        public static class MauiProgram
        {
            public static MauiApp CreateMauiApp()
            {
                var builder = MauiApp.CreateBuilder();
                builder
                    .UseMauiApp<App>()
                    .RegisterFirebaseServices()
                    .ConfigureFonts(fonts =>
                    {
                        fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                        fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                    });
    
    #if DEBUG
        		builder.Logging.AddDebug();
    #endif
    
                return builder.Build();
            }
    
            private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
            {
                builder.ConfigureLifecycleEvents(events => {
    #if ANDROID
                    events.AddAndroid(android => android.OnCreate((activity, _) =>
                    {
                        CrossFirebase.Initialize(activity, CreateCrossFirebaseSettings());
                        CrossFirebaseCrashlytics.Current.SetCrashlyticsCollectionEnabled(true);
                    }));
    #endif
                });
    
                builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);
                return builder;
            }
    
            private static CrossFirebaseSettings CreateCrossFirebaseSettings()
            {
                return new CrossFirebaseSettings(
                    isAuthEnabled: true,
                    isCloudMessagingEnabled: true,
                    isAnalyticsEnabled: true);
            }
        }
    }

     

    [ strings.xml ]

    더보기
    <?xml version="1.0" encoding="utf-8" ?>
    <resources>
    	<string name="com.google.firebase.crashlytics.mapping_file_id">none</string>
    </resources>

     

    [ AndroidManifest.xml ]

    더보기
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
    	<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
    		<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
    		<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" />
    				<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
    				<category android:name="${applicationId}" />
    			</intent-filter>
    		</receiver>
    	</application>
    	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    	<uses-permission android:name="android.permission.INTERNET" />
    	<uses-sdk android:minSdkVersion="21" />
    </manifest>

     

    [ MainActivity.cs ]

    더보기
    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using Plugin.Firebase.CloudMessaging;
    
    namespace MauiAlarm
    {
        [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
        public class MainActivity : MauiAppCompatActivity
        {
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                HandleIntent(Intent);
                CreateNotificationChannelIfNeeded();
            }
    
            protected override void OnNewIntent(Intent intent)
            {
                base.OnNewIntent(intent);
                HandleIntent(intent);
            }
    
            private static void HandleIntent(Intent intent)
            {
                FirebaseCloudMessagingImplementation.OnNewIntent(intent);
            }
    
            private void CreateNotificationChannelIfNeeded()
            {
                if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
                {
                    CreateNotificationChannel();
                }
            }
    
            private void CreateNotificationChannel()
            {
                var channelId = $"{PackageName}.general";
                var notificationManager = GetSystemService(NotificationService) as NotificationManager;
                var channel = new NotificationChannel(channelId, "General", NotificationImportance.Default);
                notificationManager.CreateNotificationChannel(channel);
                FirebaseCloudMessagingImplementation.ChannelId = channelId;
                //FirebaseCloudMessagingImplementation.SmallIconRef = Resource.Drawable.ic_push_small;
            }
        }
    }

     

    [ MainPage.xaml ]

    더보기
    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MauiAlarm.MainPage">
        <ScrollView>
            <VerticalStackLayout
                Padding="30,0"
                Spacing="25">
                <Image
                    Source="dotnet_bot.png"
                    HeightRequest="185"
                    Aspect="AspectFit"
                    SemanticProperties.Description="dot net bot in a race car number eight" />
    
                <Label
                    Text="Hello, World!"
                    Style="{StaticResource Headline}"
                    SemanticProperties.HeadingLevel="Level1" />
    
                <Label
                    Text="Welcome to &#10;.NET Multi-platform App UI"
                    Style="{StaticResource SubHeadline}"
                    SemanticProperties.HeadingLevel="Level2"
                    SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
    
                <Button
                    x:Name="CounterBtn"
                    Text="GetToken"
                    Clicked="OnGetTokenBtnClicked"
                    HorizontalOptions="Center" />
            </VerticalStackLayout>
        </ScrollView>
    </ContentPage>

     

    [ MainPage.xaml.cs ]

    더보기
    using Plugin.Firebase.CloudMessaging;
    
    namespace MauiAlarm
    {
        public partial class MainPage : ContentPage
        {
            public MainPage()
            {
                InitializeComponent();
            }
    
            private async void OnGetTokenBtnClicked(object sender, EventArgs e)
            {
                await CrossFirebaseCloudMessaging.Current.CheckIfValidAsync();
                var token = await CrossFirebaseCloudMessaging.Current.GetTokenAsync();
                Console.WriteLine($"FCM token: {token}");
            }
        }
    }

     


     

    🔗 참고 자료

    https://learn.microsoft.com/ko-kr/dotnet/maui/get-started/installation?view=net-maui-9.0&tabs=visual-studio

     

    Visual Studio 2022 및 Visual Studio Code를 설치하여 .NET MAUI를 사용하여 플랫폼 간 앱 개발 - .NET MAUI

    .NET MAUI 확장을 사용하여 Visual Studio 2022 및 Visual Studio Code를 설치하여 .NET MAUI를 사용하여 네이티브 플랫폼 간 앱을 개발하는 방법을 알아봅니다.

    learn.microsoft.com

    https://github.com/TobiasBuchholz/Plugin.Firebase

     

    GitHub - TobiasBuchholz/Plugin.Firebase: Wrapper around the native Android and iOS Firebase Xamarin SDKs

    Wrapper around the native Android and iOS Firebase Xamarin SDKs - TobiasBuchholz/Plugin.Firebase

    github.com

    https://cedricgabrang.medium.com/firebase-push-notifications-in-net-maui-android-32c808844d7e

     

    Firebase Push Notifications in .NET MAUI (Android)

    In this post, you’ll learn how to implement push notifications in your .NET MAUI application using Firebase.

    cedricgabrang.medium.com

    https://firebase.google.com/docs/cloud-messaging/?hl=ko&authuser=0&_gl=1*14srlya*_ga*%0BMTU2Mzg5OTk2OC4xNzI3MjQ4OTAw*_ga_CW55HF8NVT*%0BMTczNjkyNDU2MC4xMy4xLjE3MzY5MjQ2NzYuMjQuMC4w#implementation_paths

     

    Firebase Cloud Messaging

    Firebase 클라우드 메시징(FCM)은 메시지를 안정적으로 전송할 수 있는 크로스 플랫폼 메시징 솔루션입니다.

    firebase.google.com

    https://firebase.google.com/docs/cloud-messaging/android/first-message?hl=ko&authuser=0&_gl=1*14vjx6h*%0B_up*MQ..*_ga*NDM4MjA4ODY2LjE3MzY5Mjc5MDA.*_ga_CW55HF8NVT*%0BMTczNjkyNzkwMC4xLjAuMTczNjkyNzkwMC4wLjAuMA..

     

    백그라운드 앱에 테스트 메시지 보내기  |  Firebase Cloud Messaging

    새로운 Firebase Studio 기능부터 AI 통합 방법까지 I/O에서 발표된 모든 내용을 확인해 보세요. 블로그 읽기 의견 보내기 백그라운드 앱에 테스트 메시지 보내기 컬렉션을 사용해 정리하기 내 환경설

    firebase.google.com

     

    댓글

Designed by Tistory.