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

如何让Android FCM通知服务始终在后台运行?

Hey there, let's fix your FCM background notification issue. The core problem here is how you're sending messages from your server and a couple of missing client-side configurations. Let's break this down step by step:

1. Fix the Server-Side FCM Message Structure

Right now, you're only sending a data payload. On Android, when your app is in the background or closed, FCM doesn't deliver data messages directly to your FirebaseMessagingService—instead, you need to include a notification payload to trigger the system to automatically show the notification. You can still keep the data payload if you need to pass extra information alongside the notification.

Update your server code to include both payload types:

public static void pushFCMNotification(String DeviceIdKey, String title, String content) throws Exception { 
    String authKey = AUTH_KEY_FCM; 
    String FMCurl = API_URL_FCM; 
    URL url = new URL(FMCurl); 
    HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
    conn.setUseCaches(false); 
    conn.setDoInput(true); 
    conn.setDoOutput(true); 
    conn.setRequestMethod("POST"); 
    conn.setRequestProperty("Authorization", "key=" + authKey); 
    conn.setRequestProperty("Content-Type", "application/json"); 

    JSONObject data = new JSONObject(); 
    data.put("to", DeviceIdKey.trim()); 

    // Add notification payload for background/closed app delivery
    JSONObject notification = new JSONObject();
    notification.put("title", title);
    notification.put("body", content);
    notification.put("click_action", ".MainActivity");
    data.put("notification", notification);

    // Keep your existing data payload for extra context
    JSONObject info = new JSONObject(); 
    info.put("title", title); 
    info.put("content-text", content); 
    info.put("click_action", ".MainActivity"); 
    data.put("data", info); 

    System.out.println(data.toString()); 
    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); 
    wr.write(data.toString()); 
    wr.flush(); 
    wr.close(); 

    int responseCode = conn.getResponseCode(); 
    System.out.println("Response Code : " + responseCode); 
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    String inputLine; 
    StringBuffer response = new StringBuffer(); 
    while ((inputLine = in.readLine()) != null) { 
        response.append(inputLine); 
    } 
    in.close(); 
} 

2. Add Notification Channel for Android 8.0+

Your displayNotification method doesn't create a notification channel, which is mandatory for Android O (API 26) and above. Without this, notifications won't appear even if they're successfully delivered. Update your FCM_Messaging_Service to include channel setup:

public class FCM_Messaging_Service extends FirebaseMessagingService {
    private static final String CHANNEL_ID = "FCM_NOTIFICATION_CHANNEL";
    private static final String CHANNEL_NAME = "FCM Notifications";
    private static final String CHANNEL_DESCRIPTION = "Updates and alerts from your app";

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    CHANNEL_NAME,
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            channel.setDescription(CHANNEL_DESCRIPTION);
            channel.enableLights(true);
            channel.setLightColor(Color.RED);
            channel.setVibrationPattern(new long[]{0, 500});
            channel.enableVibration(true);

            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        
        String title = "";
        String contentText = "";

        // Handle both notification and data payloads
        if (remoteMessage.getNotification() != null) {
            title = remoteMessage.getNotification().getTitle();
            contentText = remoteMessage.getNotification().getBody();
        }
        // Fallback to data payload if notification is null
        if (remoteMessage.getData() != null) {
            if (title.isEmpty()) title = remoteMessage.getData().get("title");
            if (contentText.isEmpty()) contentText = remoteMessage.getData().get("content-text");
        }

        displayNotification(title, contentText, this);

        // Vibrate logic remains unchanged
        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
        } else {
            v.vibrate(500);
        }
    }

    @SuppressLint("NewApi")
    public void displayNotification(String title, String contentText, Context context) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle(title)
                .setContentText(contentText)
                .setSmallIcon(R.mipmap.ic_launcher_round)
                .setLights(Color.RED, 3000, 3000)
                .setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.alarm))
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);

        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationManager.notify(14, builder.build());
    }
}

3. Complete Your AndroidManifest.xml Configuration

Your provided manifest is truncated—ensure you've registered your FCM services correctly and added all required permissions, including the Android 13+ notification permission:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.ddns.kodiakscloud.fastalker">

    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Required for Android 13+ -->

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- Register Firebase Instance ID Service -->
        <service
            android:name=".FCM_Instance_ID_Service"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>

        <!-- Register Firebase Messaging Service -->
        <service
            android:name=".FCM_Messaging_Service"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        <!-- Default notification channel meta-data -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="FCM_NOTIFICATION_CHANNEL" />

        <!-- Your MainActivity and other components -->
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <!-- Handle click_action from notifications -->
            <intent-filter>
                <action android:name=".MainActivity" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

4. Verify Device-Specific Settings

  • Double-check that your app has notification permissions enabled in the device settings (Settings > Apps > Your App > Notifications)
  • For manufacturers like Xiaomi, Huawei, or Samsung, disable battery optimization for your app (Settings > Battery > Battery Optimization > Select your app > "Don't optimize")—these custom ROMs often restrict background services to save battery.

These changes should ensure notifications are delivered reliably whether your app is in the foreground, background, or fully closed.

内容的提问来源于stack exchange,提问作者Kodiak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:05:51