You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:06:18