Giap Hiep

I'm Giap Hiep

I'm a web developer, a gymer. I enjoy share something i know that help people's work!
Giap Hiep

Thay đổi trạng thái ứng dụng với Notification(Android)

Nếu bạn muốn người dùng của bạn có thể tương tác với ứng dụng Android của bạn ngay cả khi nó không ở foreground, Notification là lựa chọn. Hôm nay, mình sẽ hướng dẫn các bạn sử dụng Notification để làm điều đó.

Bước 1: Tạo một Notification Channel

Android yêu cầu bạn phải đăng ký tất cả các Notification của mình vào một Notification Channel cho Android 8.0 (API cấp 26) và các phiên bản mới hơn. Giờ thì tạo channel nào!

private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, importance).apply {
                    description = CHANNEL_DESCRIPTION
                }
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }

Sẽ an toàn hơn khi gọi phương thức này bên trong hàm onCreate của bạn vì bạn có thể gọi phương thức này nhiều lần. Nếu có một channel có cùng id, nó sẽ không được tạo lại.

Bước 2: Tạo một Notification đơn giản

Ở đây, mình sẽ sử dụng lớp NotificationCompat để tạo Notification. Sở dĩ mình dùng lớp này vì lớp này sẽ hoạt động được với tất cả các phiên bản Android của các thiết bị. Dưới là code tạo một Notification đơn giản:

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_launcher_foreground)
    .setContentTitle("Interactive Notification Title")
    .setContentText("Interactive Notification Text")
val notSoInteractiveNotification = builder.build()

Giờ thì chúng ta đã có một Notification rồi. Tuy nhiên, nó chỉ hiển thị một cách đơn giản gồm icon, title và description thôi, không thể tương tác được!

Bước 3: Thêm Pending Intent

Bạn có thể nhận được tất cả các even từ Notification bằng cách sử dụng Intent bên trong của PendingIntent vì chúng đang chờ để kích hoạt.
Chúng ta sẽ sử dụng một đối tượng Intent có lớp BroadcastReceiver ở trong vì chúng ta muốn nó được thực thi ngay cả khi ứng dụng không ở trên foreground.
Tiếp theo, chúng ta sẽ tạo một lớp BroadcastReceiver và đẩy một phương thức tạo PendingIntent.

class InteractiveNotificationBroadcastReceiver : BroadcastReceiver() {

  override fun onReceive(context: Context?, intent: Intent?) {
    Log.d("InteractiveNotificationBroadcastReceiver", "onReceive")
  }

  companion object {
    fun newPendingIntent(context: Context): PendingIntent {
      val intent = Intent(context, InteractiveNotificationBroadcastReceiver::class.java)
      return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }
  }
}

Chúng ta biết làm thế nào để có được PendingIntent của chúng ta bây giờ. Hãy để thêm nó vào Notification của chúng ta.

Bước 4: Thêm PendingIntent vào Notification Builder

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
  .setSmallIcon(R.drawable.ic_launcher_foreground)
  .setContentTitle("Interactive Notification Title")
  .setContentText("Interactive Notification Text")
  .setContentIntent(InteractiveNotificationBroadcastReceiver.newPendingIntent(this))
val soCloseInteractiveNotification = builder.build()

Thêm BroastcastReceiver class vào AndroidManifest

Bước này tuy rất ngắn nhưng lại rất quan trọng. Nếu không thêm BroastcastReceiver của bạn vào AndroidManifest, bạn sẽ không thể nhận được các sự kiện click.

Thêm dòng code dưới đây vào bên trong thẻ <application></application> trong file AndroidManifest.

<receiver android:name=".InteractiveNotificationBroadcastReceiver" />

Nếu mọi thứ diễn ra bình thường thì bạn sẽ nhìn thấy dòng log này: “D/InteractiveNotificationBroadcastReceiver: onReceive” trong Logcat.

Bước 6: Cập nhật Notification

Bây giờ, việc bạn cần làm là tạo một Notification mới với cùng Channel id và Notification id nhưng khác content. Override hàm onReceiver và thêm code như bên dưới:

override fun onReceive(context: Context?, intent: Intent?) {
  context?.let {
    Log.d("InteractiveNotificationBroadcastReceiver", "onReceive")
    val notification = NotificationCompat.Builder(context, CHANNEL_ID)
      .setSmallIcon(R.drawable.ic_launcher_foreground)
      .setContentTitle("Interactive Notification Title")
      .setContentText("MODIFIED text")
      .setContentIntent(newPendingIntent(context))
      .build()
    NotificationManagerCompat.from(context)
      .notify(INTERACTIVE_NOTIFICATION_ID, notification)
  }
}

Khi click vào Notification sẽ kích hoạt Intent mà chúng ta đã đặt làm content. Đồng thời, nó cũng làm Notification biến mất khỏi màn hình và bạn sẽ không thể tương tác được với nó nữa. Nếu bạn vẫn muốn tiếp tục tương tác với nó, Android đã cung cấp cho bạn một giải pháp, đó là thêm Action vào Notification của bạn.

Thêm Action vào Notification cũng gần giống việc bạn cài đặt content cho Notification của bạn vậy. Yêu cầu để thêm một Action như sau:

  • Một resource id của một icon
  • Action Title
  • PendingIntent(Intent sẽ được kích hoạt khi Action xảy ra)

Thêm Action vào Notification builder như sau:

.addAction(
    R.drawable.ic_launcher_foreground,
    "Increment",
    InteractiveNotificationBroadcastReceiver.newPendingIntent(context)
)

Vậy là xong, giờ thì bạn hãy run app và kiểm tra xem sao nhé!

Hy vọng sẽ giúp ích cho những người mới. Cảm ơn các bạn đã quan tâm!