Android Studio:如何实现应用内多消息通知面板及传感器告警展示
实现传感器阈值告警通知与应用内多消息面板
嘿,针对你这个智能传感器应用的告警需求,我分两部分来给你捋清楚实现步骤,都是Android Studio里实打实的操作:
一、实现传感器阈值触发的自定义告警通知
首先得明确触发逻辑:要么是云端监测到传感器数值超阈值后主动推送给App,要么是App定期从云端拉取数据后本地判断阈值。这里推荐用FCM(Firebase Cloud Messaging)做推送,效率更高,下面是具体步骤:
1. 配置FCM基础环境
在Android Studio的build.gradle(Module级别)里添加FCM依赖:
implementation 'com.google.firebase:firebase-messaging:23.4.0' // 可替换为最新版本
然后把Firebase控制台下载的google-services.json放到App模块根目录,同步项目。
2. 处理推送消息并构建自定义通知
创建一个继承自FirebaseMessagingService的类,重写onMessageReceived方法,解析云端传来的传感器状态、操作指引、通知时间等数据,然后构建带自定义内容的通知:
class MyFirebaseMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) // 解析云端携带的自定义数据 val sensorStatus = remoteMessage.data["sensor_status"] ?: "未知异常" val actionGuide = remoteMessage.data["action"] ?: "请检查设备状态" val notifyTime = remoteMessage.data["notify_time"] ?: SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) // 构建通知 val notificationBuilder = NotificationCompat.Builder(this, "ALERT_CHANNEL_ID") .setSmallIcon(R.drawable.ic_alert_red) .setContentTitle("传感器告警提醒") .setContentText("状态:$sensorStatus\n操作指引:$actionGuide\n通知时间:$notifyTime") .setPriority(NotificationCompat.PRIORITY_HIGH) .setAutoCancel(true) // 点击通知跳转到Alerts Fragment .setContentIntent( NavDeepLinkBuilder(this) .setGraph(R.navigation.nav_graph) .setDestination(R.id.alertsFragment) .createPendingIntent() ) // 适配Android O及以上的通知渠道 val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "ALERT_CHANNEL_ID", "传感器告警频道", NotificationManager.IMPORTANCE_HIGH ).apply { description = "接收传感器数值超标告警" enableVibration(true) vibrationPattern = longArrayOf(100, 200, 300) } notificationManager.createNotificationChannel(channel) } // 发送通知,用时间戳作为通知ID避免重复覆盖 notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build()) } }
如果是App本地拉取数据判断阈值,就在数据拉取完成后加判断逻辑,调用上面的通知构建代码即可:
fun checkSensorThreshold(sensorValue: Float) { val threshold = 90.0f // 自定义你的阈值 if (sensorValue > threshold) { val currentTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) sendAlertNotification( sensorStatus = "数值超标:${sensorValue}%", actionGuide = "请降低设备负载", notifyTime = currentTime ) } }
二、实现Alerts Fragment的多消息通知面板
要展示多条历史告警,需要本地存储消息数据,推荐用Room数据库(结构化存储更方便),然后用RecyclerView展示列表:
1. 定义告警数据模型与Room组件
首先创建告警数据类:
@Entity(tableName = "alert_messages") data class AlertMessage( @PrimaryKey(autoGenerate = true) val id: Int = 0, val sensorStatus: String, val actionGuide: String, val notifyTime: String, val isRead: Boolean = false )
然后创建Dao接口:
@Dao interface AlertDao { @Insert suspend fun insertAlert(alert: AlertMessage) @Query("SELECT * FROM alert_messages ORDER BY notifyTime DESC") fun getAllAlerts(): Flow<List<AlertMessage>> @Update suspend fun updateAlert(alert: AlertMessage) }
再创建Room数据库类:
@Database(entities = [AlertMessage::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun alertDao(): AlertDao companion object { @Volatile private var INSTANCE: AppDatabase? = null fun getDatabase(context: Context): AppDatabase { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "app_database" ).build() INSTANCE = instance instance } } } }
2. 在Alerts Fragment展示消息列表
用ViewModel处理数据逻辑,然后在Fragment里用RecyclerView绑定数据:
class AlertsFragment : Fragment() { private lateinit var alertAdapter: AlertAdapter private lateinit var alertViewModel: AlertViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_alerts, container, false) // 初始化适配器,点击消息标记为已读 alertAdapter = AlertAdapter { alert -> lifecycleScope.launch { alertViewModel.updateAlert(alert.copy(isRead = true)) } } view.recyclerView.apply { adapter = alertAdapter layoutManager = LinearLayoutManager(context) } // 观察数据库数据变化,实时更新列表 alertViewModel.allAlerts.observe(viewLifecycleOwner) { alerts -> alertAdapter.submitList(alerts) } return view } } // 适配器类示例 class AlertAdapter(private val onAlertClick: (AlertMessage) -> Unit) : ListAdapter<AlertMessage, AlertAdapter.AlertViewHolder>(AlertDiffCallback()) { inner class AlertViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(alert: AlertMessage) { itemView.tvStatus.text = alert.sensorStatus itemView.tvAction.text = alert.actionGuide itemView.tvTime.text = alert.notifyTime // 已读消息设置灰色文本 if (alert.isRead) { itemView.tvStatus.setTextColor(Color.GRAY) } else { itemView.tvStatus.setTextColor(Color.RED) } itemView.setOnClickListener { onAlertClick(alert) } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlertViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_alert_message, parent, false) return AlertViewHolder(view) } override fun onBindViewHolder(holder: AlertViewHolder, position: Int) { holder.bind(getItem(position)) } class AlertDiffCallback : DiffUtil.ItemCallback<AlertMessage>() { override fun areItemsTheSame(oldItem: AlertMessage, newItem: AlertMessage): Boolean { return oldItem.id == newItem.id } override fun areContentsTheSame(oldItem: AlertMessage, newItem: AlertMessage): Boolean { return oldItem == newItem } } }
3. 关联通知与应用内面板
每次发送系统通知时,同时把告警消息插入到Room数据库,这样Alerts Fragment就能展示所有历史消息:
// 在发送通知的方法里添加插入数据库逻辑 private fun sendAlertNotification(sensorStatus: String, actionGuide: String, notifyTime: String) { // ... 之前的通知构建代码 ... // 插入到数据库 lifecycleScope.launch { AppDatabase.getDatabase(this@MyFirebaseMessagingService) .alertDao() .insertAlert(AlertMessage( sensorStatus = sensorStatus, actionGuide = actionGuide, notifyTime = notifyTime )) } }
一些额外小建议
- 可以给应用内面板添加下拉刷新功能,用
SwipeRefreshLayout包裹RecyclerView。 - 支持清空已读消息或所有消息的功能,提升用户清理效率。
- 如果不需要FCM,也可以用WorkManager定期从云端拉取传感器数据,实现本地阈值判断。
内容的提问来源于stack exchange,提问作者Tia
相关产品推荐
相关产品推荐

