[英]Firebase FCM Notification issue in OREO version Android Phone
[英]FCM notification message are not received in android Oreo version?
我已經從服務器向用戶發送FCM通知。 它工作正常(直到api 25),但在奧利奧,當應用程序沒有在后台(服務已關閉)(或)完全關閉。我沒有在這種情況下獲得任何FCM通知,但在Whatsapp工作正常。 這里我附上了FCM代碼
<?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'
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");
}
}
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.