이 문서는 Legacy Kakao SDK for Android(이하 Legacy Android SDK)를 사용한 푸시 알림 기능 구현 방법을 안내합니다.
푸시 토큰 등록, 보기, 삭제는 Android와 iOS SDK도 지원하지만, 푸시 알림을 보내는 기능은 REST API로만 지원합니다. 또한 Apple Push Notification service(APNs), Firebase Cloud Messaging(FCM) 인증 정보를 내 애플리케이션(이하 앱) 정보에 미리 등록해두어야 합니다. 인증 정보 발급 및 등록 방법은 설정하기를 참고합니다.
최신 버전의 Kakao SDK for Android/iOS는 푸시 알림 기능을 지원하지 않습니다. 푸시 알림 기능을 구현하려면 REST API, Legacy Android, Legacy iOS SDK를 사용해야 합니다.
푸시 알림을 받을 사용자의 푸시 토큰(디바이스 토큰)을 카카오 푸시 서비스에 등록하는 API입니다. 카카오 푸시 서비스는 멀티 디바이스(Multi device)를 지원합니다. 한 사용자가 여러 기기를 사용하는 경우, 각 기기를 구분하는 기기 고유 ID인 deviceId
가 필요합니다. deviceId
는 자체적인 생성 규칙에 따라 만들어야 하며, 최대 64자까지만 지원됩니다.
푸시 토큰 등록은 PushService
의 registerPushToken
API로 요청하며, 푸시 토큰 등록 요청 결과에 따라 필요한 동작을 ApiResponseCallback
에 구현해야 합니다. 에러는 푸시 토큰을 등록하는 데 실패한 경우, 사용자가 로그인하지 않은 경우, 앱과 사용자 카카오계정이 연결되어 있지 않은 경우 등으로 나뉩니다.
// Firebase 푸시 토큰 발급
FirebaseInstanceId.getInstance().getInstanceId()
.addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
// 파라미터 준비
String pushToken = instanceIdResult.getToken();
String deviceId = "{기기 고유 ID를 입력하세요}";
Integer appVersion = Utility.getAppVersion(getApplicationContext());
// 카카오 서버에 푸시 토큰 등록
PushService.getInstance()
.registerPushToken(new ApiResponseCallback<Integer>() {
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.e("KAKAO_API", "세션이 닫혀 있음: " + errorResult);
}
@Override
public void onNotSignedUp() {
Log.e("KAKAO_API", "사용자가 앱에 연결되어 있지 않음");
}
@Override
public void onFailure(ErrorResult errorResult) {
Log.e("KAKAO_API", "푸시 토큰 등록 실패: " + errorResult);
}
@Override
public void onSuccess(Integer result) {
Log.i("KAKAO_API", "푸시 토큰 등록 성공: " + result);
}
}, pushToken, deviceId, appVersion);
}
});
카카오 로그인을 사용하지 않아 직접 푸시 토큰 처리 기능을 구현하는 경우, 푸시 토큰 보기 및 삭제 기능 구현 시 앱 어드민 키(Admin Key)로 REST API를 사용해야 하므로 반드시 서버에서 호출합니다.
직접 푸시 토큰을 처리하려면 다음 순서로 관리 기능을 구현합니다.
FirebaseMessagingService
를 상속하고 onNewToken()
을 구현하거나, FirebaseInstanceId.getInstance().getInstanceId()
로 가져옵니다.카카오 플랫폼 서비스에 푸시 토큰이 올바르게 등록되었는지, 해당 사용자와 관련된 다른 푸시 토큰들은 무엇인지 확인하는 API입니다. 이 기능을 사용하기 위해서는 카카오 로그인을 통해 발급 받은 액세스 토큰(Access token)이 필요합니다.
PushService
의 getPushTokens
API를 호출합니다.
PushService.getInstance()
.getPushTokens(new ApiResponseCallback<List<PushTokenInfo>>() {
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.e("KAKAO_API", "세션이 닫혀 있음: " + errorResult);
}
@Override
public void onNotSignedUp() {
Log.e("KAKAO_API", "사용자가 앱에 연결되어 있지 않음");
}
@Override
public void onFailure(ErrorResult errorResult) {
Log.e("KAKAO_API", "푸시 토큰 조회 실패: " + errorResult);
}
@Override
public void onSuccess(List<PushTokenInfo> result) {
Log.i("KAKAO_API", "푸시 토큰 조회 성공: " + result.size());
for (PushTokenInfo token : result) {
Log.d("KAKAO_API", token.toString());
}
}
});
요청이 성공하면 PushTokenInfo
의 List
로 푸시 토큰 정보를 받습니다.
Name | Type | Description |
---|---|---|
userId | String |
사용자 고유 ID, 1~((2^63)-1) 범위의 정수만 사용 가능 Deprecate, uuid를 사용하도록 변경 |
uuid | String |
사용자 고유 ID, 1~((2^63)-1) 범위의 정수만 사용 가능 |
deviceId | String |
기기 고유 ID |
pushType | String |
apns 혹은 fcm |
pushToken | String |
APNs, FCM으로부터 발급 받은 푸시 토큰 |
createdAt | String |
푸시 토큰을 처음 등록한 시각 |
updatedAt | String |
푸시 토큰을 업데이트한 시각 |
* userId: Deprecated, 사용자 고유 ID(String), uuid를 사용하도록 변경
사용자의 푸시 토큰을 삭제하는 API입니다. 사용자가 로그아웃하거나 푸시 알림을 끄는 경우, 더 이상 푸시 알림이 보내지지 않도록 하기 위해 이 API를 사용합니다. 사용자가 특정 기기에서만 로그아웃하거나 푸시 알림을 끈 경우, 특정 기기의 푸시 토큰만 지정하여 삭제할 수 있습니다.
한 기기의 푸시 토큰을 삭제하려면 PushService#deregisterPushToken
, 사용자의 모든 푸시 토큰을 삭제하려면 PushService#deregisterPushTokenAll
API를 각각 사용하며, 파라미터인 ApiResponseCallback
에는 요청 결과별 처리를 구현합니다.
String deviceID = "{기기 고유 ID를 입력하세요}";
PushService.getInstance()
.deregisterPushToken(new ApiResponseCallback<Boolean>() {
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.e("KAKAO_API", "세션이 닫혀 있음: " + errorResult);
}
@Override
public void onNotSignedUp() {
Log.e("KAKAO_API", "사용자가 앱에 연결되어 있지 않음");
}
@Override
public void onFailure(ErrorResult errorResult) {
Log.e("KAKAO_API", "푸시 토큰 삭제 실패: " + errorResult);
}
@Override
public void onSuccess(Boolean result) {
}
}, deviceID);
PushService.getInstance()
.deregisterPushTokenAll(new ApiResponseCallback<Boolean>() {
@Override
public void onSessionClosed(ErrorResult errorResult) {
Log.e("KAKAO_API", "세션이 닫혀 있음: " + errorResult);
}
@Override
public void onNotSignedUp() {
Log.e("KAKAO_API", "사용자가 앱에 연결되어 있지 않음");
}
@Override
public void onFailure(ErrorResult errorResult) {
Log.e("KAKAO_API", "푸시 토큰 삭제 실패: " + errorResult);
}
@Override
public void onSuccess(Boolean result) {
if (result) {
Log.i("KAKAO_API", "푸시 토큰 삭제 성공");
} else {
Log.i("KAKAO_API", "푸시 토큰 삭제 실패");
}
}
});
나에게 푸시 알림 보내기를 하려면 사용자가 카카오 로그인한 상태여야 합니다. Android SDK의 푸시 알림 보내기 기능은 스팸 목적으로 악용되거나 보안 문제를 일으킬 수 있어 사용자 본인에게만 전송 가능합니다. 다른 사용자에게 푸시 알림을 보내려면 REST API의 푸시 알림 보내기 API를 사용해야 합니다.
수신자 제한은 사용자 고유 ID로 판별하므로, 현재 로그인한 사용자의 다른 기기로는 푸시 알림을 보낼 수 있습니다. REST API 푸시 알림 보내기의 파라미터 정보를 참고해 푸시 메시지를 구성한 뒤 보내기 요청해야 합니다.
private void sendPushMessageToMe() {
PushMessageBuilder builder = new PushMessageBuilder();
// 사용자 정의 필드 내용 입력
Map<String, Object> customField = new HashMap<>();
customField.put("content", "데이터 메시지");
customField.put("friend_id", "1");
customField.put("noti", "test");
// 푸시 알림 메시지 내용 입력
Map<String, String> notification = new HashMap<>();
notification.put("body", "Notification");
notification.put("title", "알림 메시지");
builder.setCustomField(customField);
builder.setNotification(notification);
// 기타 푸시 메시지 설정
builder.setPriority("high");
builder.setDryRun(false);
builder.setTimeToLive(60L * 60 * 24);
// 푸시 메시지 생성 성공 시 나에게 전송 요청
final String testMessage = builder.toString();
if (testMessage == null) {
Logger.w("failed to create push Message");
} else {
PushService.getInstance().sendPushMessage(new KakaoPushResponseCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
KakaoToast.makeToast(getApplicationContext(), "succeeded to send message", Toast.LENGTH_SHORT).show();
}
}, testMessage, KakaoSDK.getAdapter().getPushConfig().getDeviceUUID());
}
}
아래는 푸시 알림을 받으면 BigTextStyle
로 알림 센터에 보여주고, 이를 클릭하면 앱으로 전환되도록 하는 AndroidManifest.xml 설정 및 FirebaseMessagingService
구현 예제입니다.
<manifest … package="com.kakao.sample.push"> <!-- a. package 이름 -->
<uses-permission android:name="android.permission.INTERNET"/>
<application>
…
<service android:name="com.kakao.push.KakaoFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name="push.SampleFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data android:name="com.kakao.sdk.AppKey"
android:value="${NATIVE_APP_KEY}"/>
...
</application>
</manifest>
public class SampleFirebaseMessagingService extends FirebaseMessagingService {
public static final int NOTIFICATION_ID = 1;
public static int count = 0;
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendDataMessage(remoteMessage);
}
private void sendDataMessage(final RemoteMessage message) {
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notifyIntent = new Intent(this, SampleLoginActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, "put your channel name here")
.setSmallIcon(R.drawable.push_noti_icon)
.setContentTitle(getApplicationContext().getString(R.string.push_notification_title))
.setStyle(new NotificationCompat.BigTextStyle().bigText(message.getData().get("content")))
.setContentText(message.getData().get("content"));
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID + count++, mBuilder.build());
}
}