FCM Notification Not Working in Chinese Phone
How to fix FCM notification in Chinese phone
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.
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.
Kemudian, akan muncul window baru seperti berikut.
Selanjutnya, kita pilih Cloud Messaging dan pilih Set up Firebase Cloud Messaging.
Akan muncul window baru yang menunjukkan langkah-langkah untuk melakukan setup-nya.
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.
Jika loading-nya sudah selesai maka, akan muncul window baru seperti berikut.
Kita pilih yang Create new Firebase project kemudian pilih button Connect to Firebase. Jika sudah dipilih button tersebut maka, akan muncul proses seperti berikut.
Jika prosesnya berhasil seharusnya akan muncul pemberitahuan popup seperti berikut.
Sekarang status Connect your app to Firebase akan berubah menjadi seperti gambar berikut.
Langkah kedua, kita pilih button Add FCM to your app. Maka, akan muncul window baru seperti berikut.
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.
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.
Setelah file tersebut berhasil dibuat silakan kita extends
class tersebut ke FirebaseMessagingService
.
Selanjutnya, kita 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”.
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.
Selanjutnya, pilih Cloud Messaging dan salin Kunci server-nya.
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.
Kemudian, kita cek di Logcat Android Studio dan disitu akan terlihat data FCM yang masuk ke Android.
Kemudian, lihat juga di device-nya seharusnya ada notifikasi yang masuk.
Lalu, sekarang kita clear screen app-nya sehingga tidak jalan sama sekali.
Di Android Studio bisa kita lihat bahwa app-nya benar-benar 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.
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.
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?
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.