New Project > Empty Views Activity 선택
Language : Java
Minimum SDK : API 24
이 상태로 진행하였습니다.
build.gradle 수정 (프로젝트 수준)
아래 내용을 파일에 추가 합니다.
...
buildscript { dependencies { classpath("com.google.gms:google-services:4.4.2") } } |
build.gradle 수정 (앱 수준)
아래 내용을 추가 합니다.
중간에 주석 부분도 추가해줍니다. 없을 경우 바로 아랫줄에 구문 에러 메세지가 출력됩니다.
plugins { alias(libs.plugins.android.application) id("com.google.gms.google-services") }
...
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:2.0.4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation(platform("com.google.firebase:firebase-bom:33.6.0")) implementation("com.google.firebase:firebase-analytics") implementation("com.google.firebase:firebase-messaging:24.1.0") implementation("com.google.firebase:firebase-core:21.1.1") } |
google-services.json 생성
Firebase console 페이지에 접근해서 프로젝트에 APP 을 추가합니다.
추가하는 과정에서 google-services.json 파일을 다운로드 받을 수 있으며,
해당 파일은 app 디렉토리 안에 넣어 놓습니다.
build.gradle 페이지에서 [Sync Now] 버튼을 눌러줍니다.
MyFirebaseMessagingService.java 생성
package kr.sysdocu.fcm;
import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences;
import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat;
import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage;
import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override public void onNewToken(@NonNull String token) { super.onNewToken(token); // token을 서버로 전송해서 저장하고 싶은 경우 이곳에 코드 입력 }
@Override public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage);
String messageContent;
// 푸시 메시지 데이터 처리 if (!remoteMessage.getData().isEmpty()) { // Data Payload 처리 messageContent = remoteMessage.getData().get("message"); String title = remoteMessage.getData().get("title"); showNotification(title, messageContent); // 아래에서 정의한 알람을 실행하는 부분 } else if (remoteMessage.getNotification() != null) { // Notification Payload 처리 messageContent = remoteMessage.getNotification().getBody(); } else { messageContent = "No Content"; }
}
// 알람을 띄운다 private void showNotification(String title, String message) { NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "default_channel_id";
// Android 8.0 (API 26) 이상에서는 알림 채널을 생성해야 함 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( channelId, "Default Channel", NotificationManager.IMPORTANCE_DEFAULT ); notificationManager.createNotificationChannel(channel); }
// 알림 클릭 시 실행할 Intent 정의 Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 기존 Activity 스택 제거 후 실행
// PendingIntent 생성 PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE // 최신 상태 유지 );
// 알림 빌더 구성 NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId) .setContentTitle(title) // 알림 제목 .setContentText(message) // 알림 메시지 .setSmallIcon(R.drawable.ic_icon) // 알림 아이콘 .setAutoCancel(true) // 알림 터치 후 제거 .setContentIntent(pendingIntent); // 알림 클릭 시 실행될 PendingIntent 설정
// 알림 표시 notificationManager.notify(0, notificationBuilder.build()); }
} |
MainActivity.java 수정
여기에서 코드를 작성할때 파란색 부분은 okhttp 라이브러리를 이용해 토큰을 웹서버로 전송하기 위한 부분입니다.
필요시 같이 작성하면 됩니다.
앱수준 build.gradle 파일에 dependencies 추가후 sync 맞추기
implementation("com.squareup.okhttp3:okhttp:4.11.0")
package kr.sysdocu.fcm;
import android.os.Bundle; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.messaging.FirebaseMessaging;
public class MainActivity extends AppCompatActivity {
private final OkHttpClient client = new OkHttpClient();
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
// 이 안의 부분은 처음 토큰을 받아올때 한 번만 실행 됩니다. FirebaseMessaging.getInstance().getToken().addOnSuccessListener(new OnSuccessListener<String>() { @Override public void onSuccess(String token) {
// 토큰을 토스트로 간단히 확인 Toast toast = Toast.makeText(getApplicationContext(), "TOKEN : " + token, Toast.LENGTH_LONG); toast.show();
// 서버로 토큰 전송 (ssl 사용) new Thread(() -> { try { String url = "https://fcm.sysdocu.kr/register.html?token=" + token; String result = run(url); // 결과 처리 (예: 로그 출력) System.out.println(result); } catch (IOException e) { e.printStackTrace(); } }).start();
} }); }
// okhttp 라이브러리 사용 // run 메서드는 클래스 수준에 정의해야 합니다. public String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } }
} |
activity_main.xml 수정
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="#DFE5E5" tools:context=".MainActivity">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:textColor="@color/black" android:text="토큰은 웹서버에서 확인하세요." />
</LinearLayout> |
AndroidManifest.xml
아래 내용을 추가합니다.
(생략)
<uses-permission android:name="android.permission.INTERNET"/>
...
// <application> 안에 아래 내용 추가
<service android:name=".MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service>
(생략) |
프로젝트를 빌드하여 apk 파일을 생성하고, 핸드폰에 설치합니다.
잠깐, 앱을 실행하기 전에 아래 내용 확인해주세요.
위 소스에서 사용되었던 서버 URL (https://fcm.sysdocu.kr/register.html) 에 해당되는 파일을 미리 생성해 놓도록 합니다.
access log 에 접근 로그가 남아 token 확인을 쉽게하기 위함이니 빈 파일도 괜찮습니다.
PUSH 발송 테스트
방법1)
Firebase Console 에서 프로젝트 선택 > '실행' 메뉴 > 'Messaging' 메뉴 > (첫 번째 캠페인 만들기) 버튼 클릭 > Firebase 알림 메세지 체크 후 [만들기]
출력된 화면에서 적절한 내용으로 모두 입력 후 [검토] 버튼을 누르면, 앱을 설치한 모든 Device 로 FCM 메세지가 발송 됩니다.
방법2)
PHP 코드를 아래와 같이 작성 합니다.
현재 (2024년 11월) 는 이전에 사용하던 방식에서 FCM HTTP API의 v1 버전으로 전송 방식이 바뀌었습니다.
1) 사용자 계정 키 (json) 다운로드
서비스 계정 키 다운로드를 위해 Firebase Console (https://console.firebase.google.com/ ) 로 이동합니다.
프로젝트 설정 > 서비스 계정 > 새 비공개 키 생성 클릭.
JSON 파일을 다운로드합니다.
다운로드 한 파일은 PHP 생성할 위치로 복사합니다.
2) php 파일 작성
v1 API 는 OAuth2 인증을 사용해야 하므로 google/apiclient 패키지를 설치합니다.
# composer require google/apiclient
아래 파란색 부분을 적절한 값으로 수정하여 작성합니다.
# vi fcm_send.php
<?php require 'vendor/autoload.php';
use Google\Auth\Credentials\ServiceAccountCredentials; use GuzzleHttp\Client;
function sendFCMMessage($serviceAccountPath, $projectId, $token, $title, $body) { // FCM 엔드포인트 URL $url = "https://fcm.googleapis.com/v1/projects/$projectId/messages:send";
// 메시지 페이로드 $message = [ 'message' => [ 'token' => $token, 'data' => [ 'title' => $title, 'message' => $body ] ] ];
// Google OAuth2 인증 $credentials = new ServiceAccountCredentials( 'https://www.googleapis.com/auth/firebase.messaging', json_decode(file_get_contents($serviceAccountPath), true) );
$accessToken = $credentials->fetchAuthToken()['access_token'];
// HTTP 요청 헤더 $headers = [ 'Authorization' => 'Bearer ' . $accessToken, 'Content-Type' => 'application/json', ];
// HTTP 클라이언트 $client = new Client();
try { // FCM 메시지 요청 $response = $client->post($url, [ 'headers' => $headers, 'body' => json_encode($message) ]);
echo "Response: " . $response->getBody(); } catch (Exception $e) { echo "Error: " . $e->getMessage(); } }
// 서비스 계정 JSON 파일 경로 $serviceAccountPath = './your-service-account.json';
// Firebase 프로젝트 ID $projectId = 'your-project-id';
// FCM 토큰, 제목, 내용 $token = 'your-device-token'; $title = 'Test Title'; $body = 'Test Body';
// 메시지 전송 함수 호출 sendFCMMessage($serviceAccountPath, $projectId, $token, $title, $body); ?> |
이제 작성한 파일을 실행만 하면 입력해놓은 특정 디바이스로 (token) FCM 메세지가 전송됩니다.
# php fcm_send.php