FCM Firebase cloud message

1 篇文章 / 0 new
FCM Firebase cloud message
► API 註冊與取得相關 key
前往  FireBase 登入, 並建立專案以取得相關所需 key
► 需要套件
Android Studio 提供引入為 aar, Eclipse 可至網站下載相關jar,下載 Google Firebase libraries for Eclipse 
► 權限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="tw.shioulo.fcm.test.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="PackageName.permission.C2D_MESSAGE" />
► 相關宣告
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
    android:exported="true" android:permission="com.google.android.c2dm.permission.SEND" >
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="PackageName" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="true" />
    <meta-data android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
► 程式
protected void onCreate(Bundle savedInstanceState) {
    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("dd", "Key: " + key + " Value: " + value);
    //參數資料來自 firebase 後台的 <strong>google-services.json</strong>
    if(FirebaseApp.getApps(this).isEmpty()) {
        FirebaseOptions.Builder builder = new FirebaseOptions.Builder();
        FirebaseOptions options = builder.build();
        FirebaseApp.initializeApp(this, options);
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
MyFirebaseInstanceIDService 當token初次產生或異動時觸發
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
    // [START refresh_token]
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d("dd", "[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.
    // [END refresh_token]
     * Persist token to third-party servers.
     * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
    private void sendRegistrationToServer(String token) {
        // TODO: Implement this method to send token to your app server.
MyFirebaseMessagingService 收到推播訊息時觸發, 但又會因訊息格式及app是否處於前景狀態而有所差異
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "dd";
    //Called when message is received.
    // [START receive_message]
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // [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]
        // 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]: " + remoteMessage.getData());
            String data = remoteMessage.getData().get("message");
            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.
            } else {// Handle message within 10 seconds
        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            RemoteMessage.Notification noti = remoteMessage.getNotification();
            String body = noti.getBody();
            String title = noti.getTitle();
            Log.d(TAG, "[Message Notification]:  Body=" + noti.getBody());
            //sendNotification(title, body);
        // 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.
    // [END receive_message]
    //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.
    private void sendNotification(String title, String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        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)
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
► PHP Server
#API access key from Google API's Console
$id = 'eYyA5XLg.................................eIvsiTPil4OOJD';
// API access key from Google API's Console
define( 'API_ACCESS_KEY', 'AAAAvans6KI:APA91......................SBB8VgU' );
$registrationIds = array($id); //$id is string not array
// prep the bundle
//讓 android 主動發出通知訊息用
$notification = array
    'title' => '標題title', 'body' => '內容body', 'icon' => 'logo',
    'sound' => 'default', 'tag' => 'tag', 'color' => '#ffffff'
$data = array
    'message' => 'message body',
    'click_action' => "PUSH_INTENT"
$fields = array
    'registration_ids'  => $registrationIds,
    'notification'      => $notification,
    'data'              => $data,
    'priority'          => 'normal'
$headers = array
    'Authorization: key=' . API_ACCESS_KEY,
    'Content-Type: application/json'
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
echo $result;
► android 觸發說明
server端推播資料是否包含 'notification' => $notification 這組資料對 android client將有所影響,
若 app處於背景狀態下, 則系統會主動發出通知訊息告知使用者, 但onMessageReceived()不會觸發, 直到使用者點選訊息啟動 app時則 $data 的資料會封裝在 intent 內供程式讀取.
若 app處於前景狀態下, 系統不會主動發出通知, 但 onMessageReceived()則會被觸發供程式處理.
則 onMessageReceived()不論 app在前景或背景均會被觸發, 是否發出通知訊息則需自行處理.
Free Web Hosting