簡體   English   中英

在Android Oreo版本中沒有收到FCM通知消息?

[英]FCM notification message are not received in android Oreo version?

我已經從服務器向用戶發送FCM通知。 它工作正常(直到api 25),但在奧利奧,當應用程序沒有在后台(服務已關閉)(或)完全關閉。我沒有在這種情況下獲得任何FCM通知,但在Whatsapp工作正常。 這里我附上了FCM代碼

的Manifest.xml

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

    <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">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/ic_stat_ic_notification" />

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/colorAccent" />

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="fcm"/>

        <meta-data android:name="firebase_messaging_auto_init_enabled"
            android:value="false" />

        <meta-data android:name="firebase_analytics_collection_enabled"
            android:value="false" />

    </application>

</manifest>

應用程序/ gradle這個

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.fcm"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.firebase:firebase-messaging:17.1.0'
}

apply plugin: 'com.google.gms.google-services'

MyFirebaseMessagingService.java

package com.fcm;

import android.app.Service;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService
{

    @Override
    public void onNewToken(String s) 
    {
    super.onNewToken(s);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    Log.e("FCM Message Received","You Have FCM Message");
    }
}

MainActivity.java

package com.nexge.fcm;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this,  new OnSuccessListener<InstanceIdResult>() {
            @Override
            public void onSuccess(InstanceIdResult instanceIdResult) {
                String newToken = instanceIdResult.getToken();
                Log.e("newToken",newToken);
            }
        });
    }
}

當您定位到Android 8.0(API級別26)時 ,您必須實現一個或多個通知渠道。 如果您的targetSdkVersion設置為25或更低,當您的應用在Android 8.0(API級別26)或更高版本上運行時,其行為與運行Android 7.1(API級別25)或更低版本的設備上的行為相同。

注意:如果您定位Android 8.0(API級別26)並在未指定通知通道的情況下發布通知,則不會顯示通知,系統會記錄錯誤。

注意:您可以在Android 8.0(API級別26)中啟用新設置,以顯示屏幕警告,當針對Android 8.0(API級別26)的應用嘗試在沒有通知渠道的情況下發布時,該警告會顯示為吐司。 要打開運行Android 8.0(API級別26)的開發設備的設置,請導航到“設置”>“開發人員選項”啟用“顯示通知通道警告”。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
   NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   String id = "id_product";
   // The user-visible name of the channel.
   CharSequence name = "Product";
   // The user-visible description of the channel.
   String description = "Notifications regarding our products";
   int importance = NotificationManager.IMPORTANCE_MAX;
   NotificationChannel mChannel = new NotificationChannel(id, name, importance);
   // Configure the notification channel.
   mChannel.setDescription(description);
   mChannel.enableLights(true);
   // Sets the notification light color for notifications posted to this
   // channel, if the device supports this feature.
   mChannel.setLightColor(Color.RED);
   notificationManager.createNotificationChannel(mChannel);
}

在Android Oreo上創建推送通知

要創建通知,您將使用NotificationCompat.Builder類。 之前使用過的構造函數只將Context作為參數,但在Android O中,構造函數看起來像這樣 -

NotificationCompat.Builder(Context context, String channelId)

以下代碼段將向您展示如何創建通知 -

Intent intent1 = new Intent(getApplicationContext(), Ma

inActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 123, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext(),"id_product")
       .setSmallIcon(R.drawable.flatpnicon) //your app icon
       .setBadgeIconType(R.drawable.flatpnicon) //your app icon
       .setChannelId(id)
       .setContentTitle(extras.get("nt").toString())
       .setAutoCancel(true).setContentIntent(pendingIntent)
       .setNumber(1)
       .setColor(255)
       .setContentText(extras.get("nm").toString())
       .setWhen(System.currentTimeMillis());
notificationManager.notify(1, notificationBuilder.build());

Android O為您提供了一些自定義通知的功能 -

setNumber() - 允許您設置長按菜單中顯示的數字setChannelId() - 允許您在使用舊構造函數setColor()時顯式設置通道ID - 允許RGB值為您設置顏色主題notification setBadgeIconType() - 允許您設置要在長按菜單中顯示的圖標

有關詳細信息, 請查看示例

“從Android 8.0(API級別26)開始,所有通知都必須分配給頻道,否則不會出現。”

現在必須將個別通知放入特定頻道。 參考

選項1 [簡單]更改目標Android版本Android 7.1(API級別25)或更低。

compileSdkVersion 25
    defaultConfig {
        applicationId "com.fcm"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

選項2如果您不想更改目標版本,請按照以下方法操作

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
     NotificationChannel nc = new NotificationChannel(“[enter your product id]”, “[Name]”,NotificationManager.IMPORTANCE_MAX);
     nc.setDescription(“[your description for the notification]”);
     nc.enableLights(true);
     nc.setLightColor(Color.GREEN);
     nm.createNotificationChannel(nc);
  }

使用以下Builder構造函數

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(appContext, [id you mentioned above in constructor of NotificationChannel])

從Builder創建通知

nm.notify("0", notificationBuilder.build())
  notification = new NotificationCompat.Builder(this, ANDROID_CHANNEL_ID)
                    .setSmallIcon(R.drawable.ic_small_logo)
                    .setLargeIcon(picture)
                    .setContentTitle("Title")
                    .setContentText("Body")
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .build();
  • ANDROID_CHANNEL_ID = "CHANNEL_ID"
  • PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • intent = new Intent(getApplicationContext(), HomeActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

您可以使用以下類在android的較低版本和較高版本中生成通知(從4.2(Jelly Bean)到8.1.1(Oreo)測試)。

public final class NotificationHelper extends Thread {

    private Context context;
    private NotificationManager notifManager;
    private NotificationCompat.Builder notification_compact;
    private Notification.Builder notification_builder;
    private int OREO_NOTIFICATION_TYPE = 2; //setting default notificaiton type 2, as 1 is not for constant updating
    //put string channel name and id in **<>**
    private static final String CHANNEL_ONE_ID = "<Your_channel_string_ID>";
    private static final String CHANNEL_ONE_NAME = "<Your channel_String_NAME>";
    private static final String CHANNEL_TWO_ID = "<Your_channel_string_ID_TWO>";
    private static final String CHANNEL_TWO_NAME = "<Your channel_String_NAME_TWO>";
    private String title = "", message = "";


    /**
     * @param context content of activity
     * @param title   title for notification_compact
     * @param message message to show in notification_compact
     */
    public NotificationHelper(Context context, String title, String message) {
        this.context = context;
        this.title = title;
        this.message = message;
        notifManager = getManager();
    }


    @Override
    public void run() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            //do stuff for oreo
            createChannels();
            postNotificationAboveV25(OREO_NOTIFICATION_TYPE, title);
        } else {
            //do stuff for other versions
            postNotificationUptoV25();
        }
    }


    //method to show notificaiton above nougat
    private void postNotificationAboveV25(int id, String title) {
        notification_builder = getNotificatonBuilder(id, title);

        if (notification_builder != null) {
            getManager().notify(id, notification_builder.build());
        }
    }


    //get pending intent to launch activity
    private PendingIntent getPendingIntent() {

        Intent startActivity = context.getPackageManager()
                .getLaunchIntentForPackage(context.getPackageName())
                .setPackage(null)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

        return PendingIntent.getActivity(context, 0, startActivity, 0);

//        Intent resultIntent = new Intent(context, ActionActivity.class);
//        return PendingIntent.getActivity(context, AppHelper.NOTIFICATION_ID, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    }


    //method to get notification builder above nougat
    private Notification.Builder getNotificatonBuilder(int id, String title) {
        switch (id) {
            case 1:
                return notification_builder = getNotification1(title, message);

            case 2:
                return notification_builder = getNotification2(title, message);

            default:
                return notification_builder = getNotification2(title, message);
        }
    }


    //Create the notification_compact that’ll be posted to Channel One
    //use this one if your notification is a type of push notificaiton
    //                              or
    //if you are not updating it in continues intervals like every 4 or 5 seconds(ex. Timer)
    @SuppressLint("NewApi")
    private Notification.Builder getNotification1(String title, String body) {
        return new Notification.Builder(context, CHANNEL_ONE_ID)
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(R.drawable.app_icon)
                .setAutoCancel(true)
                .setTicker(title + AppHelper.getMessage(R.string.started))
                .setColor(AppHelper.getColor(context, R.color.colorPrimary))
                .setContentIntent(getPendingIntent());
    }


    //Create the notification_compact that’ll be posted to Channel Two
    //use this for continues intervals or updating continuesly
    @SuppressLint("NewApi")
    private Notification.Builder getNotification2(String title, String body) {
        return new Notification.Builder(context, CHANNEL_TWO_ID)
                .setContentTitle(title)
                .setContentText(body)
                .setTicker(title + AppHelper.getMessage(R.string.started))
                .setSmallIcon(R.drawable.app_icon)
                .setAutoCancel(true)
                .setColor(AppHelper.getColor(context, R.color.colorPrimary))
                .setContentIntent(getPendingIntent());
    }


    //method to post notification upto Nougat i.e., below api level 26
    @SuppressLint("NewApi")
    private void postNotificationUptoV25() {
        notification_compact = new NotificationCompat.Builder(context);
        notification_compact.setAutoCancel(true);
        notification_compact.setSmallIcon(R.drawable.app_icon);
        notification_compact.setTicker(title + AppHelper.getMessage(R.string.started));
        notification_compact.setContentTitle(title);
        notification_compact.setContentText(message);
        notification_compact.setColor(AppHelper.getColor(context, R.color.colorPrimary));
        notification_compact.setContentIntent(getPendingIntent());
//        notification_compact.setWhen(1506067106762L);

        getManager().notify(AppHelper.NOTIFICATION_ID, notification_compact.build());
    }


    //method to update notification
    public void updateNotification(String time) {

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            //update above NOUGAT V25
            if (notification_builder != null) {
                notification_builder.setContentText(message + "  " + time);
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_builder.build());
            }
        } else {
            //update below NOUGAT V25
            if (notification_compact != null) {
                notification_compact.setContentText(message + "  " + time);
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_compact.build());
            }
        }
    }

    //method to update remainting notification
    public void updateRemainingNotification(String time) {

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            //update above NOUGAT V25
            if (notification_builder != null) {
                notification_builder.setContentText(time + AppHelper.getMessage(R.string.remaining));
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_builder.build());
            }
        } else {
            //update below NOUGAT V25
            if (notification_compact != null) {
                notification_compact.setContentText(time + AppHelper.getMessage(R.string.remaining));
                getManager().notify(AppHelper.NOTIFICATION_ID, notification_compact.build());
            }
        }
    }


    //method to create channels which is necessary above Nougat(API - 25) i.e., at Oreo(API - 26)
    @SuppressLint("NewApi")
    private void createChannels() {

        NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
                CHANNEL_ONE_NAME, notifManager.IMPORTANCE_DEFAULT);
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.setShowBadge(true);
        notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        getManager().createNotificationChannel(notificationChannel);

        NotificationChannel notificationChannel2 = new NotificationChannel(CHANNEL_TWO_ID,
                CHANNEL_TWO_NAME, notifManager.IMPORTANCE_DEFAULT);
        notificationChannel2.enableLights(false);
        notificationChannel2.enableVibration(true);
        notificationChannel2.setLightColor(Color.RED);
        notificationChannel2.setShowBadge(false);
        getManager().createNotificationChannel(notificationChannel2);

    }


    //method to get Object of Notification Manager
    private NotificationManager getManager() {
        if (notifManager == null)
            notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        return notifManager;
    }


    /**
     * call this method to destroy notification
     */
    public void destroyNotification() {
        if (notifManager != null)
            notifManager.cancel(AppHelper.NOTIFICATION_ID);
    }
}

只需使用上下文和消息來從FCM調用此類。 作為一個線程類,您也可以不斷更新通知。

當你的工作結束時,不要忘記調用destroyNotification()方法。

您可以根據需要發現並進行更改

在oreo版本中無法在沒有Channel的情況下添加通知,因此需要在firebase通知中添加以下代碼,無需通道的oreo通知服務類無法發送通知:

private void sendMyNotification(String message,String title) {
    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    Intent intent = new Intent(this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    Uri soundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        @SuppressLint("WrongConstant")
        NotificationChannel notificationChannel=new NotificationChannel("my_notification","n_channel",NotificationManager.IMPORTANCE_MAX);
        notificationChannel.setDescription("description");
        notificationChannel.setName("Channel Name");
        notificationManager.createNotificationChannel(notificationChannel);
    }
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.listlogo)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.tlogo))
                .setContentTitle(title)
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(soundUri)
                .setContentIntent(pendingIntent)
                .setDefaults(Notification.DEFAULT_ALL)
                .setPriority(NotificationManager.IMPORTANCE_MAX)
                .setOnlyAlertOnce(true)
                .setChannelId("my_notification")
                .setColor(Color.parseColor("#3F5996"));
        //.setProgress(100,50,false);
        notificationManager.notify(0, notificationBuilder.build());
}

然后你在json中發送沒有data{}對象的通知。 這是一個舊的錯誤(?)或者應該像那樣工作。 如果您的通知中沒有任何數據,那么當您的應用處於前台時,您將不會觸發通知。

示例json:

"notification":
{
  "title": "notification_title",
  "body": "notification_body"
},

"data":
{
  "example":"hey",
  "example2":"you need me."
},

"priority" : "high",

"registration_ids":
[
  "crYjxvFkASE:APA91bGv4GWj9erJ6LsblEzpag5ObkcESEsBthxsJObJ38DhZ3GbSMLlGQK3qS_qvUvrcrg_cqBgCWhBeq1X2wgxO7gmcc_gW0jM4qZYYugF5wraTHwvDKNnjQwn8dpyGEbFMXLOCvE9"
]

只有數據通知在android Oreo上處理

嘗試刪除通知

`
 remove this key notification 
 {"notification":
 {
  "title": "notification_title",
  "body": "notification_body"
 },
 // keep only the data key 
  "data":
 {
  "example":"hey",
  "example2":"you need me."
 },

 "priority" : "high",

 "registration_ids":
    []


`

當應用程序處於后台時...如果有效負載包含通知密鑰和數據密鑰,則不會調用onRecievedMessage。

所以刪除通知..只保留數據密鑰..它將運作良好

private void generateNotification(String message, String title) {

    Intent intent = new Intent(getApplicationContext(), ActitivtyNotification.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.stkfood_logo)  //a resource for your custom small icon
            .setContentTitle(title) //the "title" value you sent in your notification
            .setContentText(message) //ditto
            .setAutoCancel(true)  //dismisses the notification on click
            .setSound(defaultSoundUri);

    //Setting up Notification channels for android O and above
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel notificationChannel = new NotificationChannel("3", "CHANNEL_NAME", importance);
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.enableVibration(true);
        notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
        assert mNotificationManager != null;
        notificationBuilder.setChannelId("3");
        mNotificationManager.createNotificationChannel(notificationChannel);
    }
    PendingIntent contentIntent = PendingIntent.getActivity(this, 3, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    notificationBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(3, notificationBuilder.build());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM