http://board.sorie.net/send_push/iping/android/send_g_push.html {"data":{"data":{"title":"1","message":"1","image_url":"","site":""}},"priority":"high","content-available":true,"to":"\/topics\/android_iping2"} {"error":"Deprecated endpoint, see https:\/\/firebase.google.com\/docs\/cloud-messaging\/migrate-v1"} ´Ê¾ú½À´Ï´Ù. ¾Ë¸²ÀÌ ¾È°¡´Â ÀÌÀ¯°¡.. 2024³â 6/30ÀϺηΠ¾Ë¸² º¸³»´Â ¹æ½ÄÀ» http v1À¸·Î ¹Ù²Ù¶ó°í Çߴµ¥ ³¯Â¥ Áö³­ ÈÄ¿¡µµ ÀÌÀü ¹æ½ÄÀ» Áö¿øÇÏ´Ù°¡ ÀÌÁ¦´Â ´õ ÀÌ»ó Áö¿øÀ» ¾ÈÇÏ´Â °ÍÀÔ´Ï´Ù. {"data":{"data":{"title":"1","message":"1","image_url":"","site":""}},"priority":"high","content-available":true,"to":"\/topics\/android_iping2"} {"error":"Deprecated endpoint, see https:\/\/firebase.google.com\/docs\/cloud-messaging\/migrate-v1"} ========================= "error":"Deprecated endpoint, see https:\/\/firebase.google.com\/docs\/cloud-messaging\/migrate-v1" À§ ¸Þ½ÃÁö´ë·Î ¾Æ·¡ »çÀÌÆ® µé¾î°¡´Ï https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=ko http v1 ¹æ½ÄÀ¸·Î ¾÷µ¥ÀÌÆ®Ç϶ó°í ³ª¿É´Ï´Ù. ====== http v1 FCM(Firebase Cloud Messaging) HTTP v1 API¿¡¼­´Â ´ÜÀÏ ¿äûÀ¸·Î ¿©·¯ ÀåÄ¡ ÅäÅ«¿¡ ¸Þ½ÃÁö¸¦ º¸³»´Â °ÍÀÌ ·¹°Å½Ã API¿¡¼­Ã³·³ Á÷Á¢ Áö¿øµÇÁö ¾Ê½À´Ï´Ù. ·¹°Å½Ã API¿¡¼­´Â 'registration_ids' Çʵ忡 ÅäÅ«À» Æ÷ÇÔ½ÃÄÑ ¿©·¯ ÅäÅ«¿¡ ¸Þ½ÃÁö¸¦ º¸³¾ ¼ö ÀÖ½À´Ï´Ù. ±×·¯³ª HTTP v1 API¿¡¼­ token Çʵå´Â ´ÜÀÏ ÀåÄ¡ ÅäÅ«¸¸ Çã¿ëÇÕ´Ï´Ù. ÁøÇà ¹æ¹ýÀº ´ÙÀ½°ú °°½À´Ï´Ù. ÁÖÁ¦ »ç¿ë: ÀåÄ¡¿¡¼­ ÁÖÁ¦ ±¸µ¶: ÀÌÀü¿¡ ¸Þ½ÃÁö¸¦ ÁÖÁ¦·Î º¸³½ °æ¿ì °è¼ÓÇØ¼­ º¸³¾ ¼ö ÀÖ½À´Ï´Ù. ¸ðµç ÀåÄ¡ ÅäÅ«ÀÌ Æ¯Á¤ ÁÖÁ¦¸¦ ±¸µ¶ÇÏ´ÂÁö È®ÀÎÇϼ¼¿ä. ÁÖÁ¦¿¡ ¸Þ½ÃÁö º¸³»±â: ÁÖÁ¦¿¡ ´ÜÀÏ ¸Þ½ÃÁö¸¦ º¸³¾ ¼ö ÀÖÀ¸¸ç, ±¸µ¶ÇÑ ¸ðµç ÀåÄ¡´Â À̸¦ ¼ö½ÅÇÕ´Ï´Ù. ¿äû ¿¹½Ã: json ÄÚµå º¹»ç { "message": { "topic": "your-topic-name", "notification": { "title": "Title", "body": "Body text" } }} ÅäÅ«¿¡ ´ëÇÑ ·çÇÁ: ÁÖÁ¦¸¦ »ç¿ëÇÏ´Â °ÍÀÌ ±ÍÇÏÀÇ »ç¿ë »ç·Ê¿¡ ÀûÇÕÇÏÁö ¾ÊÀº °æ¿ì °¢ ÀåÄ¡ ÅäÅ«À» ¹Ýº¹ÇÏ¿© °³º° ¸Þ½ÃÁö¸¦ º¸³»¾ß ÇÕ´Ï´Ù. ÇÁ·Î¼¼½º ÀÚµ¿È­: ½ºÅ©¸³Æ®¸¦ ÀÛ¼ºÇϰųª ¼­¹ö Ãø Äڵ带 »ç¿ëÇÏ¿© °¢ ÅäÅ«¿¡ ´ëÇÑ ¸Þ½ÃÁö Àü¼ÛÀ» ÀÚµ¿È­ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿¹Á¦ ÀÇ»ç ÄÚµå: python ÄÚµå º¹»ç for token in device_tokens: send_message_to_token(token, message_payload) ¹èÄ¡ API »ç¿ë: FCM HTTP v1 API´Â HTTP/1.1 »ç¾ç¿¡ µû¶ó HTTP Àϰý 󸮸¦ »ç¿ëÇÏ¿© Àϰý ¿äûÀ» Áö¿øÇÕ´Ï´Ù. ¿©·¯ ¿äû Àϰý ó¸®: ¿©·¯ Àü¼Û ¿äûÀ» ´ÜÀÏ HTTP ¿äûÀ¸·Î Àϰý ó¸®ÇÒ ¼ö ÀÖÀ¸¸ç ÀÌ´Â °³º° ¿äûÀ» º¸³»´Â °Íº¸´Ù ´õ È¿À²ÀûÀÏ ¼ö ÀÖ½À´Ï´Ù. °í·Á»çÇ×: ÀÌ ¹æ¹ýÀ» »ç¿ëÇÏ·Á¸é ¿©·¯ ºÎºÐÀ¸·Î ±¸¼ºµÈ MIME ¿äûÀ» ±¸¼ºÇØ¾ß Çϸç ÀÌ´Â ´õ º¹ÀâÇÒ ¼ö ÀÖ½À´Ï´Ù. Firebase Admin SDK(¼­¹ö ȯ°æ¿¡ ±ÇÀå): Firebase Admin SDK¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Â ¼­¹ö ȯ°æ¿¡ Á¢¼ÓÇÑ °æ¿ì sendMulticast() ¸Þ¼Òµå¸¦ Ȱ¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿©·¯ ÅäÅ«À¸·Î º¸³»±â: ÀÌ ¹æ¹ýÀ» »ç¿ëÇÏ¸é ´ÜÀÏ ÇÔ¼ö È£Ãâ·Î ÃÖ´ë 500°³ÀÇ ÀåÄ¡ ÅäÅ«¿¡ ¸Þ½ÃÁö¸¦ º¸³¾ ¼ö ÀÖ½À´Ï´Ù. ¿¹(Node.js): javascript ÄÚµå º¹»ç const message = { notification: { title: 'Title', body: 'Body text' }, tokens: deviceTokens }; admin.messaging().sendMulticast(message) .then((response) => { console.log(response.successCount + ' messages were sent successfully'); }); ¿ä¾à: ÁÖÁ¦: °¡´ÉÇÏ´Ù¸é °è¼ÓÇØ¼­ ÁÖÁ¦¸¦ »ç¿ëÇϼ¼¿ä. È¿À²ÀûÀ̰í È®Àå °¡´ÉÇÕ´Ï´Ù. ·çÇÎ ÅäÅ«: ÁÖÁ¦¸¦ ¼±ÅÃÇÒ ¼ö ¾ø´Â °æ¿ì HTTP v1 API¸¦ Á÷Á¢ »ç¿ëÇÒ ¶§ ÅäÅ«¿¡ ´ëÇÑ ·çÇÎÀÌ ÇÊ¿äÇÕ´Ï´Ù. Àϰý API: Àϰý API¸¦ »ç¿ëÇÏ¿© ¿©·¯ ¿äûÀ» Çϳª·Î °áÇÕÇÕ´Ï´Ù. Admin SDK: ´õ¿í È¿À²ÀûÀÎ Á¢±Ù ¹æ½ÄÀ» ¿øÇϽøé Firebase Admin SDKÀÇ ¸ÖƼij½ºÆ® ¸Þ½Ã¡ ±â´ÉÀ» »ç¿ëÇϼ¼¿ä. Ãß°¡ ÆÁ: ¿À·ù ó¸®: ÅäÅ«À» ¹Ýº¹Çϰųª Admin SDK¸¦ »ç¿ëÇÒ ¶§ ¿À·ù 󸮸¦ ±¸ÇöÇÏ¿© À߸øµÈ ÅäÅ«À̳ª ½ÇÆÐ¸¦ °ü¸®Çϼ¼¿ä. ¼º´É °í·Á »çÇ×: °³º° ¿äûÀ» º¸³»´Â °ÍÀº ¸®¼Ò½º Áý¾àÀûÀÏ ¼ö ÀÖ½À´Ï´Ù. ÅäÅ« ¼ö°¡ ¸¹Àº °æ¿ì Àϰý ó¸® ¶Ç´Â ÁÖÁ¦ »ç¿ë°ú °°Àº Àü·«À» °í·ÁÇϽʽÿÀ. º¸¾È ¹× ¾×¼¼½º ÅäÅ«: ¼­¹ö ȯ°æÀÌ FCM ÀÎÁõ¿¡ ÇÊ¿äÇÑ ¾×¼¼½º ÅäÅ«À» ¾ÈÀüÇÏ°Ô °ü¸®ÇÏ´ÂÁö È®ÀÎÇϼ¼¿ä. Âü°íÀÚ·á: ¿©·¯ ÀåÄ¡¿¡ ¸Þ½ÃÁö º¸³»±â | Á߯÷ ±âÁö Firebase Admin SDK ¹®¼­ FCM HTTP v1 API ÂüÁ¶ ¿¹. ¼­¹ö Ãø¿¡¼­ FCM(Firebase Cloud Messaging) HTTP v1 API¸¦ »ç¿ëÇÏ´Â °æ¿ì¿¡µµ Ŭ¶óÀÌ¾ðÆ® Ãø(ÈÞ´ëÆù)¿¡¼­ ÁÖÁ¦¸¦ ÁöÁ¤ÇÏ°í °ü¸®ÇÏ´Â ¹æ¹ýÀº ÀÌÀü°ú µ¿ÀÏÇÕ´Ï´Ù. Android ¹× iOS¿ë Ŭ¶óÀÌ¾ðÆ® Ãø SDK´Â ÁÖÁ¦ ±¸µ¶ ¹æ¹ýÀ» º¯°æÇÏÁö ¾Ê¾ÒÀ¸¹Ç·Î °è¼ÓÇØ¼­ µ¿ÀÏÇÑ Äڵ带 »ç¿ëÇÏ¿© ¾Û¿¡¼­ ÁÖÁ¦¸¦ ±¸µ¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. Ŭ¶óÀ̾ðÆ®Ãø ÁÖÁ¦ ±¸µ¶: ±â°èÀû ÀÎÁ¶ Àΰ£: java ÄÚµå º¹»ç FirebaseMessaging.getInstance().subscribeToTopic("your-topic-name") .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { // Successfully subscribed to topic } else { // Failed to subscribe to topic } } }); iOS(½ºÀ§ÇÁÆ®): swift ÄÚµå º¹»ç Messaging.messaging().subscribe(toTopic: "your-topic-name") { error in if let error = error { print("Failed to subscribe to topic: \(error.localizedDescription)") } else { print("Successfully subscribed to topic") } } ÇÙ½É »çÇ×: ÁÖÁ¦ À̸§: Ŭ¶óÀÌ¾ðÆ® ¾Û¿¡ »ç¿ëµÈ ÁÖÁ¦ À̸§ÀÌ ¼­¹ö ¿äû¿¡ ÁöÁ¤µÈ À̸§°ú Á¤È®È÷ ÀÏÄ¡ÇÏ´ÂÁö È®ÀÎÇϼ¼¿ä. ÁÖÁ¦ À̸§Àº URL ¾ÈÀüÇØ¾ß ÇÕ´Ï´Ù. Áï, °ø¹éÀ̳ª Ư¼ö ¹®ÀÚ¸¦ Æ÷ÇÔÇÒ ¼ö ¾ø½À´Ï´Ù. ÇÊ¿äÇÑ °æ¿ì ÁÖÁ¦ À̸§À» URL·Î ÀÎÄÚµùÇÒ ¼ö ÀÖ½À´Ï´Ù. ±¸µ¶ È®ÀÎ: ±¸µ¶ÀÌ ¼º°øÇß´ÂÁö È®ÀÎÇÏ°í ¿À·ù¸¦ ÀûÀýÇÏ°Ô Ã³¸®Çϱâ À§ÇØ ¿Ï·á ¸®½º³Ê ¶Ç´Â ÄݹéÀ» ó¸®ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. º¯°æµÇÁö ¾ÊÀº SDK ¹æ¹ý: ±¸µ¶(subscribeToTopic) ¹× ±¸µ¶ Ãë¼Ò(unsubscribeFromTopic) ¹æ¹ýÀº º¯°æµÇÁö ¾Ê¾Ò½À´Ï´Ù. »ç¿ë ÁßÀÎ ¼­¹ö Ãø API ¹öÀü°ú µ¶¸³ÀûÀ¸·Î ÀÛµ¿ÇÕ´Ï´Ù. ¼­¹öÃø ¸Þ½ÃÁö Àü¼Û: ¼­¹ö Ãø¿¡¼­´Â HTTP v1 API¸¦ »ç¿ëÇÏ¿© ÁÖÁ¦¿¡ ¸Þ½ÃÁö¸¦ º¸³¾ ¶§ ´ÙÀ½°ú °°ÀÌ ¸Þ½ÃÁö ÆäÀ̷ε忡 ÁÖÁ¦¸¦ ÁöÁ¤ÇÕ´Ï´Ù. json ÄÚµå º¹»ç { "message": { "topic": "your-topic-name", "notification": { "title": "Title", "body": "Body text" } }} Âü°í: Àϰü¼º: Ŭ¶óÀÌ¾ðÆ® ±¸µ¶°ú ¼­¹ö ¸Þ½ÃÁö ÆäÀÌ·Îµå °£¿¡ ÁÖÁ¦ À̸§ÀÌ ÀÏÄ¡ÇÏ´ÂÁö È®ÀÎÇϼ¼¿ä. ÀÎÁõ: HTTP v1 API¸¦ »ç¿ëÇÒ ¶§ ÀûÀýÇÑ ¹üÀ§ÀÇ OAuth 2.0À» »ç¿ëÇÏ¿© ¼­¹ö ¿äûÀÌ ¿Ã¹Ù¸£°Ô ÀÎÁõµÇ¾ú´ÂÁö È®ÀÎÇϼ¼¿ä. ·¹°Å½Ã Áö¿ø: ÁÖÁ¦¿¡ ¸Þ½ÃÁö¸¦ º¸³»±â À§ÇØ ·¹°Å½Ã API¸¦ »ç¿ëÇϰí ÀÖ¾ú´Ù¸é HTTP v1 API·Î ÀüȯÇÒ ¶§ ÁÖÁ¦ ±¸µ¶°ú °ü·ÃµÈ Ŭ¶óÀÌ¾ðÆ® Ãø º¯°æÀÌ ÇÊ¿äÇÏÁö ¾Ê½À´Ï´Ù. Âü°íÀÚ·á: Ŭ¶óÀÌ¾ðÆ® ¾Û¿¡¼­ ÁÖÁ¦ ±¸µ¶ | Firebase ¹®¼­ ÁÖÁ¦¿¡ ¸Þ½ÃÁö º¸³»±â | Firebase ¹®¼­ ¿ä¾à: Ŭ¶óÀÌ¾ðÆ® Ãø: µ¿ÀÏÇÑ Äڵ带 °è¼Ó »ç¿ëÇÏ¿© ¾ÛÀÇ ÁÖÁ¦¸¦ ±¸µ¶Çϼ¼¿ä. ¼­¹ö Ãø: HTTP v1 API¸¦ »ç¿ëÇÏ¿© »õ·Î¿î Çü½Ä¿¡ µû¶ó ÁÖÁ¦¿¡ ¸Þ½ÃÁö¸¦ º¸³À´Ï´Ù. º¯°æ ÇÊ¿ä ¾øÀ½: HTTP v1 API·Î À̵¿ÇÒ ¶§ ÁÖÁ¦ ±¸µ¶¿¡ ´ëÇÑ Å¬¶óÀÌ¾ðÆ® Ãø ¼öÁ¤ÀÌ ÇÊ¿äÇÏÁö ¾Ê½À´Ï´Ù. ÁÖÁ¦ ¸Þ½ÃÁö ±¸Çö¿¡ Ãß°¡ Áö¿øÀÌ ÇÊ¿äÇϰųª Ãß°¡ Áú¹®ÀÌ ÀÖ´Â °æ¿ì ¾ðÁ¦µçÁö ¹®ÀÇÇϼ¼¿ä! ==== Àεå·ÎÀÌµå ¾Û¿¡¼­ º¸³»±â 1. Android ½ºÆ©µð¿À¿¡¼­ ÇÁ·ÎÁ§Æ® ¸¸µé±â Android ½ºÆ©µð¿À¸¦ ¿±´Ï´Ù. »õ·Î¿î Android ÇÁ·ÎÁ§Æ®¸¦ »ý¼ºÇϰųª ±âÁ¸ ÇÁ·ÎÁ§Æ®¸¦ ¿±´Ï´Ù. 2. Çʼö Á¾¼Ó¼º Ãß°¡ app/build.gradle ÆÄÀÏ¿¡¼­ okhttp ¹× Firebase °ü·Ã ¶óÀ̺귯¸®¸¦ Æ÷ÇÔÇÏ·Á¸é ´ÙÀ½ Á¾¼Ó¼ºÀ» Ãß°¡Çϼ¼¿ä. dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.3' implementation 'com.google.firebase:firebase-messaging:23.0.0' // For Firebase Messaging } ¶ÇÇÑ ·çÆ® ¼öÁØ build.gradle¿¡ Google ¼­ºñ½º Ç÷¯±×ÀÎÀ» Àû¿ëÇß´ÂÁö È®ÀÎÇϼ¼¿ä. buildscript { dependencies { classpath 'com.google.gms:google-services:4.3.10' } } app/build.gradle ÆÄÀÏ ÇÏ´Ü¿¡¼­ Ç÷¯±×ÀÎÀ» Àû¿ëÇÕ´Ï´Ù. apply plugin: 'com.google.gms.google-services' 3. Google ¼­ºñ½º JSON ´Ù¿î·Îµå Firebase ÄַܼΠÀ̵¿ÇÕ´Ï´Ù. ÇÁ·ÎÁ§Æ®¸¦ ¼±ÅÃÇϰųª »õ ÇÁ·ÎÁ§Æ®¸¦ ¸¸µå¼¼¿ä. google-services.json ÆÄÀÏÀ» ´Ù¿î·ÎµåÇÏ¿© Android ÇÁ·ÎÁ§Æ®ÀÇ app/ µð·ºÅ丮¿¡ ¹èÄ¡Çϼ¼¿ä. 4. Java ÆÄÀÏ Ãß°¡ GoogleAuthTokenGenerator Ŭ·¡½º¸¦ Ãß°¡Çϼ¼¿ä: ÇÁ·ÎÁ§Æ®¿¡ »õ Java Ŭ·¡½º ÆÄÀÏÀ» ¸¸µé°í À̸§À» GoogleAuthTokenGenerator.java·Î ÁöÁ¤ÇÕ´Ï´Ù. ´ÙÀ½ Äڵ带 º¹»çÇÏ¿© ºÙ¿©³ÖÀ¸¼¼¿ä. import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.ServiceAccountCredentials; import java.io.FileInputStream; import java.io.IOException; public class GoogleAuthTokenGenerator { public static String getAccessToken() throws IOException { FileInputStream serviceAccountStream = new FileInputStream("path_to_your_service_account.json"); GoogleCredentials googleCredentials = ServiceAccountCredentials .fromStream(serviceAccountStream) .createScoped("https://www.googleapis.com/auth/firebase.messaging"); googleCredentials.refreshIfExpired(); AccessToken accessToken = googleCredentials.getAccessToken(); return accessToken.getTokenValue(); } } "path_to_your_service_account.json"À» ´Ù¿î·ÎµåÇÑ ¼­ºñ½º °èÁ¤ JSON ÆÄÀÏÀÇ ½ÇÁ¦ °æ·Î·Î ¹Ù²ã¾ß ÇÕ´Ï´Ù. path_to_your_service_account.json ÆÄÀÏÀº Firebase Äֿܼ¡¼­ ´Ù¿î·ÎµåÇØ¾ß ÇÏ´Â Firebase ¼­ºñ½º °èÁ¤ ŰÀÔ´Ï´Ù. À̸¦ ó¸®ÇÏ´Â ¹æ¹ýÀº ´ÙÀ½°ú °°½À´Ï´Ù. 1. ¼­ºñ½º °èÁ¤ Ű ´Ù¿î·Îµå ¼­ºñ½º °èÁ¤ JSON ÆÄÀÏÀ» °¡Á®¿À·Á¸é ´ÙÀ½ ¾È³»¸¦ µû¸£¼¼¿ä. Firebase ÄַܼΠÀ̵¿ÇÕ´Ï´Ù. ÇÁ·ÎÁ§Æ® ¼³Á¤À¸·Î À̵¿ÇÕ´Ï´Ù. ¼­ºñ½º °èÁ¤ ÅÇÀ» Ŭ¸¯ÇÕ´Ï´Ù. »õ °³ÀΠŰ »ý¼ºÀ» Ŭ¸¯ÇÏ¿© JSON ÆÄÀÏÀ» ´Ù¿î·ÎµåÇÕ´Ï´Ù. 2. JSON ÆÄÀÏÀ» ÀúÀåÇÒ À§Ä¡ ÀÌ service_account.json ÆÄÀÏÀ» Android ÇÁ·ÎÁ§Æ® µð·ºÅ͸®³ª Äڵ尡 ¾×¼¼½ºÇÒ ¼ö ÀÖ´Â À§Ä¡¿¡ ¹èÄ¡ÇØ¾ß ÇÕ´Ï´Ù. ÀϹÝÀûÀÎ À§Ä¡´Â ÇÁ·ÎÁ§Æ®ÀÇ assets ¶Ç´Â res/raw Æú´õ ³»¿¡ ÀÖ½À´Ï´Ù. ¿É¼Ç 1: assets/¿¡ ¹èÄ¡ src/main/ ¾È¿¡ assets µð·ºÅ丮¸¦ »ý¼ºÇÕ´Ï´Ù(¾ÆÁ÷ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì). °Å±â¿¡ service_account.json ÆÄÀÏÀ» ¹èÄ¡ÇÕ´Ï´Ù. app/src/main/assets/service_account.json ¿É¼Ç 2: res/raw/¿¡ ¹èÄ¡ res/ ¾È¿¡ raw µð·ºÅ丮¸¦ »ý¼ºÇÕ´Ï´Ù(¾ÆÁ÷ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì). °Å±â¿¡ service_account.json ÆÄÀÏÀ» ¹èÄ¡ÇÕ´Ï´Ù. app/src/main/res/raw/service_account.json 3. ÄÚµåÀÇ ÆÄÀÏ °æ·Î ¾÷µ¥ÀÌÆ® ÆÄÀÏÀ» assets¿¡ ¹èÄ¡ÇÏ´Â °æ¿ì ´ÙÀ½°ú °°ÀÌ °æ·Î¸¦ ¾÷µ¥ÀÌÆ®ÇÒ ¼ö ÀÖ½À´Ï´Ù. FileInputStream serviceAccountStream = new FileInputStream(getAssets().open("service_account.json")); ÆÄÀÏÀ» res/raw¿¡ ¹èÄ¡Çϸé ÄÚµå´Â ´ÙÀ½°ú °°ÀÌ ¾÷µ¥ÀÌÆ®µÉ ¼ö ÀÖ½À´Ï´Ù. InputStream serviceAccountStream = getResources().openRawResource(R.raw.service_account); ==== ÆÄÀÏ ´ë½Å¿¡ ¾ÈÀÇ ³»¿ë »ç¿ë ÆÄÀÏ ½Ã½ºÅÛ¿¡¼­ ¼­ºñ½º °èÁ¤ JSON ÆÄÀÏÀ» ·ÎµåÇÏÁö ¾Ê°í ÄÚµå ³»¿¡¼­ Á÷Á¢ ÄÜÅÙÃ÷¸¦ »ç¿ëÇÏ·Á´Â °æ¿ì JSON ¹®ÀÚ¿­À» Äڵ忡 »ðÀÔÇÒ ¼ö ÀÖ½À´Ï´Ù. À̸¦ ó¸®ÇÏ´Â ¹æ¹ýÀº ´ÙÀ½°ú °°½À´Ï´Ù. 1. JSON ÆÄÀÏ ÄÜÅÙÃ÷ º¹»ç ¸ÕÀú Firebase Äֿܼ¡¼­ ´Ù¿î·ÎµåÇÑ service_account.json ÆÄÀÏÀ» ¿±´Ï´Ù. ÆÄÀÏÀÇ Àüü ³»¿ëÀ» º¹»çÇÕ´Ï´Ù. 2. JSON ÄÜÅÙÃ÷¸¦ Äڵ忡 ¹®ÀÚ¿­·Î ÀúÀå JSON ÄÜÅÙÃ÷¸¦ ¹®ÀÚ¿­·Î ÀúÀåÇϰí Á÷Á¢ ±¸¹® ºÐ¼®ÇÒ ¼ö ÀÖ½À´Ï´Ù. À̸¦ ¼öÇàÇÏ´Â ¹æ¹ýÀÇ ¿¹´Â ´ÙÀ½°ú °°½À´Ï´Ù. // JSON content of the service account String jsonContent = "{\n" + " \"type\": \"service_account\",\n" + " \"project_id\": \"your_project_id\",\n" + " \"private_key_id\": \"your_private_key_id\",\n" + " \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----\\n\",\n" + " \"client_email\": \"your_service_account_email@your_project_id.iam.gserviceaccount.com\",\n" + " \"client_id\": \"your_client_id\",\n" + " \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n" + " \"token_uri\": \"https://oauth2.googleapis.com/token\",\n" + " \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n" + " \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/your_service_account_email\"\n" + "}"; // Convert the JSON string into an InputStream InputStream serviceAccountStream = new ByteArrayInputStream(jsonContent.getBytes(StandardCharsets.UTF_8)); FcmHttpV1Sender Ŭ·¡½º¸¦ Ãß°¡Çϼ¼¿ä: ÇÁ·ÎÁ§Æ®¿¡ ¶Ç ´Ù¸¥ Java Ŭ·¡½º ÆÄÀÏÀ» ¸¸µé°í À̸§À» FcmHttpV1Sender.java·Î ÁöÁ¤ÇÕ´Ï´Ù. ´ÙÀ½ Äڵ带 º¹»çÇÏ¿© ºÙ¿©³ÖÀ¸¼¼¿ä. import android.os.AsyncTask; import okhttp3.*; import org.json.JSONObject; import java.io.IOException; public class FcmHttpV1Sender { private static final String FCM_BASE_URL = "https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send"; private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); private String oauthToken; private OkHttpClient client = new OkHttpClient(); public FcmHttpV1Sender(String oauthToken) { this.oauthToken = oauthToken; } public void sendPushNotification(String token, String title, String body, String imageUrl) { new SendPushNotificationTask().execute(token, title, body, imageUrl); } private class SendPushNotificationTask extends AsyncTask { @Override protected Void doInBackground(String... params) { String token = params[0]; String title = params[1]; String body = params[2]; String imageUrl = params[3]; try { JSONObject notification = new JSONObject(); notification.put("title", title); notification.put("body", body); if (imageUrl != null && !imageUrl.isEmpty()) { notification.put("image", imageUrl); } JSONObject message = new JSONObject(); message.put("token", token); message.put("notification", notification); JSONObject payload = new JSONObject(); payload.put("message", message); RequestBody requestBody = RequestBody.create(JSON, payload.toString()); Request request = new Request.Builder() .url(FCM_BASE_URL) .post(requestBody) .addHeader("Authorization", "Bearer " + oauthToken) .addHeader("Content-Type", "application/json; UTF-8") .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println("Notification sent successfully."); } else { System.out.println("Failed to send notification: " + response.body().string()); } } catch (Exception e) { e.printStackTrace(); } return null; } } } "YOUR_PROJECT_ID"¸¦ Firebase ÇÁ·ÎÁ§Æ® ID·Î ¹Ù²ß´Ï´Ù. 5. ÁÖ¿ä Ȱµ¿ ¿¹½Ã MainActivity.java¿¡ Ǫ½Ã ¾Ë¸²À» º¸³»´Â ·ÎÁ÷À» Ãß°¡Çϼ¼¿ä. java ÄÚµå º¹»ç import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import com.google.firebase.messaging.FirebaseMessaging; import java.io.IOException; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Firebase Messaging Service to get the device token FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> { if (task.isSuccessful()) { String token = task.getResult(); try { // Get the OAuth token String oauthToken = GoogleAuthTokenGenerator.getAccessToken(); // Send a push notification with the device FCM token FcmHttpV1Sender sender = new FcmHttpV1Sender(oauthToken); sender.sendPushNotification(token, "Hello", "This is a test push notification", "https://example.com/image.jpg"); } catch (IOException e) { e.printStackTrace(); } } }); } } 6. ÄÄÆÄÀÏ ¹× ½ÇÇà Android Studio¿¡¼­ ÇÁ·ÎÁ§Æ®¸¦ ½ÇÇàÇÕ´Ï´Ù. Ǫ½Ã ¾Ë¸²À» ¹ÞÀ¸·Á¸é ±â±â¿¡ Ȱ¼º FCM ÅäÅ«ÀÌ ÀÖ´ÂÁö È®ÀÎÇϼ¼¿ä. ÀÌ ¼³Á¤À» »ç¿ëÇϸé Android ¾Û¿¡¼­ Á÷Á¢ À̹ÌÁö¿Í ÇÔ²² HTTP v1 Ǫ½Ã ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. ÇÁ·Î´ö¼Ç ¿ëµµÀÇ °æ¿ì Android Ŭ¶óÀÌ¾ðÆ® ´ë½Å º¸¾È ¹é¿£µå ¼­¹ö¿¡¼­ Ǫ½Ã ¾Ë¸²À» ó¸®ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. À§ Äڵ忡¼­ FCM ÅäÅ«À» »ç¿ëÇÏ¿© ƯÁ¤ ±â±â·Î Ǫ½Ã ¾Ë¸²À» º¸³»°í ÀÖ½À´Ï´Ù. ÇÏÁö¸¸ Àüü Ǫ½Ã ¾Ë¸²À» º¸³»°í ½Í´Ù¸é, ƯÁ¤ ÅäÅ«ÀÌ ¾Æ´Ñ ±¸µ¶µÈ **ÅäÇÈ(Topic)**À» »ç¿ëÇÏ¿© Ǫ½Ã ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. Firebase Cloud Messaging(FCM)Àº ÅäÇÈ ±â¹Ý ¸Þ½Ã¡À» Áö¿øÇϸç, ¿©·¯ ±â±â¸¦ ƯÁ¤ ÁÖÁ¦(ÅäÇÈ)¿¡ ±¸µ¶ÇÏ°Ô ÇÑ ÈÄ ±× ÅäÇÈ¿¡ ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¾î, ¸ðµç ±â±â°¡ "global"À̶ó´Â ÅäÇÈÀ» ±¸µ¶Çϰí ÀÖ´Ù¸é, "global" ÅäÇÈ¿¡ Ǫ½Ã ¾Ë¸²À» º¸³»¸é ¸ðµç ±¸µ¶µÈ ±â±â°¡ ¾Ë¸²À» ¼ö½ÅÇÒ ¼ö ÀÖ½À´Ï´Ù. 1. ÅäÇÈ ±â¹Ý Ǫ½Ã ¾Ë¸²À» º¸³»´Â ¹æ¹ý Àüü ±â±â·Î Ǫ½Ã ¾Ë¸²À» º¸³»·Á¸é ÅäÇÈÀ» »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. FCM¿¡¼­´Â ±â±â°¡ ƯÁ¤ ÅäÇÈ¿¡ °¡ÀÔÇϰí, ±× ÅäÇÈÀ» ´ë»óÀ¸·Î ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. À̸¦ À§Çؼ­´Â Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ÅäÇÈÀ» ±¸µ¶ÇÏ°Ô Çϰí, ¼­¹ö¿¡¼­ ÇØ´ç ÅäÇÈ¿¡ ¸Þ½ÃÁö¸¦ º¸³»¾ß ÇÕ´Ï´Ù. 1.1. Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ÅäÇÈ ±¸µ¶ Firebase Ŭ¶óÀÌ¾ðÆ® SDK¸¦ »ç¿ëÇÏ¿© Android ¾Û¿¡¼­ ƯÁ¤ ÅäÇÈÀ» ±¸µ¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¾î, ¸ðµç »ç¿ëÀÚ°¡ "global"À̶ó´Â ÅäÇÈÀ» ±¸µ¶Çϵµ·Ï ¼³Á¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. FirebaseMessaging.getInstance().subscribeToTopic("global") .addOnCompleteListener(task -> { if (task.isSuccessful()) { System.out.println("Subscribed to global topic"); } else { System.out.println("Failed to subscribe to global topic"); } }); ÅäÇÈ ±¸µ¶: FirebaseMessaging.getInstance().subscribeToTopic("global")À» »ç¿ëÇÏ¿© ¸ðµç Ŭ¶óÀÌ¾ðÆ®°¡ globalÀ̶ó´Â ÅäÇÈ¿¡ ±¸µ¶Çϵµ·Ï ¼³Á¤ÇÕ´Ï´Ù. ÅäÇÈ ´ë»ó ¾Ë¸²: ±âÁ¸¿¡ ƯÁ¤ ÅäÅ«À» ´ë»óÀ¸·Î ¸Þ½ÃÁö¸¦ º¸³»´Â ´ë½Å, topic Çʵ带 »ç¿ëÇÏ¿© "global"°ú °°Àº ÅäÇÈ¿¡ ¸Þ½ÃÁö¸¦ º¸³À´Ï´Ù. À̸¦ ÅëÇØ ÇØ´ç ÅäÇÈ¿¡ ±¸µ¶µÈ ¸ðµç ±â±â·Î Ǫ½Ã ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. sendPushNotificationToTopic ¸Þ¼­µå¸¦ È£ÃâÇÏ¿© Àüü »ç¿ëÀÚ¿¡°Ô Ǫ½Ã ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. import android.os.AsyncTask; import okhttp3.*; import org.json.JSONObject; import java.io.IOException; public class FcmHttpV1Sender { private static final String FCM_BASE_URL = "https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send"; private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); private String oauthToken; private OkHttpClient client = new OkHttpClient(); public FcmHttpV1Sender(String oauthToken) { this.oauthToken = oauthToken; } // Àüü ±â±â¿¡ Ǫ½Ã¸¦ º¸³»±â À§ÇØ ÅäÇÈÀ» »ç¿ëÇÔ public void sendPushNotificationToTopic(String topic, String title, String body, String imageUrl) { new SendPushNotificationTask().execute(topic, title, body, imageUrl); } private class SendPushNotificationTask extends AsyncTask { @Override protected Void doInBackground(String... params) { String topic = params[0]; // ÅäÇÈ À̸§ (¿¹: "global") String title = params[1]; String body = params[2]; String imageUrl = params[3]; try { // ¾Ë¸² Á¤º¸ ±¸¼º JSONObject notification = new JSONObject(); notification.put("title", title); notification.put("body", body); if (imageUrl != null && !imageUrl.isEmpty()) { notification.put("image", imageUrl); // À̹ÌÁö URL Ãß°¡ } // ¸Þ½ÃÁö Á¤º¸ ±¸¼º (ÅäÇÈ »ç¿ë) JSONObject message = new JSONObject(); message.put("topic", topic); // ƯÁ¤ ÅäÇÈÀ» ´ë»óÀ¸·Î ¼³Á¤ message.put("notification", notification); // ÃÖÁ¾ ÆäÀÌ·Îµå ±¸¼º JSONObject payload = new JSONObject(); payload.put("message", message); // HTTP ¿äû ±¸¼º RequestBody requestBody = RequestBody.create(JSON, payload.toString()); Request request = new Request.Builder() .url(FCM_BASE_URL) .post(requestBody) .addHeader("Authorization", "Bearer " + oauthToken) // OAuth ÅäÅ« »ç¿ë .addHeader("Content-Type", "application/json; UTF-8") .build(); // ¿äû ½ÇÇà Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println("Notification sent successfully to topic."); } else { System.out.println("Failed to send notification: " + response.body().string()); } } catch (Exception e) { e.printStackTrace(); } return null; } } } È£Ãâ ¿¹½Ã sendPushNotificationToTopic ¸Þ¼­µå¸¦ È£ÃâÇÏ¿© Àüü »ç¿ëÀÚ¿¡°Ô Ǫ½Ã ¾Ë¸²À» º¸³¾ ¼ö ÀÖ½À´Ï´Ù. // OAuth ÅäÅ« »ý¼º String oauthToken = GoogleAuthTokenGenerator.getAccessToken(); // FCM "global" ÅäÇÈÀ» ±¸µ¶ÇÑ ¸ðµç »ç¿ëÀÚ¿¡°Ô ¾Ë¸² Àü¼Û String topic = "global"; // Àüü ±â±âµéÀÌ ±¸µ¶ÇÑ ÅäÇÈ String title = "Global Notification"; String body = "This is a message for all users."; String imageUrl = "https://example.com/path/to/image.jpg"; FcmHttpV1Sender sender = new FcmHttpV1Sender(oauthToken); sender.sendPushNotificationToTopic(topic, title, body, imageUrl); ÀÌ·¸°Ô Çϸé "global" ÅäÇÈÀ» ±¸µ¶ÇÑ ¸ðµç »ç¿ëÀÚ¿¡°Ô Ǫ½Ã ¾Ë¸²ÀÌ Àü¼ÛµË´Ï´Ù. ÁÖÀÇ»çÇ× ÅäÇÈ Çѵµ: ÇÑ ±â±â´Â ÃÖ´ë 2000°³ÀÇ ÅäÇÈ¿¡ ±¸µ¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. º¸¾È: ÀÌ ¹æ½ÄÀº ¾Ë¸²À» Àüü ±â±â·Î º¸³»±â À§ÇÑ °£´ÜÇÑ ¹æ¹ýÀÌÁö¸¸, ½Ç½Ã°£À¸·Î »ç¿ëÀÚ ±×·ìÀ» ¼¼ºÐÈ­ÇÏ°í ½Í´Ù¸é ÁÖÀÇÇØ¾ß ÇÕ´Ï´Ù. ¹é¿£µå ÅëÇÕ: ½ÇÁ¦ ¿î¿µ ȯ°æ¿¡¼­´Â ÀÌ·¯ÇÑ ¾Ë¸² Àü¼Û ·ÎÁ÷À» Ŭ¶óÀÌ¾ðÆ®°¡ ¾Æ´Ñ ¼­¹ö¿¡¼­ ó¸®ÇÏ´Â °ÍÀÌ º¸¾È»ó ´õ ¾ÈÀüÇÕ´Ï´Ù. === ÅäÇÈÀ¸·Î ±¸ºÐ ¹æ¹ý ¿¹, ÁÖÁ¦º°·Î FCM(Firebase Cloud Messaging) ¾Ë¸²À» ¼ö½ÅÇÒ ¶§ Ŭ¶óÀÌ¾ðÆ®´Â ±â±â°¡ ±¸µ¶ÇÏ´Â ÁÖÁ¦¿¡ µû¶ó ÀÌ·¯ÇÑ ¾Ë¸²À» º°µµ·Î ¼ö½ÅÇϰí ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù. À̸¦ ±¸ÇöÇÏ´Â ¹æ¹ýÀº ´ÙÀ½°ú °°½À´Ï´Ù. 1. Android Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ÁÖÁ¦¸¦ ±¸µ¶Çϼ¼¿ä. ±â±â´Â FirebaseÀÇ Å¬¶óÀÌ¾ðÆ® Ãø API¸¦ »ç¿ëÇÏ¿© Çϳª ÀÌ»óÀÇ ÁÖÁ¦¸¦ ±¸µ¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¾î ÀåÄ¡´Â "½ºÆ÷Ã÷" ÁÖÁ¦¿Í "´º½º" ÁÖÁ¦¸¦ º°µµ·Î ±¸µ¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. FirebaseMessaging.getInstance().subscribeToTopic("sports") .addOnCompleteListener(task -> { if (task.isSuccessful()) { System.out.println("Subscribed to sports topic"); } else { System.out.println("Failed to subscribe to sports topic"); } }); FirebaseMessaging.getInstance().subscribeToTopic("news") .addOnCompleteListener(task -> { if (task.isSuccessful()) { System.out.println("Subscribed to news topic"); } else { System.out.println("Failed to subscribe to news topic"); } }); 2. ÁÖÁ¦¿¡ µû¶ó FCM ¸Þ½ÃÁö ó¸® »ç¿ëÀÚ Á¤ÀÇ ÀåÄ¡°¡ FCM ¸Þ½ÃÁö¸¦ ¼ö½ÅÇÏ¸é ¸Þ½ÃÁö ³»¿ëÀ» °Ë»çÇÏ¿© ¸Þ½ÃÁö°¡ ¾î¶² ÁÖÁ¦·Î Àü¼ÛµÇ¾ú´ÂÁö È®ÀÎÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ´Â ÀϹÝÀûÀ¸·Î ¸Þ½ÃÁö°¡ 󸮵Ǵ FirebaseMessagingService Ŭ·¡½º¿¡¼­ ¼öÇàµË´Ï´Ù. ÁÖÁ¦¿¡ µû¶ó ¾Ë¸²À» ´Ù¸£°Ô ó¸®ÇÏ·Á¸é 'FirebaseMessagingService'¸¦ »ý¼ºÇϰųª ¼öÁ¤Çϼ¼¿ä. public class MyFirebaseMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { // Check if the message contains a data payload if (remoteMessage.getData().size() > 0) { handleDataMessage(remoteMessage); } // Check if the message contains a notification payload if (remoteMessage.getNotification() != null) { handleNotificationMessage(remoteMessage); } } // Method to handle notification message (displayed when app is in the background) private void handleNotificationMessage(RemoteMessage remoteMessage) { String title = remoteMessage.getNotification().getTitle(); String body = remoteMessage.getNotification().getBody(); // Here you can check the title, body or any other custom data to see which topic it relates to. // For example, if the notification is for a "sports" topic: if ("sports".equals(remoteMessage.getFrom())) { // Handle sports topic notification System.out.println("Received a sports notification: " + title + ", " + body); } else if ("news".equals(remoteMessage.getFrom())) { // Handle news topic notification System.out.println("Received a news notification: " + title + ", " + body); } // Display the notification or take action based on topic // Show the notification in your app¡¯s preferred style } // Method to handle data messages (sent when app is in the foreground) private void handleDataMessage(RemoteMessage remoteMessage) { Map data = remoteMessage.getData(); String topic = data.get("topic"); // Custom key-value pair to identify the topic if ("sports".equals(topic)) { // Handle sports topic data System.out.println("Received a sports data message: " + data.toString()); } else if ("news".equals(topic)) { // Handle news topic data System.out.println("Received a news data message: " + data.toString()); } // Process the data or display the message based on the topic } } 3. ´Ù¾çÇÑ ÁÖÁ¦¿¡ ´ëÇÑ ¾Ë¸² ó¸® ¾Ë¸² ÆäÀ̷εå: ¸Þ½ÃÁö¿¡ ¾Ë¸² ÆäÀ̷ε尡 Æ÷ÇÔµÈ °æ¿ì ¾ÛÀÌ ¹é±×¶ó¿îµå¿¡ ÀÖÀ» ¶§ ½Ã½ºÅÛ¿¡ Ç¥½ÃµË´Ï´Ù. À§ Äڵ忡¼­´Â remoteMessage.getFrom()À» È®ÀÎÇÏ¿© ƯÁ¤ ÁÖÁ¦¿¡¼­ ³ª¿Â °ÍÀÎÁö È®ÀÎÇÕ´Ï´Ù. µ¥ÀÌÅÍ ÆäÀ̷εå: µ¥ÀÌÅÍ ÆäÀ̷ε尡 Æ÷ÇÔµÈ ¸Þ½ÃÁö¸¦ º¸³»´Â °æ¿ì ¸Þ½ÃÁö¿¡ "topic": "sports"¿Í °°Àº »ç¿ëÀÚ Á¤ÀÇ Å°¸¦ Æ÷ÇÔÇϰí ÀÌ¿¡ µû¶ó onMessageReceived¿¡¼­ ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù. () ¹æ¹ý. 4. ÁÖÁ¦ ¸Þ½ÃÁö Àü¼Û ¿¹½Ã ¹é¿£µå(¶Ç´Â Firebase ÄܼÖ)¿¡¼­ ÁÖÁ¦·Î ¸Þ½ÃÁö¸¦ º¸³¾ ¶§ ´ÙÀ½°ú °°ÀÌ ±¸¼ºÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ´Â ¾ÛÀÌ ¸Þ½ÃÁö¸¦ ¼ö½ÅÇÒ ¶§ ¸Þ½ÃÁö°¡ ¾î¶² ÁÖÁ¦¿¡ °üÇÑ °ÍÀÎÁö ½Äº°ÇÏ´Â µ¥ µµ¿òÀÌ µË´Ï´Ù. ¿¹: '½ºÆ÷Ã÷' ÁÖÁ¦¿¡ ´ëÇÑ JSON ÆäÀ̷εå: { "message": { "topic": "sports", "notification": { "title": "Sports Update", "body": "Your favorite team just scored!" }, "data": { "topic": "sports" } }} ¿¹: '´º½º' ÁÖÁ¦¿¡ ´ëÇÑ JSON ÆäÀ̷εå: { "message": { "topic": "news", "notification": { "title": "Breaking News", "body": "Here's the latest news update." }, "data": { "topic": "news" } }} 5. Ŭ¶óÀÌ¾ðÆ® Ãø¿¡¼­ ÁÖÁ¦¸¦ ±¸º°ÇÏ´Â ¹æ¹ý ¸Þ½ÃÁö°¡ Ŭ¶óÀÌ¾ðÆ®¿¡ µµÂøÇϸé: ¾Ë¸² ¸Þ½ÃÁöÀÇ °æ¿ì remoteMessage.getFrom()À» »ç¿ëÇÏ¿© ÁÖÁ¦¸¦ ½Äº°Çϼ¼¿ä. °ªÀº "/topics/sports" ¶Ç´Â "/topics/news"¿Í °°½À´Ï´Ù. µ¥ÀÌÅÍ ¸Þ½ÃÁöÀÇ °æ¿ì À§ÀÇ ¿¹¿Í °°ÀÌ data ÆäÀ̷ε忡 topic Çʵ带 Æ÷ÇÔ½ÃŲ ´ÙÀ½ remoteMessage.getData().get("topic")À» »ç¿ëÇÏ¿© °Ë»öÇÕ´Ï´Ù. °á·Ð ±â±â°¡ ±¸µ¶ÇÏ´Â ÁÖÁ¦¿¡ µû¶ó ¸Þ½ÃÁö¸¦ ´Ù¸£°Ô ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀåÄ¡¸¦ ¿©·¯ ÁÖÁ¦¿¡ ±¸µ¶ÇÕ´Ï´Ù. 'FirebaseMessagingService'¿¡¼­ ¸Þ½ÃÁö ÆäÀ̷ε带 °Ë»çÇÏ¿© ¸Þ½ÃÁö°¡ ¾î¶² ÁÖÁ¦¿¡ °üÇÑ °ÍÀÎÁö È®ÀÎÇÕ´Ï´Ù. ÁÖÁ¦¿¡ µû¶ó ÀûÀýÇÑ Á¶Ä¡¸¦ ÃëÇϰųª ¾Ë¸²À» Ç¥½ÃÇÕ´Ï´Ù. À̸¦ ÅëÇØ ÁÖÁ¦¸¦ ±¸µ¶ÇÏ´Â ¸ðµç ÀåÄ¡¿¡ ¾Ë¸²À» º¸³¾ ¼ö ÀÖÁö¸¸ Android ¾ÛÀÇ ÁÖÁ¦¿¡ µû¶ó ƯÁ¤ ¹æ½ÄÀ¸·Î ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù. ================================================ Volley overview Volley is an HTTP library that makes networking for Android apps easier and most importantly, faster. Volley is available on GitHub. https://google.github.io/volley/simple.html FCM-Snippet-master Firebase Admin SDK ¼±Åà ÈÄ »õ ºñ°ø°³ Ű »ý¼º: Firebase Admin SDK¸¦ ¼±ÅÃÇÑ ÈÄ "»õ ºñ°ø°³ Ű »ý¼º(Generate new private key)"À» Ŭ¸¯ÇÕ´Ï´Ù. ´Ù¿î·ÎµåµÈ ÆÄÀÏÀ» service_account.jsonÀ¸·Î À̸§À» º¯°æÇÕ´Ï´Ù. ÀÌ ÆÄÀÏÀ» res/raw µð·ºÅ͸®¿¡ º¹»çÇÕ´Ï´Ù. MainActivity.java ÆÄÀÏ ¼öÁ¤: MainActivity.java ÆÄÀÏ¿¡¼­ getTokenForNotification ÇÔ¼ö¸¦ ã½À´Ï´Ù. ¾Ë¸²À» º¸³¾ ´ë»óÀÇ ÅäÅ«À¸·Î token °ªÀ» ±³Ã¼ÇÕ´Ï´Ù. Áß¿ä »çÇ×: ¸ðµâ ¼öÁØÀÇ build.gradle ÆÄÀÏ ¼öÁ¤: android { ... } ºí·Ï ¾È¿¡ ¾Æ·¡ ³»¿ëÀ» Ãß°¡ÇÕ´Ï´Ù. android { packagingOptions { exclude 'META-INF/DEPENDENCIES' } ... } ¾Æ·¡ ÀÇÁ¸¼ºµéÀ» Ãß°¡ÇÕ´Ï´Ù: implementation 'com.android.volley:volley:1.2.0' implementation 'com.google.auth:google-auth-library-oauth2-http:0.25.3' AllConstants¿¡¼­ ÇÁ·ÎÁ§Æ® ¾ÆÀ̵𸦠¹Ù²Ù¼¼¿ä package com.revolt.fcmtest.constants; public interface AllConstants { String CHANNEL_ID = "1000"; // httpv1-c0e4a ºÎºÐ¿¡ ÇÁ·ÎÁ§Æ® id ¸¦ ³ÖÀ¸¼¼¿ä String NOTIFICATION_URL = "https://fcm.googleapis.com/v1/projects/httpv1-c0e4a/messages:send" ; String MESSAGING_SCOPE = "https://www.googleapis.com/auth/firebase.messaging"; String[] SCOPES = { MESSAGING_SCOPE }; }