Firebase(FCM)によるプッシュ通知実装から動作確認まで一通り載せてあります。
手順通りに行えれば、動作確認まで行えますので是非試してください。
目次 [非表示]
Firebaseの設定
Firebaseのプッシュ通知を行うには、Firebaseプロジェクトの作成とプッシュ通知アプリの作成&設定を行う必要があります。また、プッシュ通知を送るためのサーバーキーを取得する必要あります。
Firebaseプロジェクトの作成
https://console.firebase.google.com/にアクセス
- 新規プロジェクトを作成押下
- 必要項目を入力し、プロジェクトを作成押下
Androidアプリ作成と設定
サーバーキーの確認
ソースコードの実装
Firebaseの実装を手順を説明します。
google-service.jsonの設置
- ダウンロードしてきたgoogle-service.jsonをpj/app直下に設置
build.gradleの記載
pj/build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
- google-servicesのclasspathを定義(10行目)
pj/app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
def PACKAGE_NAME = "com.test.notification"
android {
compileSdkVersion 24
buildToolsVersion "23.0.3"
defaultConfig {
applicationId PACKAGE_NAME
minSdkVersion 19
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
testCompile 'junit:junit:4.12'
compile 'com.google.firebase:firebase-messaging:9.0.1'
}
- google-servicesのapply pluginを定義(3行目)
- 実際のプロジェクトがFirebaseで定義したパッケージ名と違う場合は、パッケージ名を再定義(4行目,10行目)
- firebaseを使うためにcompileを定義(33行目)
javaの実装
TestFirebaseInstanceIdService.java
package jp.co.sample.notificationtest;
import android.content.Intent;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class TestFirebaseInstanceIdService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
super.onTokenRefresh();
sendRegistrationToServer();
}
private void sendRegistrationToServer() {
// Add custom implementation, as needed.
startService(new Intent(this, RegistrationIntentService.class));
}
}
- FirebaseInstanceIdServiceはトークンのリフレッシュが来た場合に自動で呼び出される。ここでサーバーへの登録を依頼処理を追加(16行目)
RegistrationIntentService.java
package jp.co.sample.notificationtest;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
public class RegistrationIntentService extends IntentService {
public RegistrationIntentService() {
super("RegistrationIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
String token = FirebaseInstanceId.getInstance().getToken();
Log.d("###", "token = " + token);
insertServer(token);
}
private void insertServer(String token) {
// サーバーへ登録
}
}
- IntentServiceでサーバーへの登録を実装をする。起動時orログイン時で任意の呼び出しとトークンリフレッシュ時の自動呼び出しの計2ヶ所から呼び出される。
- 動作確認のため、トークンをログに出す(17行目)
TestFirebaseMessagingService.java
package jp.co.sample.notificationtest;
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.text.TextUtils;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.Map;
public class TestFirebaseMessagingService extends FirebaseMessagingService {
private static final String EXTRA_URL = "url";
private static final String EXTRA_TITLE = "title";
private static final String EXTRA_MESSAGE = "message";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Map<String, String> data = remoteMessage.getData();
if(TextUtils.isEmpty(data.get(EXTRA_MESSAGE))) return;
if(TextUtils.isEmpty(data.get(EXTRA_TITLE))) data.put(EXTRA_TITLE,getResources().getString(R.string.app_name));
sendNotification(data);
}
private void sendNotification(Map<String, String> data) {
// 履歴削除,activity再利用
final Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.putExtra(MainActivity.EXTRA_NOTIFY_URL, data.get(EXTRA_URL));
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
final Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
android.support.v4.app.NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(data.get(EXTRA_TITLE))
.setContentText(data.get(EXTRA_MESSAGE))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(contentIntent);
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
final int notifyId = getNotifyId();
notificationManager.notify(notifyId, builder.build());
}
// notification複数表示
private int getNotifyId() {
Calendar calendar = Calendar.getInstance();
return Integer.parseInt(new SimpleDateFormat("ddHHmmss", Locale.JAPAN).format(calendar.getTime()));
}
}
- FirebaseMessagingServiceはプッシュ通知受信用のクラスである。ここでNotificationを実装する。
MainActivity.java
package jp.co.sample.notificationtest;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
public static final String EXTRA_NOTIFY_URL = "url";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
// 起動時にサーバー送信
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
- 起動時にサーバーへのトークンを送信する(33~35行目)
仕様によってサーバーへの登録タイミングは違うのでお好みのタイミングで実装をする。
AndroidManifest.xmlの記載
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="jp.co.sample.notificationtest"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".TestFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".TestFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name=".RegistrationIntentService"/>
</application>
</manifest>
- javaで定義したserviceを全て定義する(23~35行目)
動作確認
アプリ実行後ログからトークンを確認し、DHCで動作確認を行います。
DHCはChromeのアドオンで、Chromeウェブストアで「DHC REST Client」を検索してインストールしてください。
トークン取得
DHCによるサーバー送信
REQUEST:HTTP、fcm.googleapis.com/fcm/send、POST
- HEADERS:Authorization、key=Firebaseで確認したサーバーキー
- HEADERS:Content-Type、application/json
- BODY:JSONを入力する。toはアプリログで確認したトークンを入力。toの後ろに”,”があるので入れ忘れないこと
- Sendを押下で送信
最後に
Googleのプッシュ通知に歴史はC2DM->GCM->GCM 3.0->FCMの順に進化してきました。
過去のプッシュ通知は全て実装してきましたが、本当に楽になったと感じます。
みなさんもぜひこの機会にプッシュ通知を試してください。