FCM Notification Not Working in Chinese Phone

How to fix FCM notification in Chinese phone

Yudi Setiawan
Nusanet Developers
8 min readSep 10, 2019

--

Pengenalan

Firebase Cloud Messaging atau sering disingkat dengan sebutan FCM merupakan salah satu teknologi yang mampu mengirim pesan atau layanan pemberitahuan (notification) untuk Android, iOS dan Web. FCM sendiri merupakan penerus dari teknologi sebelumnya yang dimiliki oleh Google yang bernama Google Cloud Messaging (GCM). Dikalangan mobile developer FCM banyak dipakai untuk dimanfaatkan mengirimkan notifikasi dari API ke Mobile (client side).

Permasalahan Yang Ada

Permasalahan yang ada ketika kita pakai FCM adalah ketika app tidak berjalan alias mati total maka, ketika FCM dijalankan seharusnya notifikasi tersebut masuk ke App dan otomatis men-trigger app untuk menjalankan sesuatu yang developer inginkan. Masalahnya adalah notifikasi tersebut terkadang tidak jalan di beberapa device dengan kondisi app dalam keadaan mati total. Ingat ya mati total bukan background mode. Kalau background mode berarti masih ada service yang berjalan dibelakangnya.

Percobaan Analisis

Sekarang untuk mencari analisis dari permasalahan tersebut maka, kita buat projek baru di Android Studio dimana, aplikasinya cuma menerima notifikasi yang masuk dari FCM.

Buat projek baru

Silakan kita buat projek baru di Android Studio dengan nama FCM Analysis.

Buat projek baru di Android Studio

Setup FCM

Sekarang kita perlu untuk setup FCM di projek Android Studio. Untuk cara kali ini kita pakai cara otomatis dari Android Studio saja ya. Caranya kita pilih menu Tools kemudian pilih Firebase.

Setup FCM di projek

Kemudian, akan muncul window baru seperti berikut.

Window Assistant

Selanjutnya, kita pilih Cloud Messaging dan pilih Set up Firebase Cloud Messaging.

Pilih Cloud Messaging

Akan muncul window baru yang menunjukkan langkah-langkah untuk melakukan setup-nya.

Langkah-langkah setup FCM

Jika sudah muncul seperti gambar diatas kita tinggal ikuti langkah-langkahnya saja. Pertama, kita pilih button Connect to Firebase dan nantinya akan muncul dialog seperti berikut.

Pilih Connect to Firebase

Jika loading-nya sudah selesai maka, akan muncul window baru seperti berikut.

Window Connect to Firebase

Kita pilih yang Create new Firebase project kemudian pilih button Connect to Firebase. Jika sudah dipilih button tersebut maka, akan muncul proses seperti berikut.

Proses terhubung ke Console Firebase

Jika prosesnya berhasil seharusnya akan muncul pemberitahuan popup seperti berikut.

Proses pembuatan projek di Console Firebase berhasil

Sekarang status Connect your app to Firebase akan berubah menjadi seperti gambar berikut.

Proses menghubungkan projek app ke Firebase berhasil

Langkah kedua, kita pilih button Add FCM to your app. Maka, akan muncul window baru seperti berikut.

Setup dependency FCM di app

Kita pilih saja button Accept Changes. Maka, tunggu sampai proses sync build gradle-nya selesai. Jika berhasil, seharusnya status Add FCM to your app akan berubah menjadi seperti gambar berikut.

Proses Add FCM to your app berhasil

Buat Service untuk menerima pesan masuk

Sekarang kita ikuti langkah ketiga yaitu, kita diberi petunjuk bahwa kita harus menangani pesan yang masuk dari FCM. Caranya, kita buat service baru dan untuk nama file-nya kita beri nama MyFcmService.

Buat service baru
Buat service baru dengan nama MyFcmService

Setelah file tersebut berhasil dibuat silakan kita extends class tersebut ke FirebaseMessagingService .

Extends ke FirebaseMessagingService

Selanjutnya, kita override method onMessageReceived .

Override method onMessageReceived

Didalamnya method tersebut kita buat kode seperti berikut.

private val tag = javaClass.simpleName

override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(tag, "From: ${remoteMessage.from}")

if (remoteMessage.data != null) {
val remoteData = remoteMessage.data
Log.d(tag, "remoteData: $remoteData")
}
}

Untuk analisis kali ini kita pakai jenis notifikasi data payload. Sedikit info saja bagi kita yang belum tahu di FCM sebenarnya ada 2 jenis notifikasi yang kita kirim yaitu data notifikasi dan data payload. Untuk perbedaannya bahwa data notifikasi dipakai untuk membuat notifikasi secara otomatis ketika notifikasi tersebut masuk ke app sedangkan, data payload dipakai ketika kita ingin mengirimkan data yang cukup kompleks dan kita mau memproses data tersebut. Untuk info lebih jelasnya bisa dibaca di link berikut ya.

Selanjutnya, kita perlu buat fungsi untuk menampilkan notifikasi yang masuk dari FCM. Tambahkan fungsi berikut didalam file MyFcmService.

private fun createNotification(jsonData: JSONObject) {
val titleNotification = jsonData.getString("title")
val notificationChannelId = BuildConfig.APPLICATION_ID + ".myfcmservice"
val notificationChannelName = "Testing FCM"

val contentNotification = jsonData.getString("message")
val alarmNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val mChannel = NotificationChannel(
notificationChannelId,
notificationChannelName,
NotificationManager.IMPORTANCE_DEFAULT
)
alarmNotificationManager.createNotificationChannel(mChannel)
}

val alarmNotificationBuilder = NotificationCompat.Builder(this, notificationChannelId)
.setContentTitle(titleNotification)
.setContentText(contentNotification)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setAutoCancel(true)
alarmNotificationManager.notify(100, alarmNotificationBuilder.build())
}

Selanjutnya, kita buka file AndroidManifest.xml dan kita ubah pada bagian service-nya menjadi seperti berikut.

<application
...
<service
android:name=".MyFcmService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

...
</application>

Token FCM device

Untuk testing kali ini kita memerlukan token FCM yang ada di device. Caranya, kita tinggal override method onNewToken dan buat kodenya seperti berikut.

override fun onNewToken(token: String) {
Log.d(tag, "token: $token")
super.onNewToken(token)
}

Jadi, kode lengkap dari file MyFcmService adalah seperti berikut.

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.media.RingtoneManager
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import org.json.JSONObject

class MyFcmService : FirebaseMessagingService() {

private val tag = javaClass.simpleName

override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(tag, "From: ${remoteMessage.from}")

if (remoteMessage.data != null) {
val remoteData = remoteMessage.data
Log.d(tag, "remoteData: $remoteData")

val jsonData = JSONObject(remoteData)
createNotification(jsonData)
}
}

override fun onNewToken(token: String) {
Log.d(tag, "token: $token")
super.onNewToken(token)
}

private fun createNotification(jsonData: JSONObject) {
val titleNotification = jsonData.getString("title")
val notificationChannelId = BuildConfig.APPLICATION_ID + ".myfcmservice"
val notificationChannelName = "Testing FCM"

val contentNotification = jsonData.getString("message")
val alarmNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val mChannel = NotificationChannel(
notificationChannelId,
notificationChannelName,
NotificationManager.IMPORTANCE_DEFAULT
)
alarmNotificationManager.createNotificationChannel(mChannel)
}

val alarmNotificationBuilder = NotificationCompat.Builder(this, notificationChannelId)
.setContentTitle(titleNotification)
.setContentText(contentNotification)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setAutoCancel(true)
alarmNotificationManager.notify(100, alarmNotificationBuilder.build())
}
}

Testing FCM

Sekarang untuk testing-nya kita perlu jalankan aplikasi yang sudah kita buat tadi lalu, kita lihat di Logcat dengan keyword “token”.

Log token FCM di device

Kita catat terlebih dahulu nilai token tersebut. Kemudian, kita buka aplikasi Postman atau sejenisnya. Kemudian, kita post ke endpoint berikut.

https://fcm.googleapis.com/fcm/send

Dan body-nya seperti berikut.

{
"to": "token_fcm_di_device_android",
"data": {
"title": "Testing Notification",
"message": "Ini pesan notification"
}
}

Kemudian, dibagian header-nya tambahkan key FCM yang kita dapatkan dari console Firebase. Caranya, kita buka console Firebase. Kemudian, pilih Setelan Proyek.

Pilih Setelan proyek

Selanjutnya, pilih Cloud Messaging dan salin Kunci server-nya.

Salin nilai kunci server

Kemudian, Kunci server tadi kita masukkan ke bagian header di bagian Postman atau aplikasi sejenisnya.

Authorization: key=AAAAwNxdd7s:APA91bHCr-XedpHqpUxGh5we672aFCq6HjLY2Mz2ZrFM43YUG9IEl5pkXlM5ezIh5OYWt5XPuDlQnxjzsVUdh992SMWs7aDI7XGGu-t99VVzp9EskhwDmvU1jx5neF4qUyJkvRGWpiz5

Selanjutnya, kita pilih button Send.

Hasil kirim data ke API FCM

Kemudian, kita cek di Logcat Android Studio dan disitu akan terlihat data FCM yang masuk ke Android.

Data FCM yang masuk ke Android

Kemudian, lihat juga di device-nya seharusnya ada notifikasi yang masuk.

Notifikasi FCM yang masuk di Android

Lalu, sekarang kita clear screen app-nya sehingga tidak jalan sama sekali.

Clear screen app

Di Android Studio bisa kita lihat bahwa app-nya benar-benar tidak jalan.

Kondisi app tidak jalan

Sekarang kita test kirim FCM lagi dari Postman atau aplikasi sejenisnya.

Pada video tersebut bisa kita lihat bahwa trigger-nya masuk tapi data notifikasinya tidak masuk. Pesan error-nya adalah

E/FirebaseInstanceId: Error while delivering the message: ServiceIntent not found.

Jikalau kita cari-cari di Google untuk solusinya maka, yang muncul akan seperti berikut.

Hasil pencarian di Google

Hampir semua website yang saya kunjungi dari hasil pencarian tersebut hasilnya tidak ada yang berhasil dari solusi-solusi yang mereka berikan. Testing diatas kita lakukan di device Xiaomi (China Device). Sekarang kita coba testing di Emulator-nya Android Studio.

Testing FCM di Emulator

Ketika saya test di Emulator ternyata FCM masuk ketika kondisinya jalan (foreground) maupun kondisinya tidak jalan. Dari percobaan kedua diatas saya dapat mengambil kesimpulan bahwa ternyata ada masalah di device. Lalu, pertanyaannya ada apa dengan di device Xiaomi? Mengapa FCM tidak masuk ketika kondisi app-nya tidak jalan?

Bingung???

Solusi

Setelah saya cari-cari referensi di Google ternyata di device China terdapat penekanan terhadap app yang menggunakan FCM. Info tersebut bisa kita baca di link berikut.

Dari keterangan website tersebut ada kalimat seperti berikut.

Lots and lots of people have complained about Xiaomi phones not displaying push notifications. This is in fact more of a Chinese thing. Most Chinese manufactured smartphones, suppress push notifications in order to enhance battery life. This may be a little bit inconveniencing if you want to know instantly when a message comes into your phone.

Setelah saya baca-baca solusi dari website tersebut ternyata hasilnya berhasil. Untuk solusinya silakan ikuti langkah-langkah berikut.

Battery Usage

Ternyata dari sisi Xiaomi terdapat fitur battery saver untuk setiap aplikasi. Solusinya bisa dilihat pada video berikut.

Autostart App

Untuk solusi kedua mengenai fitur Autostart app. Di Xiaomi ternyata ada fungsi untuk mengizinkan aplikasi tertentu saja yang boleh hidup secara otomatis. Solusinya bisa dilihat pada video berikut.

Priority

Solusi ketiga adalah masalah prioritas notifikasi. Di Xiaomi ternyata terdapat fitur untuk menon-aktifkan fitur notifikasi setiap app. Solusinya bisa dilihat di video berikut.

Sekarang coba kita test lagi fitur FCM setelah selesai mengubah konfigurasi diatas. Berikut hasilnya.

Dan setelah kita coba lagi ternyata hasilnya berhasil di device Xiaomi.

Untuk source code projeknya bisa dilihat di link berikut.

--

--