Android Notification Builder Expert Эксперт по реализации уведомлений Android с использованием NotificationCompat.Builder и notification channels. Notification Channels (API 26+) class NotificationHelper ( private val context : Context ) { companion object { const val CHANNEL_ID_MESSAGES = "messages" const val CHANNEL_ID_UPDATES = "updates" const val CHANNEL_ID_PROMOTIONS = "promotions" } fun createNotificationChannels ( ) { if ( Build . VERSION . SDK_INT
= Build . VERSION_CODES . O ) { val messagesChannel = NotificationChannel ( CHANNEL_ID_MESSAGES , "Сообщения" , NotificationManager . IMPORTANCE_HIGH ) . apply { description = "Уведомления о новых сообщениях" enableLights ( true ) lightColor = Color . BLUE enableVibration ( true ) vibrationPattern = longArrayOf ( 0 , 250 , 250 , 250 ) } val updatesChannel = NotificationChannel ( CHANNEL_ID_UPDATES , "Обновления" , NotificationManager . IMPORTANCE_DEFAULT ) . apply { description = "Системные обновления" } val notificationManager = context . getSystemService ( NotificationManager :: class . java ) notificationManager . createNotificationChannels ( listOf ( messagesChannel , updatesChannel ) ) } } } Базовое уведомление fun showBasicNotification ( title : String , message : String ) { val intent = Intent ( context , MainActivity :: class . java ) . apply { flags = Intent . FLAG_ACTIVITY_NEW_TASK or Intent . FLAG_ACTIVITY_CLEAR_TASK } val pendingIntent = PendingIntent . getActivity ( context , 0 , intent , PendingIntent . FLAG_IMMUTABLE or PendingIntent . FLAG_UPDATE_CURRENT ) val notification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_notification ) . setContentTitle ( title ) . setContentText ( message ) . setPriority ( NotificationCompat . PRIORITY_HIGH ) . setContentIntent ( pendingIntent ) . setAutoCancel ( true ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( NOTIFICATION_ID , notification ) } Расширяемые уведомления Big Text Style fun showExpandableTextNotification ( title : String , shortText : String , longText : String ) { val bigTextStyle = NotificationCompat . BigTextStyle ( ) . bigText ( longText ) . setBigContentTitle ( title ) . setSummaryText ( "Подробности" ) val notification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_notification ) . setContentTitle ( title ) . setContentText ( shortText ) . setStyle ( bigTextStyle ) . setPriority ( NotificationCompat . PRIORITY_DEFAULT ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( NOTIFICATION_ID , notification ) } Big Picture Style fun showImageNotification ( title : String , message : String , bitmap : Bitmap ) { val bigPictureStyle = NotificationCompat . BigPictureStyle ( ) . bigPicture ( bitmap ) . bigLargeIcon ( null as Bitmap ? ) . setBigContentTitle ( title ) . setSummaryText ( message ) val notification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_notification ) . setContentTitle ( title ) . setContentText ( message ) . setLargeIcon ( bitmap ) . setStyle ( bigPictureStyle ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( NOTIFICATION_ID , notification ) } Inbox Style fun showInboxNotification ( title : String , messages : List < String
) { val inboxStyle = NotificationCompat . InboxStyle ( ) . setBigContentTitle ( title ) . setSummaryText ( " ${ messages . size } новых сообщений" ) messages . take ( 5 ) . forEach { message -> inboxStyle . addLine ( message ) } val notification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_notification ) . setContentTitle ( title ) . setContentText ( " ${ messages . size } новых сообщений" ) . setStyle ( inboxStyle ) . setNumber ( messages . size ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( NOTIFICATION_ID , notification ) } Интерактивные уведомления Action Buttons fun showNotificationWithActions ( title : String , message : String ) { // Reply action val replyIntent = Intent ( context , ReplyReceiver :: class . java ) val replyPendingIntent = PendingIntent . getBroadcast ( context , 0 , replyIntent , PendingIntent . FLAG_IMMUTABLE or PendingIntent . FLAG_UPDATE_CURRENT ) val remoteInput = RemoteInput . Builder ( "key_text_reply" ) . setLabel ( "Ответить" ) . build ( ) val replyAction = NotificationCompat . Action . Builder ( R . drawable . ic_reply , "Ответить" , replyPendingIntent ) . addRemoteInput ( remoteInput ) . build ( ) // Archive action val archiveIntent = Intent ( context , ArchiveReceiver :: class . java ) val archivePendingIntent = PendingIntent . getBroadcast ( context , 1 , archiveIntent , PendingIntent . FLAG_IMMUTABLE ) val archiveAction = NotificationCompat . Action . Builder ( R . drawable . ic_archive , "Архивировать" , archivePendingIntent ) . build ( ) val notification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_notification ) . setContentTitle ( title ) . setContentText ( message ) . addAction ( replyAction ) . addAction ( archiveAction ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( NOTIFICATION_ID , notification ) } Progress Notification fun showProgressNotification ( title : String , maxProgress : Int , currentProgress : Int ) { val notification = NotificationCompat . Builder ( context , CHANNEL_ID_UPDATES ) . setSmallIcon ( R . drawable . ic_download ) . setContentTitle ( title ) . setContentText ( "Загрузка: $ currentProgress %" ) . setProgress ( maxProgress , currentProgress , false ) . setOngoing ( true ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( PROGRESS_NOTIFICATION_ID , notification ) } fun showIndeterminateProgress ( title : String ) { val notification = NotificationCompat . Builder ( context , CHANNEL_ID_UPDATES ) . setSmallIcon ( R . drawable . ic_sync ) . setContentTitle ( title ) . setContentText ( "Синхронизация..." ) . setProgress ( 0 , 0 , true ) . setOngoing ( true ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( PROGRESS_NOTIFICATION_ID , notification ) } fun completeProgressNotification ( title : String ) { val notification = NotificationCompat . Builder ( context , CHANNEL_ID_UPDATES ) . setSmallIcon ( R . drawable . ic_done ) . setContentTitle ( title ) . setContentText ( "Загрузка завершена" ) . setProgress ( 0 , 0 , false ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( PROGRESS_NOTIFICATION_ID , notification ) } Grouped Notifications fun showGroupedNotifications ( messages : List < Message
) { val GROUP_KEY = "com.example.MESSAGE_GROUP" // Individual notifications messages . forEachIndexed { index , message -> val notification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_message ) . setContentTitle ( message . sender ) . setContentText ( message . text ) . setGroup ( GROUP_KEY ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( index , notification ) } // Summary notification val summaryNotification = NotificationCompat . Builder ( context , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_message ) . setContentTitle ( " ${ messages . size } новых сообщений" ) . setStyle ( NotificationCompat . InboxStyle ( ) . setBigContentTitle ( " ${ messages . size } новых сообщений" ) . setSummaryText ( "Сообщения" ) ) . setGroup ( GROUP_KEY ) . setGroupSummary ( true ) . build ( ) NotificationManagerCompat . from ( context ) . notify ( SUMMARY_ID , summaryNotification ) } FCM Integration class MyFirebaseMessagingService : FirebaseMessagingService ( ) { override fun onMessageReceived ( remoteMessage : RemoteMessage ) { remoteMessage . notification ? . let { notification -> showNotification ( notification . title ?: "Уведомление" , notification . body ?: "" ) } remoteMessage . data . isNotEmpty ( ) . let { handleDataMessage ( remoteMessage . data ) } } override fun onNewToken ( token : String ) { sendTokenToServer ( token ) } private fun showNotification ( title : String , body : String ) { val notification = NotificationCompat . Builder ( this , CHANNEL_ID_MESSAGES ) . setSmallIcon ( R . drawable . ic_notification ) . setContentTitle ( title ) . setContentText ( body ) . setPriority ( NotificationCompat . PRIORITY_HIGH ) . setAutoCancel ( true ) . build ( ) NotificationManagerCompat . from ( this ) . notify ( System . currentTimeMillis ( ) . toInt ( ) , notification ) } } Лучшие практики Безопасность // Скрытие контента на lock screen . setVisibility ( NotificationCompat . VISIBILITY_PRIVATE ) . setPublicVersion ( publicNotification ) // Безопасные PendingIntent PendingIntent . FLAG_IMMUTABLE or PendingIntent . FLAG_UPDATE_CURRENT Производительность // Оптимизация bitmap fun scaleBitmap ( bitmap : Bitmap , maxSize : Int = 256 ) : Bitmap { val ratio = minOf ( maxSize . toFloat ( ) / bitmap . width , maxSize . toFloat ( ) / bitmap . height ) return Bitmap . createScaledBitmap ( bitmap , ( bitmap . width * ratio ) . toInt ( ) , ( bitmap . height * ratio ) . toInt ( ) , true ) } Пользовательский опыт Используйте соответствующие importance levels Группируйте связанные уведомления Добавляйте действия для быстрого реагирования Обеспечьте accessibility через content descriptions Тестируйте на разных версиях Android