Android Studio中基于Firebase实现温度状态显示与通知功能问询
Hey Zack, let's break down how to implement all your requirements step by step based on your existing RealtimeData class code:
实现步骤详解
1. 调整布局:左右分栏展示
First, modify your activity_realtime_data.xml to use ConstraintLayout for the split-screen layout (left for Firebase database structure, right for sensor data display):
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".RealtimeData"> <!-- Top Toolbar --> <androidx.appcompat.widget.Toolbar android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_constraintTop_toTopOf="parent" /> <!-- Left Area: Firebase Database Structure --> <ScrollView android:id="@+id/firebase_db_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="8dp" android:background="#f5f5f5" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/split_divider" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/app_bar"> <TextView android:id="@+id/db_structure_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:text="Firebase Database Structure:\n- sensors\n - temp: --\n - humid: --" android:textSize="14sp" /> </ScrollView> <!-- Divider Line --> <View android:id="@+id/split_divider" android:layout_width="1dp" android:layout_height="0dp" android:background="#cccccc" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/data_display_container" app:layout_constraintStart_toEndOf="@+id/firebase_db_container" app:layout_constraintTop_toBottomOf="@+id/app_bar" /> <!-- Right Area: Sensor Data Display --> <LinearLayout android:id="@+id/data_display_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="8dp" android:orientation="vertical" android:padding="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/split_divider" app:layout_constraintTop_toBottomOf="@+id/app_bar"> <!-- Wifi Status Section --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:layout_marginBottom="20dp" android:orientation="horizontal"> <TextView android:id="@+id/wifi_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Wifi status: OFF" android:textSize="16sp" /> <Switch android:id="@+id/wifiswitch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" /> </LinearLayout> <!-- Temperature Data --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Current Temperature:" android:textSize="16sp" /> <TextView android:id="@+id/mTempView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="--°C" android:textSize="28sp" android:layout_marginBottom="16dp" /> <!-- Humidity Data --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Current Humidity:" android:textSize="16sp" /> <TextView android:id="@+id/mHumidView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="--%" android:textSize="28sp" android:layout_marginBottom="24dp" /> <!-- Temperature Status Alert --> <TextView android:id="@+id/temp_status_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Status: --" android:textSize="22sp" android:textStyle="bold" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
2. 完善RealtimeData类:实时监听与温度状态判断
Update your RealtimeData code to add Firebase database listening logic and temperature status judgment:
import android.graphics.Color; import android.net.wifi.WifiManager; import android.os.Bundle; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; public class RealtimeData extends AppCompatActivity { private DatabaseReference mDatabase; private TextView mTempView; private TextView mHumidView; private TextView tempStatusView; private TextView dbStructureText; // Wifi Related WifiManager wifiManager; TextView wifiStatusTextView; Switch wifiSwitch; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_realtime_data); Toolbar toolbar = findViewById(R.id.app_bar); setSupportActionBar(toolbar); // Initialize UI Components mTempView = findViewById(R.id.mTempView); mHumidView = findViewById(R.id.mHumidView); tempStatusView = findViewById(R.id.temp_status_view); dbStructureText = findViewById(R.id.db_structure_text); // Wifi Status Setup Toast.makeText(RealtimeData.this, "Make sure device is connected to the internet for latest data", Toast.LENGTH_LONG).show(); wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE); wifiStatusTextView = findViewById(R.id.wifi_status); wifiSwitch = findViewById(R.id.wifiswitch); updateWifiStatus(); wifiSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { wifiManager.setWifiEnabled(isChecked); updateWifiStatus(); }); // Initialize Firebase Database Reference (replace with your node path) mDatabase = FirebaseDatabase.getInstance().getReference("sensors"); // Listen for real-time database changes mDatabase.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { // Fetch temperature and humidity Double temp = snapshot.child("temp").getValue(Double.class); Integer humid = snapshot.child("humid").getValue(Integer.class); // Update UI with sensor data if (temp != null) { mTempView.setText(temp + "°C"); // Check temperature status if (temp > 30) { tempStatusView.setText("abnormal"); tempStatusView.setTextColor(Color.RED); // You can trigger a notification here if needed } else { tempStatusView.setText("normal"); tempStatusView.setTextColor(Color.GREEN); } } if (humid != null) { mHumidView.setText(humid + "%"); } // Update left panel with database structure updateDbStructureDisplay(snapshot); } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(RealtimeData.this, "Failed to load data: " + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); } // Update Wifi status text and switch state private void updateWifiStatus() { boolean isWifiEnabled = wifiManager.isWifiEnabled(); wifiStatusTextView.setText(isWifiEnabled ? "Wifi status: ON" : "Wifi status: OFF"); wifiSwitch.setChecked(isWifiEnabled); } // Traverse Firebase snapshot and update structure display private void updateDbStructureDisplay(DataSnapshot snapshot) { StringBuilder sb = new StringBuilder("Firebase Database Structure:\n"); traverseSnapshot(snapshot, sb, 0); dbStructureText.setText(sb.toString()); } // Recursively traverse database nodes private void traverseSnapshot(DataSnapshot snapshot, StringBuilder sb, int indentLevel) { String indent = " ".repeat(indentLevel); sb.append(indent).append("- ").append(snapshot.getKey()).append("\n"); for (DataSnapshot child : snapshot.getChildren()) { if (child.getValue() != null && !child.hasChildren()) { sb.append(" ").append(indent).append("- ").append(child.getKey()).append(": ").append(child.getValue().toString()).append("\n"); } else { traverseSnapshot(child, sb, indentLevel + 1); } } } }
3. Implement Firebase Notification Push (FCM)
To send notifications to users, integrate Firebase Cloud Messaging:
3.1 Add FCM Dependency
Add this to your module-level app/build.gradle:
dependencies { // Other dependencies... implementation 'com.google.firebase:firebase-messaging:23.4.1' }
3.2 Create Messaging Service Class
Create MyFirebaseMessagingService.java to handle incoming notifications:
import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import androidx.core.app.NotificationCompat; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String CHANNEL_ID = "sensor_alert_channel"; @Override public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); if (remoteMessage.getNotification() != null) { sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody()); } } // Show notification in system tray private void sendNotification(String title, String messageBody) { Intent intent = new Intent(this, RealtimeData.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE); Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) // Replace with your icon .setContentTitle(title) .setContentText(messageBody) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent) .setPriority(Notification.PRIORITY_DEFAULT); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Create channel for Android O and above if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Sensor Alerts", NotificationManager.IMPORTANCE_DEFAULT); notificationManager.createNotificationChannel(channel); } notificationManager.notify(0, notificationBuilder.build()); } }
3.3 Register Service in Manifest
Add this inside the <application> tag of your AndroidManifest.xml:
<service android:name=".MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
3.4 Trigger Notifications
- Manual Trigger: Go to Firebase Console > Your Project > Cloud Messaging > Send your first message to send notifications manually.
- Auto Trigger on Abnormal Temp: Use Firebase Cloud Functions to listen for temperature changes. Example Node.js function:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.sendTempAlert = functions.database.ref('/sensors/temp') .onUpdate((change) => { const newTemp = change.after.val(); if (newTemp > 30) { const payload = { notification: { title: "Temperature Alert!", body: `Current temp is ${newTemp}°C - abnormal!` } }; return admin.messaging().sendToTopic("sensor_users", payload); } return null; });
Key Notes
- Ensure your Firebase project is correctly linked to Android Studio (google-services.json added).
- Add required permissions in
AndroidManifest.xml:<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> - For testing, set Firebase database rules to public, then update to secure rules later.
内容的提问来源于stack exchange,提问作者Zack Choon
相关产品推荐
相关产品推荐

