在Android项目中使用FCM(FirebaeCloudMessage)

时间:2022-08-21 08:51:03

What

FCM是GCM的升级版本(Google 官方说法),是一种消息推送框架。

Why

使用FCM进行推送,与GCM相比,功能相同,但是FCM支持从FirebaseConsole发送通知,而GCM不能再控制台发送通知。

How

1.在Firebase中建立想要推送功能的App

在Android项目中使用FCM(FirebaeCloudMessage)

2.下载google-services.json文件,并将文件放置在app目录下

说明:如果要在不同buildType或者productFlavors下区分不同的json文件,请建立对应的文件夹,并将json文件cpoy至对应文件夹的根目录下

在Android项目中使用FCM(FirebaeCloudMessage)

  • 不同的buildType时
// dogfood and release are build types.
app/
google-services.json
src/dogfood/google-services.json
src/release/google-services.json
...
  • 不同的productFlavors时
// free and paid are product flavors.
app/
google-services.json
src/dogfood/paid/google-services.json
src/release/free/google-services.json
...

3.加入Firebase需要的包

  • 在Project-level的build.gradle中加入:
buildscript {
dependencies {
...
classpath 'com.google.gms:google-services:3.0.0'
...
}
}
  • 在Module-level的build.gradle中加入:
android {
...
}

dependencies {
//版本可能更新,请自行修改
...
compile 'com.google.firebase:firebase-core:10.2.1'
compile 'com.google.firebase:firebase-messaging:10.2.1'
...
}

//在最后一行添加
apply plugin: 'com.google.gms.google-services'

4.添加FCM相关服务

  • 新建MyFirebaseMessagingService,通过继承FirebaseMessagingService实现接受服务
public class MyFirebaseMessagingService extends FirebaseMessagingService{

private static final String TAG = "Fireabse Cloud Message";

/**
* Called when message is received.
*
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/

// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e("receive", "receive");
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]

// TODO(developer): Handle FCM messages here.
// Not getting messages here? See why this may be: https://goo.gl/39bRNJ
Log.d(TAG, "From: " + remoteMessage.getFrom());

// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());

if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}

}

// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}

// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
sendNotification(remoteMessage.getNotification().getBody());
}
// [END receive_message]

/**
* Schedule a job using FirebaseJobDispatcher.
*/

private void scheduleJob() {
/*
// [START dispatch_job]
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("my-job-tag")
.build();
dispatcher.schedule(myJob);
// [END dispatch_job]
*/

}

/**
* Handle time allotted to BroadcastReceivers.
*/

private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}

/**
* Create and show a simple notification containing the received FCM message.
*
* @param messageBody FCM message body received.
*/

private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);

Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
  • 新建MyFirebaseInstanceIDService,通过继承FirebaseInstanceIDService实现设备Token的获取。
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService{


private static final String TAG = "FCM Token";

@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);

// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}

private void sendRegistrationToServer(String token){
//// TODO: upload your token
}
}

5.在manifest文件中声明服务

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

<service
android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>

6.在manifest文件中设置当App后天运行时接收Notification样式

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/study" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />

7.使用注意问题:

7.1 程序前台运行

程序前台运行时,接受到通知会走MyFirebaseMessagingService的onMessageReceived方法,此时,可以自定义处理。

7.2 程序后台运行

程序后台运行时接收到通知,不会走MyFirebaseMessagingService的onMessageReceived方法,而是显示在系统托盘中,此时点击通知,会打开App中的默认启动Activity,并将数据放在Intent的extras中传送。

  • 如何处理数据?
    可以在创建Activity时获取数据,然后进行处理
  • 当程序后台时,接收到了多个Notification时,如何处理?
    当收到多个通知时,如果Activity不是SingleTopSingleTaskSingleInstance,每点击一次通知,就会创建一个Activity,可以在Intent中获取数据。如果是另外三种方式,可以通过newIntent方法回调获取intent中的数据。