Thiết lập ứng dụng nhắn tin qua đám mây của Firebase trên Android

Ứng dụng FCM yêu cầu thiết bị chạy Android 4.4 trở lên phải cài đặt ứng dụng Cửa hàng Google Play hoặc trình mô phỏng chạy Android 4.4 có API Google. Xin lưu ý rằng bạn không bị giới hạn ở việc triển khai ứng dụng Android thông qua Cửa hàng Google Play.

Thiết lập SDK

Phần này bao gồm các nhiệm vụ bạn có thể đã hoàn thành nếu đã bật các tính năng khác của Firebase cho ứng dụng. Nếu bạn chưa bật, hãy thêm Firebase vào dự án Android của bạn

Chỉnh sửa tệp kê khai ứng dụng

Thêm mã sau vào tệp kê khai của ứng dụng:

  • Dịch vụ mở rộng FirebaseMessagingService. Đây là yêu cầu bắt buộc nếu bạn muốn xử lý bất kỳ thông báo nào ngoài việc nhận thông báo trên các ứng dụng ở chế độ nền. Để nhận thông báo trong các ứng dụng chạy trên nền trước, nhận tải trọng dữ liệu, gửi thông báo ngược dòng, v.v., bạn phải mở rộng dịch vụ này.
  • <service
        android:name=".java.MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
  • (Không bắt buộc) Trong thành phần ứng dụng, các phần tử siêu dữ liệu để đặt màu và biểu tượng thông báo mặc định. Android sử dụng các giá trị này bất cứ khi nào tin nhắn đến không đặt biểu tượng hoặc màu sắc một cách rõ ràng.
  • <!-- 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" />
  • (Không bắt buộc) Từ Android 8.0 (API cấp 26) trở lên, chúng tôi hỗ trợ và đề xuất kênh thông báo. FCM cung cấp kênh thông báo mặc định với các chế độ cài đặt cơ bản. Nếu bạn muốn tạo và sử dụng kênh mặc định của riêng mình, hãy đặt default_notification_channel_id thành mã nhận dạng của đối tượng kênh thông báo như dưới đây; FCM sẽ sử dụng giá trị này bất cứ khi nào có tin nhắn đến không thiết lập rõ ràng kênh thông báo. Để tìm hiểu thêm, hãy xem bài viết Quản lý kênh thông báo.
  • <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/default_notification_channel_id" />

Yêu cầu quyền gửi thông báo khi bắt đầu chạy trên Android 13 trở lên

Android 13 giới thiệu một quyền mới khi bắt đầu chạy để hiện thông báo. Vấn đề này ảnh hưởng đến tất cả các ứng dụng chạy trên Android 13 trở lên sử dụng thông báo FCM.

Theo mặc định, SDK FCM (phiên bản 23.0.6 trở lên) bao gồm quyền POST_NOTIFICATIONS được xác định trong tệp kê khai. Tuy nhiên, ứng dụng của bạn cũng cần yêu cầu phiên bản thời gian chạy của quyền này thông qua hằng số android.permission.POST_NOTIFICATIONS. Ứng dụng của bạn sẽ không được phép hiển thị thông báo cho đến khi người dùng cấp quyền này.

Cách yêu cầu quyền khi bắt đầu chạy mới:

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);
        }
    }
}

Nhìn chung, bạn nên hiển thị giao diện người dùng giải thích cho người dùng các tính năng sẽ được bật nếu họ cấp quyền cho ứng dụng đăng thông báo. Giao diện người dùng này sẽ cung cấp cho người dùng các tuỳ chọn để đồng ý hoặc từ chối, chẳng hạn như nút OKKhông, cảm ơn. Nếu người dùng chọn OK, hãy trực tiếp yêu cầu cấp quyền. Nếu người dùng chọn Không, cảm ơn, hãy cho phép người dùng tiếp tục mà không cần thông báo.

Vui lòng xem bài viết Quyền khi bắt đầu chạy thông báo để biết thêm các phương pháp hay nhất về thời điểm ứng dụng nên yêu cầu người dùng cấp quyền POST_NOTIFICATIONS.

Quyền gửi thông báo đối với ứng dụng nhắm đến Android 12L (API cấp 32) trở xuống

Android tự động yêu cầu người dùng cấp quyền vào lần đầu tiên ứng dụng của bạn tạo kênh thông báo, miễn là ứng dụng đang chạy ở nền trước. Tuy nhiên, có một số lưu ý quan trọng liên quan đến thời gian tạo kênh và yêu cầu cấp quyền:

  • Nếu ứng dụng của bạn tạo kênh thông báo đầu tiên khi đang chạy ở chế độ nền (SDK FCM sẽ thực hiện khi nhận được thông báo FCM), Android sẽ không cho phép hiển thị thông báo và sẽ không nhắc người dùng cấp quyền gửi thông báo cho đến lần tiếp theo ứng dụng của bạn mở. Điều này có nghĩa là mọi thông báo nhận được trước khi ứng dụng của bạn mở và người dùng chấp nhận quyền sẽ bị mất.
  • Bạn nên cập nhật ứng dụng để nhắm đến Android 13 trở lên nhằm tận dụng các API của nền tảng để yêu cầu cấp quyền. Nếu không thể, ứng dụng của bạn nên tạo kênh thông báo trước khi bạn gửi bất kỳ thông báo nào đến ứng dụng để kích hoạt hộp thoại cấp quyền thông báo và đảm bảo không có thông báo nào bị mất. Xem các phương pháp hay nhất về quyền gửi thông báo để biết thêm thông tin.

Không bắt buộc: xoá quyền POST_NOTIFICATIONS

Theo mặc định, SDK FCM bao gồm quyền POST_NOTIFICATIONS. Nếu ứng dụng của bạn không sử dụng thông báo (cho dù là thông qua thông báo FCM, thông qua SDK khác hoặc do ứng dụng đăng trực tiếp) và bạn không muốn ứng dụng đưa quyền này vào, thì bạn có thể xoá quyền đó bằng cách sử dụng điểm đánh dấu remove của trình hợp nhất tệp kê khai. Xin lưu ý rằng việc xoá quyền này sẽ ngăn hiển thị tất cả thông báo, chứ không chỉ thông báo FCM. Thêm đoạn mã sau vào tệp kê khai của ứng dụng:

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

Truy cập vào mã thông báo đăng ký thiết bị

Trong lần đầu khởi động ứng dụng lần đầu, SDK FCM sẽ tạo mã thông báo đăng ký cho phiên bản ứng dụng. Nếu muốn nhắm đến một thiết bị hoặc tạo nhóm thiết bị, bạn cần truy cập vào mã thông báo này bằng cách mở rộng FirebaseMessagingService và ghi đè onNewToken.

Phần này mô tả cách truy xuất mã thông báo và cách theo dõi các thay đổi đối với mã thông báo. Vì mã thông báo có thể xoay vòng sau lần khởi động đầu tiên, bạn nên truy xuất mã thông báo đăng ký đã cập nhật mới nhất.

Mã thông báo đăng ký có thể thay đổi khi:

  • Ứng dụng này được khôi phục trên một thiết bị mới
  • Người dùng gỡ cài đặt/cài đặt lại ứng dụng
  • Người dùng xoá dữ liệu ứng dụng.

Truy xuất mã thông báo đăng ký hiện tại

Khi bạn cần truy xuất mã thông báo hiện tại, hãy gọi 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();
        }
    });

Theo dõi quá trình tạo mã thông báo

Lệnh gọi lại onNewToken sẽ kích hoạt bất cứ khi nào mã thông báo mới được tạo.

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);
}

Sau khi nhận được mã thông báo, bạn có thể gửi mã đó đến máy chủ ứng dụng và lưu trữ mã đó bằng phương thức ưu tiên.

Kiểm tra Dịch vụ Google Play

Các ứng dụng dựa vào SDK Dịch vụ Google Play phải luôn kiểm tra thiết bị để tìm tệp APK Dịch vụ Google Play tương thích trước khi sử dụng các tính năng của Dịch vụ Google Play. Bạn nên thực hiện việc này ở 2 vị trí: trong phương thức onCreate() của hoạt động chính và trong phương thức onResume() của hoạt động đó. Quy trình kiểm tra onCreate() đảm bảo ứng dụng không được sử dụng nếu không được kiểm tra thành công. Quy trình kiểm tra onResume() đảm bảo rằng nếu người dùng quay lại ứng dụng đang chạy thông qua một số phương thức khác, chẳng hạn như thông qua nút quay lại, thì hoạt động kiểm tra vẫn được thực hiện.

Nếu thiết bị không có phiên bản tương thích của Dịch vụ Google Play, ứng dụng có thể gọi GoogleApiAvailability.makeGooglePlayServicesAvailable() để cho phép người dùng tải Dịch vụ Google Play xuống từ Cửa hàng Play.

Ngăn việc tự động khởi chạy

Khi mã đăng ký FCM được tạo, thư viện sẽ tải dữ liệu nhận dạng và cấu hình lên Firebase. Nếu bạn không muốn ngăn việc tự động tạo mã thông báo, hãy tắt tính năng thu thập Analytics và tính năng tự động khởi chạy FCM (bạn phải tắt cả hai) bằng cách thêm các giá trị siêu dữ liệu sau vào 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" />

Để bật lại tính năng tự động khởi chạy FCM, hãy thực hiện một cuộc gọi trong thời gian chạy:

Kotlin+KTX

Firebase.messaging.isAutoInitEnabled = true

Java

FirebaseMessaging.getInstance().setAutoInitEnabled(true);

Để bật lại tính năng thu thập Analytics, hãy gọi phương thức setAnalyticsCollectionEnabled() của lớp FirebaseAnalytics. Ví dụ:

setAnalyticsCollectionEnabled(true);

Các giá trị này vẫn tồn tại cho đến khi ứng dụng khởi động lại sau khi bạn thiết lập xong.

Các bước tiếp theo

Sau khi thiết lập ứng dụng, bạn có thể bắt đầu gửi thông báo xuôi dòng bằng Trình soạn thông báo. Chức năng này được minh hoạ trong mẫu bắt đầu nhanh mà bạn có thể tải xuống, chạy và xem lại.

Để thêm hành vi nâng cao khác vào ứng dụng của mình, bạn có thể khai báo bộ lọc ý định và triển khai một hoạt động để phản hồi các tin nhắn đến. Để biết thông tin chi tiết, hãy xem hướng dẫn gửi thông báo từ máy chủ ứng dụng:

Lưu ý rằng để tận dụng các tính năng này, bạn sẽ cần triển khai máy chủ và các procotols máy chủ (HTTP hoặcKiểm soát thông tin trên mạng) hoặc triển khai SDK dành cho quản trị viên.