일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 주엽역 생활맥주
- 막내의막무가내 코틀린
- 막내의막무가내 플러터 flutter
- 프로그래머스 알고리즘
- 막내의막무가내 플러터
- 안드로이드 Sunflower 스터디
- 막내의막무가내 SQL
- 막내의막무가내
- 부스트코스
- 막내의 막무가내 알고리즘
- Fragment
- flutter network call
- 막내의막무가내 안드로이드 코틀린
- 막내의막무가내 rxjava
- 막내의막무가내 알고리즘
- 막내의막무가내 코틀린 안드로이드
- 안드로이드 sunflower
- 2022년 6월 일상
- 막내의 막무가내
- 막무가내
- 막내의막무가내 목표 및 회고
- 막내의막무가내 프로그래밍
- 막내의막무가내 일상
- 안드로이드
- 프래그먼트
- 막내의막무가내 안드로이드
- 막내의막무가내 코볼 COBOL
- 부스트코스에이스
- 막내의막무가내 안드로이드 에러 해결
- 주택가 잠실새내
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
파이어베이스 FCM 노티피케이션(notification)하는 방법 정리 2019 본문
예를들어 카톡알림처럼 내가 누군가에게 채팅을 했을때 상대방에게 알림을 주고싶을 때 즉 , 디바이스에서 디바이스로 알림을 주고 싶은데 하는방법에 대해 포스팅해볼려고합니다.
먼저 OkHttp3, 클라우드메세징 파이어베이스 관련된 것은 gradle에서 implementation 해줬다고 생각하고 진행해보도록 하겠습니다.
//okHttp
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
FCM을 하기위해서는 먼저 상대방의 토큰 값을 알아야합니다. 그래서 전 저의 토큰값을 데이터베이스에 저장하여 상대방이 저의 토큰을 데이터베이스를 통해 알고 푸시메세지를 쏴줄 수 있게 했습니다. 다음은 그 코드입니다.
//fcm토큰 얻어서 디비에 저장해줌
private void sendPushTokenToDB() {
//파이어베이스
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(@NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
Map<String, Object> map = new HashMap<>();
map.put("fcmToken", token);
FirebaseHelper.db.collection("Users").document(FirebaseHelper.mUid).collection("FcmToken").document(FirebaseHelper.mUid).set(map);
finish();
}
});
}
package com.mtjinse.myapplication.activity.services;
import android.app.Notification;
import android.app.NotificationChannel;
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.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.mtjinse.myapplication.R;
import com.mtjinse.myapplication.activity.activities.MainActivity;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* 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) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
}
// [END receive_message]
// [START on_new_token]
/**
* 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.
*/
@Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
}
// [END on_new_token]
/**
* Create and show a simple notification containing the received FCM message.
*
* @param messageBody FCM message body received.
*/
private void sendNotification(String title, 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);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.com_facebook_button_icon)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("fcm_default_channel",
"fcm_default_channel",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
1. FirebaseMessagingService를 상속한 서비스를 만들어줍니다. 구글 파이어베이스 문서에는 해당 클래스에 다른 메소드들도 몇개 더 써져있으나 저는 안쓰므로 이렇게 3가지 메소드만 남겨주었습니다. 오레오 버전부터는 노티피케이션 채널이 필요한데 저는 fcm_default_channel 이라고 지었습니다. 원하시는대로 짓되 통일되게만 해주시면 됩니다.
그리고 notify()에서 0 /*ID 는 노피케이션의 아이디인데 이게 숫자를 0으로고정해놓으면 알림이 한개가왔으면 거기에 이어서 하나 더 온 경우, 하나의 알림창에 중복되서 뜬다. 즉 위에 뜨는 알림창 하나에 모든 알림 정보를 중첩해서 넣는다는거다. 만약 아이디를 다르게 보내면 알림창이 1개, 2개, 3개 이렇게 각각 구분해서 뜬다.
그리고 PendingIntent는 알림을 눌렀을 때 해당 액티비티로 이동할 수 있게해준다. 일반 인텐트처럼 putExtra로 값도 넣을 수도 있다.
<manifest>
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<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_ic_notification" />
<!-- 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" />
<수신용>
package com.mtjinse.myapplication.activity.models;
import android.os.AsyncTask;
import android.util.Log;
import android.view.textclassifier.TextLinks;
import org.json.JSONObject;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class SendNotification {
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
public static void sendNotification(String regToken, String title, String messsage){
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... parms) {
try {
OkHttpClient client = new OkHttpClient();
JSONObject json = new JSONObject();
JSONObject dataJson = new JSONObject();
dataJson.put("body", messsage);
dataJson.put("title", title);
json.put("notification", dataJson);
json.put("to", regToken);
RequestBody body = RequestBody.create(JSON, json.toString());
Request request = new Request.Builder()
.header("Authorization", "key=" + "AKXY5Wc7gWvZf5tEj")
.url("https://fcm.googleapis.com/fcm/send")
.post(body)
.build();
Response response = client.newCall(request).execute();
String finalResponse = response.body().string();
}catch (Exception e){
Log.d("error", e+"");
}
return null;
}
}.execute();
}
}
2. 다음 클래스를 하나 생성해주는데 저는 안에다가 static으로 구현하고 여러군데에서 바로바로 가져다가 사용할 수 있게끔 구현하였습니다. 그리고 refToken(알림을받아야하는사람의 토큰)과 제가 보내는데 추가로 필요한 정보인 title, message를 매개변수를 추가로만들고 JsonObject에 put해주어 보냈습니다
그리고 Authorization에서 서버키를 적어야하는데 저는 보안을 위해서 코드에는 제가 멋대로 짤라서(주작해서) 포스팅에 올렸는데 서버키는 위와같이 파이어베이스 콘솔에서 볼 수 있습니다. (좀 키가 깁니다, 가장위에것)
<발신을위한 코드>
private void sendGson() {
mRootDatabaseReference.child("UserList").child(mFriendUid).child("PushToken").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Map<String,String> map= (Map<String, String>) dataSnapshot.getValue(); //상대유저의 토큰
mPushToken = map.get("pushToken");
Log.d(TAG, "상대방의 토큰 : " + mPushToken);
mRootDatabaseReference.child("UserList").child(mFriendUid).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Profile profile = dataSnapshot.getValue(Profile.class);
SendNotification.sendNotification(mPushToken, profile.getNickName(), mFcmMessage);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
3. 이제 2번에서 만든 클래스를 사용하여 sendNotification을 하면됩니다. 저 같은 경우는 DB에서 토큰과 메세지내용 및 닉네임을 가져와야하기떄문에 리얼타임디비 코드가 섞여있는데 SendNotification.sendNotification(mPushToken, profile.getNickName(), mFcmMessage); 부분만 보시면 될 것 같습니다.
<2번에서 만들것을 사용해서 보내자>
결과로 포어그라운드(앱이 켜져있을때) 백그라운드일때(앱이 꺼져있을때) 모두 알림이 잘 수신됨을 확인할 수 있습니다.
이상포스팅 마치겠습니다.
공감과 댓글은 큰 힘이됩니다. 감사함니다.
https://youngest-programming.tistory.com/393
추가 2020 업데이트 글 남깁니다.
참고:
https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko
'안드로이드 > 자바 & Previous' 카테고리의 다른 글
[안드로이드] Spanny 라이브러리 (0) | 2019.06.15 |
---|---|
[안드로이드] Retrofit2 정리 예제 (19) | 2019.06.14 |
[안드로이드] 리사이클러뷰(RecyclerVeiw) xml 뷰 여러개 사용하는 법 (뷰홀더 2개 이상) (4) | 2019.05.28 |
[안드로이드] 애드몹 전면광고 달기 17버전 2019년도 (0) | 2019.05.19 |
[안드로이드] 리사이클러뷰(RecyclerView) 표본 (0) | 2019.05.19 |