Android : Masalah Notifikasi dan AD ID di Android 12 & 13

Ady Sanjaya
5 min readOct 13, 2023

--

  1. Notification Crash

Dimulai sejak android 12 (Api Level 31) sebagai improvement app security, google mengharuskan aplikasi untuk membuat flagging apakah FLAG_MUTABLE atau FLAG_IMMUTABLE.

FLAG_MUTABLE

  • PendingIntent yang di-attach dengan FLAG_MUTABLE dapat diubah setelah dibuat.
  • Dapat memperbarui PendingIntent dengan informasi tambahan atau aksi lain seperti saat notifikasi diklik setelah notifikasi dibuat.

FLAG_IMMUTABLE

  • PendingIntent yang di-attach dengan FLAG_IMMUTABLE tidak dapat diubah setelah dibuat.
  • Ini berarti PendingIntent akan tetap tidak berubah, dan tidak ada perubahan aksi/informasi yang dapat dilakukan kepadanya setelah notifikasi dibuat.

Step Solusi :

  • Cukup ubah bagian berikut pada notification service
  • Berikut contoh lengkapnya :
class MyFirebaseMessagingService : FirebaseMessagingService() {

var session: SessionManager? = null

override fun onCreate() {
session = SessionManager(this)
super.onCreate()
}

override fun onNewToken(s: String) {
super.onNewToken(s)
session?.setFirebaseId(s)
}

override fun onMessageReceived(remoteMessage: RemoteMessage) {
createNotification(
remoteMessage.data["title"],
remoteMessage.data["message"],
remoteMessage.data
)
}

private fun createNotification(
title: String?,
body: String?,
data: MutableMap<String, String>
) {
@SuppressLint("SimpleDateFormat")
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val now = Date()
data["datetime"] = sdf.format(now)

val intent: Intent
if (session?.isLoggedIn == true) {
when (data["type"]){
"deposit" -> {
intent = Intent(this, ActDetailDeposit::class.java)
intent.putExtra("id", data["id_deposit"]?.toInt())
sendBroadcast(Intent("receiver.detail_deposit")
.putExtra("data",data["id_deposit"]?.toInt())
.putExtra("type",data["type"])
)
}

else -> {
intent = Intent(this, MainActivity::class.java)
}
}

}else{
intent = Intent(this, ActWelcome::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}

intent.action = System.currentTimeMillis().toString()
var resultIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
var notificationSoundURI: Uri
val GROUP_KEY = "group"

val CHANNEL_ID = resources.getString(R.string.channel_id)// The id of the channel.
val groupBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)

val aBitmap: Bitmap? = BitmapFactory.decodeResource(resources, R.drawable.ic_notif)

groupBuilder
.setSmallIcon(R.drawable.ic_notif)
.setLargeIcon(aBitmap)
.setAutoCancel(true)
.setContentTitle(title)
.setContentText(body)
.setGroupSummary(true)
.setGroup(GROUP_KEY)
.setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
.setStyle(NotificationCompat.BigTextStyle().bigText(body))

notificationBuilder
.setSmallIcon(R.drawable.ic_notif)
.setLargeIcon(aBitmap)
.setAutoCancel(true)
.setContentTitle(title)
.setContentText(body)
.setGroup(GROUP_KEY)
.setStyle(NotificationCompat.BigTextStyle().bigText(body))
.setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
.setContentIntent(resultIntent)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
groupBuilder.color = resources.getColor(R.color.palette1, null)
notificationBuilder.color = resources.getColor(R.color.palette1, null)
} else {
groupBuilder.color = resources.getColor(R.color.palette1)
notificationBuilder.color = resources.getColor(R.color.palette1)
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.channel_name)// The user-visible name of the channel

val attributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
val mChannel =
NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH)
mChannel.enableLights(true)
mChannel.lightColor = Color.BLUE
mChannel.enableVibration(true)
mChannel.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
mChannel.setSound(notificationSoundURI, attributes)

notificationManager.createNotificationChannel(mChannel)
} else {
groupBuilder
.setSound(notificationSoundURI)
.setVibrate(longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400))

notificationBuilder
.setSound(notificationSoundURI)
.setVibrate(longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400))

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
notificationBuilder.priority = NotificationManager.IMPORTANCE_HIGH
}
}

notificationManager.notify(0, groupBuilder.build())
notificationManager.notify(NotificationID.id, notificationBuilder.build())
}

companion object {
private val TAG = MyFirebaseMessagingService::class.java.simpleName
}
}

2. AD_ID

Salah satu impact yang muncul ketika compileSdk ≥ 33 dan belum menambahkan AD ID adalah aplikasi crash ketika notifikasi masuk

Step Solusi :

  • Tambahkan script berikut pada manifest
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
  • Masuk ke developer console, pilih aplikasi yang sesuai
  • Scroll sidebar, Masuk ke AppContent > Actioned > Start Declaration
  • Pada isian kita diharapkan mengisikan sesuai peruntukan advertising ID digunakan untuk Apa. Jika aplikasi sama sekali tidak menggunakan package yang membutuhkan advertising id bisa untuk memilih No. Namun kebanyakan aplikasi menggunakan notifikasi firebase yang membutuhkan advertising ID didalamnya.
  • Sesuaikan dengan kebutuhan aplikasi anda
  • Terakhir silahkan menunggu review dari playstore.

3. Permission Notification

Dimulai sejak android 13 pada tahun 2022, android menerapkan akses terbatas untuk menampilkan notifikasi. Aplikasi yang belum menambahkan permission ini tidak akan bisa menerima notifikasi

notifikasi tidak bisa diaktifkan

Step Solusi :

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>

Buat NotificationPermissionHelper

/** Helper to ask notification permission.  */
object NotificationPermissionHelper {
const val NOTIFICATION_PERMISSION_CODE = 13
const val NOTIFICATION_PERMISSION = Manifest.permission.POST_NOTIFICATIONS

/** Check to see we have the necessary permissions for this app. */
fun hasNotificationPermission(activity: Activity): Boolean {
return ContextCompat.checkSelfPermission(activity, NOTIFICATION_PERMISSION) == PackageManager.PERMISSION_GRANTED
}

/** Check to see we have the necessary permissions for this app, and ask for them if we don't. */
fun requestNotificationPermission(fragment: Fragment) {
fragment.requestPermissions(arrayOf(NOTIFICATION_PERMISSION), NOTIFICATION_PERMISSION_CODE)
}

fun requestNotificationPermission(activity: Activity) {
ActivityCompat.requestPermissions(
activity, arrayOf(NOTIFICATION_PERMISSION), NOTIFICATION_PERMISSION_CODE
)
}

/** Check to see if we need to show the rationale for this permission. */
fun shouldShowRequestPermissionRationale(activity: Activity): Boolean {
return ActivityCompat.shouldShowRequestPermissionRationale(activity, NOTIFICATION_PERMISSION)
}

/** Launch Application Setting to grant permission. */
fun launchPermissionSettings(activity: Activity) {
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
intent.data = Uri.fromParts("package", activity.packageName, null)
activity.startActivity(intent)
}
}
  • Tambahkan Helper ke Activity yang muncul pertama kali
class ActWelcome : AppCompatActivity(){  

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_welcome)

//request permission for notification
if(!NotificationPermissionHelper.hasNotificationPermission(this)) {
NotificationPermissionHelper.requestNotificationPermission(this)
}
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode== NotificationPermissionHelper.NOTIFICATION_PERMISSION_CODE) {
if (!NotificationPermissionHelper.hasNotificationPermission(this)) {
Toast.makeText(
this,
"Izin akses notifikasi dibutuhkan",
Toast.LENGTH_SHORT
).show()
if (!NotificationPermissionHelper.shouldShowRequestPermissionRationale(this)) {
// Permission denied with checking "Do not ask again".
NotificationPermissionHelper.launchPermissionSettings(this)
}
}
}
}
}
  • Setelah dijalankan, maka hasil akhir akan menampilkan pilihan berikut
  • Setelah di allow maka pada setting notification permission sudah aktif dan sudah bisa menerima notifikasi.

Itulah tadi beberapa perubahan yang perlu di highlight di android 12 & 13 untuk aplikasi yang sifatnya legacy. Happy code 🎉

Credits :

https://staticg.sportskeeda.com/editor/2023/03/de684-16788774455984-1920.jpg

--

--

Ady Sanjaya
Ady Sanjaya

No responses yet