我已经从服务器向用户发送了FCM通知。它工作正常(直到 api 25),但在奥利奥,当应用程序不在后台(服务关闭)(或)完全关闭时。在这种情况下,我没有收到任何FCM通知,但在Whatsapp中工作正常。 在这里我附上了 FCM 代码
清单.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>
应用/格拉德尔
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");
}
}
主要活动.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);
}
在安卓奥利奥上创建推送通知
若要创建通知,将使用 NotificationCompat.Builder 类。之前使用的构造函数仅将上下文作为参数,但在 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()– 如果您使用的是旧构造函数,则允许您显式设置通道 IDsetColor()– 允许 RGB 值为您的通知放置颜色主题setBadgeIconType()– 允许您设置要在长按菜单中显示的图标
有关更多信息,请在此处查看示例
"从 Android 8.0(API 级别 26)开始,所有通知都必须分配给一个频道,否则它将不会显示。
现在必须将单个通知放在特定频道中。(参考资料)
选项 1 [简单]更改目标安卓版本 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);
}
使用以下生成器构造函数
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(appContext, [id you mentioned above in constructor of NotificationChannel])
从构建器创建通知
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);
您可以使用下面的类在安卓的低版本和上版本中生成通知(从4.2(果冻豆)到8.1.1(奥利奥)测试)。
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 调用这个类,带有上下文和 msg。 由于它是一个线程类,因此您也可以不断更新通知。
不要忘记在工作结束时调用destroyNotification()方法。
您可以根据需要发现并进行更改
在奥利奥版本中无法添加没有频道的通知,因此需要在Firebase通知中添加以下代码 没有频道的奥利奥通知的服务类无法发送通知:
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());
}
然后,您将发送通知data{}
而不会在 json 中对象。这是一个老错误(?)或者应该像那样工作。如果通知中没有任何数据,则在应用处于前台时不会触发通知。
示例 json:
"notification":
{
"title": "notification_title",
"body": "notification_body"
},
"data":
{
"example":"hey",
"example2":"you need me."
},
"priority" : "high",
"registration_ids":
[
"crYjxvFkASE:APA91bGv4GWj9erJ6LsblEzpag5ObkcESEsBthxsJObJ38DhZ3GbSMLlGQK3qS_qvUvrcrg_cqBgCWhBeq1X2wgxO7gmcc_gW0jM4qZYYugF5wraTHwvDKNnjQwn8dpyGEbFMXLOCvE9"
]
在安卓奥利奥上只处理数据通知
尝试删除通知
`
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..
所以删除通知..只保留数据密钥..它会很好地工作
您需要广告权限并创建通知渠道
public static void createChannelAndHandleNotifications(Context context) {
ctx = context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(NOTIFICATION_CHANNEL_DESCRIPTION);
channel.setShowBadge(true);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
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());
}