在Android項(xiàng)目中使用FCM(FirebaseCloudMessage)

FCM簡(jiǎn)介

1. FCM是Google的GCM升級(jí)版的一種消息推送框架(官方網(wǎng)站)
2. FCM可以在官方網(wǎng)站的控制臺(tái)Firebase console上發(fā)送通知肄梨,但是GCM不能(需要在官方網(wǎng)站添加上你的應(yīng)用才可以登陸到控制臺(tái))

FCM使用前提

  • 設(shè)備必須是android4.0以上,Google Play Services 必須是 11.2.0以上版本
  • Android SDK Manager 必須有Google Play services SDK
  • Android Studio必須是1.5以上版本

FCM接入

官方接入文檔

  • 下載google-services.json文件念祭,并將文件放置在app目錄下
說(shuō)明:如果要在不同buildType或者productFlavors下區(qū)分不同的json文件,請(qǐng)建立對(duì)應(yīng)的文件夾湾盗,并將json文件copy至對(duì)應(yīng)文件夾的根目錄下
 不同的buildType時(shí) 
 // dogfood and release are build types.
app/
google-services.json
src/dogfood/google-services.json
src/release/google-services.json
...

不同的productFlavors時(shí)
// free and paid are product flavors.
app/
google-services.json
src/dogfood/paid/google-services.json
src/release/free/google-services.json
...
  • 加入FCM需要的插件和依賴
  1. 在工程級(jí)別(Project-level)的build.gradle中加入:
buildscript {    
    repositories {
        jcenter()
        google() // 必填項(xiàng)(gradle plugin 3.x以上) 
        或者
        maven { url 'https://maven.google.com' } // 必填項(xiàng)
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.0' // gradle pulagin 版本
        classpath 'com.google.gms:google-services:3.1.0' // service 插件的版本(最新參考官網(wǎng))
    }
}

allprojects {
    repositories {
        jcenter()
        google() // 必填項(xiàng)(gradle plugin 3.x以上) 
        或者
        maven { url 'https://maven.google.com' } // 必填項(xiàng)
    }
}
  1. 在項(xiàng)目級(jí)別(Model-level)的build-gradle中加入:
apply plugin: 'com.android.application'

android {
      ...
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    ...
    implementation 'com.google.firebase:firebase-messaging:12.0.1' // FCM推送使用的依賴
}

apply plugin: 'com.google.gms.google-services' 
// 必須要放在最后你辣,不然會(huì)報(bào)錯(cuò):Please fix the version conflict either by updating the version of the google-services plugin (information about the latest version is available at https://bintray.com/android/android-tools/com.google.gms.google-services/) or updating the version of com.google.android.gms to X.X.X.

如果引用了Google其他服務(wù),比如google地圖拦盹,那么需要版本一致

//下方的firebase-messaging 和 play-services-maps 和 play-services版本號(hào)必須一致
    compile 'com.google.firebase:firebase-messaging:11.2.0'
    compile 'com.google.android.gms:play-services-maps:11.2.0'
    compile 'com.google.android.gms:play-services:11.2.0'
    compile 'com.google.gms:google-services:3.1.0'
  • 添加FCM相關(guān)的服務(wù)
  1. 創(chuàng)建FCMMessagingService,繼承FirebaseMessagingService
public class FCMMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        if (remoteMessage.getNotification() != null && remoteMessage.getNotification().getBody() != null) {
            sendNotification(getApplicationContext(), remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
        } else {
            sendNotification(getApplicationContext(), remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
        }
    }

    @Override
    public void onDeletedMessages() {
        super.onDeletedMessages();
    }

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

    @Override
    public void onSendError(String s, Exception e) {
        super.onSendError(s, e);
    }

    private void sendNotification(Context iContext, String messageTitle, String messageBody) {

        NotificationManager notificationManager = (NotificationManager) iContext.getSystemService(Context.NOTIFICATION_SERVICE);
        Intent intent = new Intent(this, MessageActivity.class); // 接收到通知后鹃祖,點(diǎn)擊通知,啟動(dòng) MessageActivity

        PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        long[] pattern = {500,500,500,500,500};
        NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(),"-1")
                .setTicker(messageTitle)
                .setSmallIcon(R.drawable.ic_stat_notify)
                .setContentTitle("push 通知 標(biāo)題")
                .setAutoCancel(true)
                .setContentText(messageBody)
                .setWhen(System.currentTimeMillis())
                .setVibrate(pattern)
                .setLights(Color.BLUE, 1, 1)
        builder.setDefaults(NotificationCompat.DEFAULT_SOUND | NotificationCompat.DEFAULT_VIBRATE);

        builder.setContentIntent(pendingIntent);
//        builder.setFullScreenIntent(pendingIntent, true);//將一個(gè)Notification變成懸掛式Notification

        if (notificationManager != null) {
            notificationManager.notify(0, builder.build());
        }
    }
}
  1. 創(chuàng)建FCMInstanceIDService,繼承FirebaseInstanceIdService普舆,參考官網(wǎng)
唯一Token的獲取和上傳

最初啟動(dòng)您的應(yīng)用時(shí)恬口,F(xiàn)CM SDK 會(huì)為客戶端應(yīng)用實(shí)例生成一個(gè)注冊(cè)令牌。如果您希望定位單臺(tái)設(shè)備或創(chuàng)建設(shè)備組沼侣,則需要通過(guò)繼承 FirebaseInstanceIdService
來(lái)訪問(wèn)此令牌祖能。
當(dāng)您需要檢索當(dāng)前令牌時(shí),請(qǐng)調(diào)用 FirebaseInstanceId.getInstance().getToken()
如果令牌尚未生成华临,此方法將返回 null芯杀。

public class FCMInstanceIDService extends FirebaseInstanceIdService {

    @Override
    public void onTokenRefresh() {
        super.onTokenRefresh();
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.v("FCM----", refreshedToken);
        sendRefreshToken(refreshedToken);
    }

    public void sendRefreshTokenToService(String refreshedToken){
        //這里是往自己app應(yīng)用的后臺(tái)發(fā)送刷新refreshedToken的api
    }
}

Firebase建議我們復(fù)寫onTokenRefresh方法并且及時(shí)上傳更新的Token通知App服務(wù)器

  1. 注冊(cè)Service
        <service android:name=".FCMInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>

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

        <!-- 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/ic_stat_notify" />
        <!-- 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" />

  • 需要注意的問(wèn)題
  1. FCM有兩種消息

1.1 顯示消息:僅當(dāng)應(yīng)用處于前臺(tái)時(shí),消息才會(huì)觸發(fā) onMessageReceived() 回調(diào)
1.2 數(shù)據(jù)消息:程序后臺(tái)運(yùn)行時(shí)接收到通知雅潭,不會(huì)走FirebaseMessagingService的 onMessageReceived() 方法揭厚,而是顯示在系統(tǒng)托盤中,此時(shí)點(diǎn)擊通知扶供,會(huì)打開App中的默認(rèn)啟動(dòng)Activity筛圆,并將數(shù)據(jù)放在Intent的extras中傳送。

所以如果app處于后臺(tái)或者被killed椿浓,想要點(diǎn)擊通知顯示MessageActivity太援,可以這樣做:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (getIntent().getExtras() != null) {
            for (String s : getIntent().getExtras().keySet()) {
                Log.d("MainActivity", s + "--" + getIntent().getExtras().get(s)); 
            // 在官網(wǎng)的發(fā)送notification 使用高級(jí)選項(xiàng)可以自定義 鍵值對(duì),最終會(huì)在getIntent().getExtras()中獲取到
            }
            Intent intent = new Intent(this, MessageActivity.class);
            startActivity(intent);
        }
    }
}

使用FCM云消息推送

目標(biāo)分為三種:

  • 用戶細(xì)分--->對(duì)所有安裝過(guò)程序的client端進(jìn)行發(fā)送推送
  • 主 題--->官方鏈接
  • 單個(gè)設(shè)備--->對(duì)指定的Client進(jìn)行發(fā)送扳碍,需要一個(gè)FCM注冊(cè)令牌提岔,程序運(yùn)行起來(lái)時(shí),通過(guò)FirebaseInstanceId.getInstance().getToken()獲得笋敞,設(shè)置進(jìn)去即可
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碱蒙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赛惩,老刑警劉巖哀墓,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異喷兼,居然都是意外死亡篮绰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門季惯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吠各,“玉大人,你說(shuō)我怎么就攤上這事勉抓∽吣酰” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵琳状,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我盒齿,道長(zhǎng)念逞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任边翁,我火速辦了婚禮翎承,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘符匾。我一直安慰自己叨咖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布啊胶。 她就那樣靜靜地躺著甸各,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焰坪。 梳的紋絲不亂的頭發(fā)上趣倾,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音某饰,去河邊找鬼儒恋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛黔漂,可吹牛的內(nèi)容都是我干的诫尽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼炬守,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼牧嫉!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起劳较,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驹止,失蹤者是張志新(化名)和其女友劉穎浩聋,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體臊恋,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衣洁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抖仅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坊夫。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖撤卢,靈堂內(nèi)的尸體忽然破棺而出环凿,到底是詐尸還是另有隱情,我是刑警寧澤放吩,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布智听,位于F島的核電站,受9級(jí)特大地震影響渡紫,放射性物質(zhì)發(fā)生泄漏到推。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一惕澎、第九天 我趴在偏房一處隱蔽的房頂上張望莉测。 院中可真熱鬧,春花似錦唧喉、人聲如沸捣卤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)董朝。三九已至,卻和暖如春干跛,著一層夾襖步出監(jiān)牢的瞬間益涧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工驯鳖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闲询,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓浅辙,卻偏偏與公主長(zhǎng)得像扭弧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子记舆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,501評(píng)論 25 707
  • FCM鸽捻,即Firebase Cloud Messaging Firebase,F(xiàn)irebase是一家實(shí)時(shí)后端數(shù)據(jù)庫(kù)...
    阿敏其人閱讀 34,712評(píng)論 4 15
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)御蒲,斷路器衣赶,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 六豐商城提示:減了一年的肥過(guò)年的幾天全給增回來(lái)了有木有?每天的大魚大肉讓自己的身體多少有些吃不消府瞄,這個(gè)時(shí)候...
    nongyedianshang閱讀 310評(píng)論 0 0
  • 今年的6月份,有之前一段時(shí)間的積累碘箍。積累指的是(閱讀了幾本影響思維模式的書)幾乎顛覆了之前我對(duì)事物認(rèn)知的很多觀點(diǎn)遵馆,...
    定見閱讀 92評(píng)論 0 0