ตั้งค่าแอปไคลเอ็นต์ Firebase Cloud Messaging บน Android

ไคลเอ็นต์ FCM กำหนดให้มีอุปกรณ์ที่ใช้ Android 4.4 ขึ้นไปซึ่งมีแอป Google Play Store ติดตั้งอยู่ หรือใช้โปรแกรมจำลองที่ใช้ Android 4.4 ซึ่งมี Google APIs โปรดทราบว่าคุณไม่จำกัดเพียงแค่การทำให้แอป Android ใช้งานได้ผ่าน Google Play Store

ตั้งค่า SDK

ส่วนนี้จะครอบคลุมงานที่คุณอาจทำเสร็จแล้วหากได้เปิดใช้ฟีเจอร์ Firebase อื่นๆ สำหรับแอปแล้ว ให้เพิ่ม Firebase ลงในโปรเจ็กต์ Android หากยังไม่ได้ดำเนินการ

แก้ไขไฟล์ Manifest ของแอป

เพิ่มโค้ดต่อไปนี้ลงในไฟล์ Manifest ของแอป

  • บริการที่ขยาย FirebaseMessagingService คุณจำเป็นต้องดำเนินการนี้หากต้องการจัดการกับข้อความนอกเหนือจากการรับการแจ้งเตือนในแอปในเบื้องหลัง หากต้องการรับการแจ้งเตือนในแอปที่ทำงานอยู่เบื้องหน้า รับเพย์โหลดข้อมูล ส่งข้อความอัปสตรีม และอื่นๆ คุณต้องขยายบริการนี้
  • <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
  • (ไม่บังคับ) ภายในคอมโพเนนต์ของแอปพลิเคชัน มีองค์ประกอบข้อมูลเมตาเพื่อตั้งค่าไอคอนและสีการแจ้งเตือนเริ่มต้น Android ใช้ค่าเหล่านี้ทุกครั้งที่ข้อความขาเข้าไม่ได้ตั้งค่าไอคอนหรือสีไว้อย่างชัดแจ้ง
  • <!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
         See README(https://goo.gl/l4GJaQ) for more. -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_stat_ic_notification" />
    <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
         notification message. See README(https://goo.gl/6BKBk7) for more. -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />
  • (ไม่บังคับ) ตั้งแต่ Android 8.0 (API ระดับ 26) ขึ้นไป ระบบจะรองรับและแนะนำให้ใช้ ช่องทางการแจ้งเตือน FCM มีช่องทางการแจ้งเตือนเริ่มต้นที่มีการตั้งค่าพื้นฐาน หากต้องการ สร้างและใช้ช่องทางเริ่มต้นของคุณเอง ให้ตั้งค่า default_notification_channel_id เป็นรหัสของออบเจ็กต์ช่องทางการแจ้งเตือนตามที่แสดง โดย FCM จะใช้ค่านี้ทุกครั้งที่ข้อความขาเข้าไม่ได้ตั้งค่าช่องทางการแจ้งเตือนอย่างชัดเจน ดูข้อมูลเพิ่มเติมได้ใน จัดการช่องทางการแจ้งเตือน
  • <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id" />

ขอสิทธิ์การแจ้งเตือนรันไทม์ใน Android 13 ขึ้นไป

Android 13 เปิดตัวสิทธิ์รันไทม์แบบใหม่สำหรับแสดงการแจ้งเตือน ปัญหานี้ส่งผลกระทบต่อแอปทั้งหมดที่ทำงานบน Android 13 ขึ้นไปที่ใช้การแจ้งเตือน FCM

โดยค่าเริ่มต้น FCM SDK (เวอร์ชัน 23.0.6 ขึ้นไป) จะมีสิทธิ์ POST_NOTIFICATIONS ที่กำหนดไว้ในไฟล์ Manifest อย่างไรก็ตาม แอปของคุณจะต้องขอสิทธิ์นี้ในเวอร์ชันรันไทม์ผ่าน android.permission.POST_NOTIFICATIONS ค่าคงที่ด้วย แอปของคุณไม่ได้รับอนุญาตให้แสดงการแจ้งเตือนจนกว่า ผู้ใช้จะให้สิทธิ์นี้

วิธีขอสิทธิ์รันไทม์ใหม่

Kotlin+KTX

// Declare the launcher at the top of your Activity/Fragment:
private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
    if (isGranted) {
        // FCM SDK (and your app) can post notifications.
    } else {
        // TODO: Inform user that that your app will not show notifications.
    }
}

private fun askNotificationPermission() {
    // This is only necessary for API level >= 33 (TIRAMISU)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
            PackageManager.PERMISSION_GRANTED
        ) {
            // FCM SDK (and your app) can post notifications.
        } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
            // TODO: display an educational UI explaining to the user the features that will be enabled
            //       by them granting the POST_NOTIFICATION permission. This UI should provide the user
            //       "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
            //       If the user selects "No thanks," allow the user to continue without notifications.
        } else {
            // Directly ask for the permission
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }
}

Java

// Declare the launcher at the top of your Activity/Fragment:
private final ActivityResultLauncher<String> requestPermissionLauncher =
        registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
            if (isGranted) {
                // FCM SDK (and your app) can post notifications.
            } else {
                // TODO: Inform user that that your app will not show notifications.
            }
        });

private void askNotificationPermission() {
    // This is only necessary for API level >= 33 (TIRAMISU)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
                PackageManager.PERMISSION_GRANTED) {
            // FCM SDK (and your app) can post notifications.
        } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
            // TODO: display an educational UI explaining to the user the features that will be enabled
            //       by them granting the POST_NOTIFICATION permission. This UI should provide the user
            //       "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
            //       If the user selects "No thanks," allow the user to continue without notifications.
        } else {
            // Directly ask for the permission
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
        }
    }
}

โดยทั่วไป คุณควรแสดง UI เพื่ออธิบายให้ผู้ใช้ทราบถึงฟีเจอร์ที่จะเปิดใช้หากผู้ใช้ให้สิทธิ์แก่แอปในการโพสต์การแจ้งเตือน UI นี้ควรมีตัวเลือกให้ผู้ใช้ยอมรับหรือปฏิเสธ เช่น ปุ่มตกลงและไม่เป็นไร หากผู้ใช้เลือกตกลง ให้ขอสิทธิ์โดยตรง หากผู้ใช้เลือกไม่เป็นไร ให้อนุญาตให้ผู้ใช้ดำเนินการต่อโดยไม่มีการแจ้งเตือน

โปรดดูสิทธิ์รันไทม์ของการแจ้งเตือนเพื่อดูแนวทางปฏิบัติแนะนำเพิ่มเติมว่าแอปควรขอสิทธิ์ POST_NOTIFICATIONS จากผู้ใช้เมื่อใด

สิทธิ์การแจ้งเตือนสำหรับแอปที่กำหนดเป้าหมายเป็น Android 12L (API ระดับ 32) หรือต่ำกว่า

Android จะขอสิทธิ์จากผู้ใช้โดยอัตโนมัติในครั้งแรกที่แอปสร้างช่องทางการแจ้งเตือน ตราบใดที่แอปทำงานอยู่เบื้องหน้า อย่างไรก็ตาม มีคำเตือนที่สำคัญเกี่ยวกับระยะเวลาในการสร้างช่องและคำขอสิทธิ์ดังนี้

  • หากแอปสร้างช่องทางการแจ้งเตือนแรกเมื่อทำงานในเบื้องหลัง (ซึ่ง FCM SDK ทำเมื่อได้รับการแจ้งเตือน FCM) Android จะไม่อนุญาตให้แสดงการแจ้งเตือนนั้นและจะไม่แสดงข้อความแจ้งให้ผู้ใช้อนุญาตการแจ้งเตือนจนกว่าจะถึงครั้งถัดไปที่มีการเปิดแอปของคุณ ซึ่งหมายความว่าการแจ้งเตือนใดๆ ที่ได้รับก่อนเปิดแอปของคุณและผู้ใช้ยอมรับสิทธิ์จะสูญหายไป
  • เราขอแนะนำให้อัปเดตแอปเพื่อกำหนดเป้าหมายเป็น Android 13 ขึ้นไปเพื่อใช้ประโยชน์จาก API ของแพลตฟอร์มในการขอสิทธิ์ หากทำไม่ได้ แอปควรสร้างช่องทางการแจ้งเตือนก่อนที่คุณจะส่งการแจ้งเตือนไปยังแอปเพื่อทริกเกอร์กล่องโต้ตอบสิทธิ์การแจ้งเตือนและตรวจสอบว่าไม่มีการแจ้งเตือนใดสูญหาย ดูข้อมูลเพิ่มเติมได้ในแนวทางปฏิบัติแนะนำสำหรับสิทธิ์การแจ้งเตือน

ไม่บังคับ: นำสิทธิ์ของ POST_NOTIFICATIONS ออก

โดยค่าเริ่มต้น FCM SDK จะมีสิทธิ์ POST_NOTIFICATIONS หากแอปไม่ได้ใช้ข้อความการแจ้งเตือน (ไม่ว่าจะผ่านการแจ้งเตือน FCM, ผ่าน SDK อื่น หรือโพสต์โดยแอปของคุณโดยตรง) และคุณไม่ต้องการให้แอปรวมสิทธิ์ดังกล่าว ก็นำสิทธิ์ดังกล่าวออกได้โดยใช้เครื่องหมายของเครื่องมือผสานไฟล์ remove โปรดทราบว่าการนำสิทธิ์นี้ออกจะป้องกันไม่ให้ระบบแสดงการแจ้งเตือนทั้งหมด ไม่ใช่แค่การแจ้งเตือน FCM เพิ่มข้อมูลต่อไปนี้ลงในไฟล์ Manifest ของแอป

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" tools:node="remove"/>

เข้าถึงโทเค็นการลงทะเบียนอุปกรณ์

เมื่อเริ่มต้นแอปเป็นครั้งแรก FCM SDK จะสร้างโทเค็นการลงทะเบียนสำหรับอินสแตนซ์ของแอปไคลเอ็นต์ หากต้องการกำหนดเป้าหมายอุปกรณ์เดียวหรือสร้างกลุ่มอุปกรณ์ คุณจะต้องเข้าถึงโทเค็นนี้โดยการขยาย FirebaseMessagingService และลบล้าง onNewToken

ส่วนนี้จะอธิบายวิธีเรียกข้อมูลโทเค็นและวิธีตรวจสอบการเปลี่ยนแปลงโทเค็น เนื่องจากโทเค็นอาจหมุนเวียนได้หลังจากเริ่มต้นใช้งานครั้งแรก เราจึงขอแนะนำอย่างยิ่งให้เรียกโทเค็นการลงทะเบียนที่อัปเดตล่าสุด

โทเค็นการลงทะเบียนอาจเปลี่ยนแปลงในกรณีต่อไปนี้

  • แอปได้รับการกู้คืนในอุปกรณ์เครื่องใหม่
  • ผู้ใช้ถอนการติดตั้ง/ติดตั้งแอปอีกครั้ง
  • ผู้ใช้ล้างข้อมูลแอป

ดึงข้อมูลโทเค็นการลงทะเบียนปัจจุบัน

เมื่อต้องการเรียกโทเค็นปัจจุบัน ให้เรียก FirebaseMessaging.getInstance().getToken():

Kotlin+KTX

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result

    // Log and toast
    val msg = getString(R.string.msg_token_fmt, token)
    Log.d(TAG, msg)
    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})

Java

FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
          if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
          }

          // Get new FCM registration token
          String token = task.getResult();

          // Log and toast
          String msg = getString(R.string.msg_token_fmt, token);
          Log.d(TAG, msg);
          Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
        }
    });

ตรวจสอบการสร้างโทเค็น

โค้ดเรียกกลับ onNewToken จะเริ่มทำงานเมื่อมีการสร้างโทเค็นใหม่

Kotlin+KTX

/**
 * Called if the FCM registration token is updated. This may occur if the security of
 * the previous token had been compromised. Note that this is called when the
 * FCM registration token is initially generated so this is where you would retrieve the token.
 */
override fun onNewToken(token: String) {
    Log.d(TAG, "Refreshed token: $token")

    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // FCM registration token to your app server.
    sendRegistrationToServer(token)
}

Java

/**
 * There are two scenarios when onNewToken is called:
 * 1) When a new token is generated on initial app startup
 * 2) Whenever an existing token is changed
 * Under #2, there are three scenarios when the existing token is changed:
 * A) App is restored to a new device
 * B) User uninstalls/reinstalls the app
 * C) User clears app data
 */
@Override
public void onNewToken(@NonNull String token) {
    Log.d(TAG, "Refreshed token: " + token);

    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // FCM registration token to your app server.
    sendRegistrationToServer(token);
}

หลังจากได้รับโทเค็นแล้ว คุณสามารถส่งโทเค็นดังกล่าวไปยังเซิร์ฟเวอร์ของแอปและจัดเก็บโดยใช้วิธีการที่ต้องการได้

ตรวจสอบบริการ Google Play

แอปที่ใช้ SDK บริการ Google Play ควรตรวจสอบอุปกรณ์เพื่อหา APK ของบริการ Google Play ที่เข้ากันได้ทุกครั้ง ก่อนที่จะเข้าถึงฟีเจอร์ของบริการ Google Play เราขอแนะนำให้ดำเนินการใน 2 ที่ ได้แก่ ในเมธอด onCreate() ของกิจกรรมหลัก และในเมธอด onResume() การตรวจสอบใน onCreate() ช่วยให้มั่นใจได้ว่าแอปจะใช้งานไม่ได้หากการตรวจสอบไม่ประสบความสำเร็จ การตรวจสอบใน onResume() ช่วยให้แน่ใจว่าหากผู้ใช้กลับมาที่แอปที่ทำงานอยู่ด้วยวิธีการอื่น เช่น การตรวจสอบผ่านปุ่มย้อนกลับ การตรวจสอบจะยังคงดำเนินการอยู่

หากอุปกรณ์ไม่มีบริการ Google Play เวอร์ชันที่เข้ากันได้ แอปจะเรียกใช้ GoogleApiAvailability.makeGooglePlayServicesAvailable() เพื่ออนุญาตให้ผู้ใช้ดาวน์โหลดบริการ Google Play จาก Play Store ได้

ป้องกันการเริ่มต้นอัตโนมัติ

เมื่อสร้างโทเค็นการจดทะเบียน FCM แล้ว ไลบรารีจะอัปโหลดตัวระบุและข้อมูลการกำหนดค่าไปยัง Firebase หากไม่ต้องการสร้างโทเค็นโดยอัตโนมัติ ให้ปิดใช้การรวบรวม Analytics และการเริ่มต้นอัตโนมัติของ FCM (ต้องปิดใช้ทั้ง 2 รายการ) โดยการเพิ่มค่าข้อมูลเมตาต่อไปนี้ลงใน AndroidManifest.xml

<meta-data
    android:name="firebase_messaging_auto_init_enabled"
    android:value="false" />
<meta-data
    android:name="firebase_analytics_collection_enabled"
    android:value="false" />

หากต้องการเปิดใช้ FCM เริ่มต้นโดยอัตโนมัติอีกครั้ง ให้เรียกรันไทม์โดยทำดังนี้

Kotlin+KTX

Firebase.messaging.isAutoInitEnabled = true

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

หากต้องการเปิดใช้การรวบรวมข้อมูล Analytics อีกครั้ง ให้เรียกใช้เมธอด setAnalyticsCollectionEnabled() ของคลาส FirebaseAnalytics เช่น

setAnalyticsCollectionEnabled(true);

ค่าเหล่านี้จะยังคงอยู่เมื่อมีการรีสตาร์ทแอปเมื่อตั้งค่าแล้ว

ขั้นตอนถัดไป

หลังจากตั้งค่าแอปไคลเอ็นต์แล้ว คุณก็พร้อมที่จะเริ่มส่งข้อความดาวน์สตรีมด้วย การเขียนการแจ้งเตือน ฟังก์ชันการทำงานนี้จะแสดงอยู่ในตัวอย่างการเริ่มต้นอย่างรวดเร็วซึ่งคุณดาวน์โหลด เรียกใช้ และตรวจสอบได้

หากต้องการเพิ่มลักษณะการทำงานขั้นสูงอื่นๆ ลงในแอป คุณสามารถประกาศตัวกรอง Intent และนำกิจกรรมไปใช้เพื่อตอบกลับข้อความขาเข้าได้ โปรดดูรายละเอียดในคำแนะนำสำหรับการส่งข้อความจากเซิร์ฟเวอร์แอป ดังนี้

โปรดทราบว่าหากต้องการใช้ประโยชน์จากฟีเจอร์เหล่านี้ คุณจะต้อง ติดตั้งใช้งานเซิร์ฟเวอร์และโปรโตคอลเซิร์ฟเวอร์ (HTTP หรือ XMPP) หรือการใช้งาน Admin SDK