안녕하세요 꼭 좀 답변 부탁드립니다 KakaoSdk관련 문의입니다

처음에 제가 만든 카카오 앱에 푸쉬를 날렸을때는 푸쉬가 왔었습니다 실제로 푸쉬기록이 남아있고요
그런데 그 앱에서 탈퇴한후 다시 가입하니 Firebase에서는 푸쉬가 보내지지만 RestAPI에서는 푸쉬가 보내지지 않습니다 .
“msg”: “push token for ( appId=143337, receiverUserId=49701319 ) does not exist.”,
“code”: -901 이런 에러를 뱉습니다. 사용자 id는 앱상에서도 등록되어 있습니다.
아마 사용자 id에 맞는 토큰을 KakaoSDK가 매칭해주지 않는 것 같습니다.

KakaoSDK는 자동으로 토큰하고 uuid를 연결해주는거 아닌가요? 만약 아니라면 저는 따로 설정해준것이 없는데 처음에는 어떻게 deviceid와 Token정보를 얻어온것인지 이해가 안됩니다.
GlobalApplication에서 KakaoSDK.init(new KakaoSDKAdapter());하면 충분한건가요?

그리고 천운으로 처음에 된것이라고 가정해도 어떻게 uuid와 firebase에서 받은 Token을 연결하는지 궁금합니다. KakaoApi를 사용해서 하고싶구요.

되던게 탈퇴했다고 되지않아서 귀신이 곡할 노릇입니다… 도움 부탁드립니다.
package com.example.haha.a123123;

import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;

import java.io.UnsupportedEncodingException;
import java.util.UUID;
import com.kakao.auth.ApiResponseCallback;
import com.kakao.auth.ApprovalType;
import com.kakao.auth.AuthType;
import com.kakao.auth.IApplicationConfig;
import com.kakao.auth.IPushConfig;
import com.kakao.auth.ISessionConfig;
import com.kakao.auth.KakaoAdapter;
import com.kakao.auth.Session;
import com.kakao.auth.network.response.ApiResponse;
import com.kakao.network.ErrorResult;
import com.kakao.push.PushService;
import com.kakao.push.PushToken;
import com.kakao.push.response.model.PushTokenInfo;
import com.kakao.util.helper.SharedPreferencesCache;

public class KakaoSDKAdapter extends KakaoAdapter {

private static final String PROPERTY_DEVICE_ID = null;

@Override
public IPushConfig getPushConfig() {
    return new IPushConfig() {
        /**
         * [주의!] 아래 예제는 샘플앱에서 사용되는 것으로 기기정보 일부가 포함될 수 있습니다. 실제 릴리즈 되는 앱에서 사용하기 위해서는 사용자로부터 개인정보 취급에 대한 동의를 받으셔야 합니다.
         *
         * 한 사용자에게 여러 기기를 허용하기 위해 기기별 id가 필요하다.
         * ANDROID_ID가 기기마다 다른 값을 준다고 보장할 수 없어, 보완된 로직이 포함되어 있다.
         * @return 기기의 unique id
         */

        public String getDeviceUUID() {
            String deviceUUID;
            Log.d("test","0");
            final SharedPreferencesCache cache = Session.getCurrentSession().getAppCache();
            final String id = cache.getString(PROPERTY_DEVICE_ID);

            if (id != null) {
                deviceUUID = id;
                return deviceUUID;
            } else {
                UUID uuid = null;
                Context context = getApplicationConfig().getApplicationContext();
                final String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
                try {
                    if (!"9774d56d682e549c".equals(androidId)) {
                        uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                    } else {
                        final String deviceId = ((TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE)).getDeviceId();
                        uuid = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) : UUID.randomUUID();
                    }
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }

                Bundle bundle = new Bundle();
                bundle.putString(PROPERTY_DEVICE_ID, uuid.toString());
                cache.save(bundle);

                deviceUUID = uuid.toString();
                return deviceUUID;
            }
        }

        @Override
        public ApiResponseCallback<Integer> getTokenRegisterCallback() {
            return new ApiResponseCallback<Integer>() {
                @Override
                public void onFailure(ErrorResult errorResult) {
                    // FCM 토큰 등록 실패 처리.
                    Log.d("test","1");
                }

                @Override
                public void onSessionClosed(ErrorResult errorResult) {
                    // 현재 로그인이 되어 있지 않은 상태.
                    Log.d("test","2");
                }

                @Override
                public void onNotSignedUp() {
                    // 앱에 카카오톡 계정으로 가입이 되어있지 않은 상태.
                    Log.d("test","3");
                }

                @Override
                public void onSuccess(Integer result) {
                    // 성공적으로 토큰이 등록된 상태
                    Log.d("test","4");
                }
            };
        }
    };
}


@Override
public ISessionConfig getSessionConfig() {

    return new ISessionConfig() {
        @Override
        public AuthType[] getAuthTypes() {
            return new AuthType[]{AuthType.KAKAO_LOGIN_ALL};
        }

        @Override
        public boolean isUsingWebviewTimer() {
            return false;
        }

        @Override
        public boolean isSecureMode() {
            return false;
        }

        @Override
        public ApprovalType getApprovalType() {
            return ApprovalType.INDIVIDUAL;
        }

        @Override
        public boolean isSaveFormData() {
            return true;
        }
    };
}

@Override
public IApplicationConfig getApplicationConfig() {
    return new IApplicationConfig() {
        @Override
        public Context getApplicationContext() {
            return GlobalApplication.getGlobalApplicationContext();
        }
    };
}

}

제 나름대로 log를 찍어봤는데 log메세지도 출력되지 않네요… 그러면 아예 토큰을 넣지않는다는 이야기 아닌가요? 어떻게 해결해야 좋을까요?

service android:name=“com.kakao.push.KakaoFirebaseInstanceIdService”
intent-filter
action android:name=“com.google.firebase.INSTANCE_ID_EVENT” /
/intent-filter
/service
service android:name=".SampleFirebaseMessagingService"
intent-filter
action android:name=“com.google.firebase.MESSAGING_EVENT” /
/intent-filter
/service
manifest에 이렇게 추가도 하였습니다! < > 이건 안보여서 지웠습니다

만약 RestApi에서 토큰등록을 따로해줘야 하는거라면 처음에 따로 등록을 해주지 않았는데 어떻게 RestApi를 통한 push가 가능했는지 정말로 궁금합니다. 아니면 kakaoSDK가 자동적으로 해주는건가요 ?..

카카오 푸시라고 해서 다를건 없어보입니다. device id등록은 getDeviceUUID를 통해 카카오에 등록하는걸로 보이구요, 실제로 상용으로 사용하기 위해서는 6.0 OS 이상에서는 퍼미션동의를 받는 로직도 추가하셔서 사용해야 합니다.
(device id 조회에는 전화상태 조회 퍼미션을 동의받아야 합니다.)

  1. PushService.getPushTokens 로 푸시토큰이 올바로 등록됐는지 확인
  2. 회원 탈퇴시 PushService.deregisterPushToken 로 정상 삭제를 하는지 확인
  3. push 가 정상적으로 수신되는지 service에 Log 찍어서 확인

이렇게 현상 확인을 우선해보시는것도 방법일듯 합니다.

1개의 좋아요

질문 하나 드려도 괜찮을까요? 그렇다면 kakaoSDK가 자동으로 푸쉬토큰가 uuid를 연결해주는게 아니라는 말씀이신건가요? 만약에 연결해주는게 맞다면 왜 uuid를 발급받았지만 push token is not exist라는 에러가 발생하는 걸까요?
deviceid==new KakaoSDKAdapter().getPushConfig().getDeviceUUID());
uuid==accessTokenInfoResponse.toString();
Token==FirebaseInstanceId.getInstance().getToken();
다 정상적으로 출력은 됩니다. SDK가 이어주지 못하는 것 같습니다.

위에 확인하는 사항에 문제가 없다면 FirebaseInstanceId.getInstance().getToken() 확인 후 push 발송시 token key와 동일한지 비교해보세요.

1개의 좋아요

FirebaseInstanceId.getInstance().getToken()로 나온 푸쉬키와 push발송시 token key와 어떻게 같은지 비교하나요? firebase console창 내에서 FirebaseInstanceId.getInstance().getToken()로 나온 푸쉬키로 푸쉬를 날리면 정상적으로 푸쉬가 날라갑니다 하지만 RestApi로 날리면 푸쉬가 가지않아요.
제가 카카오 로그인 ID를 바꿔가면서 접속해봐도 계속 같은 Token을 뱉는데 혹시 이 문제가 있는건가요?
계속 똑같은 Token을 뱉어서 처음 등록된 아이디만 푸쉬를 받고 다음 ID부터 푸쉬를 못 받는것 같습니다.
그렇다면 KakaoSdk의 TokenRefesh 함수가 제대로 작동안되는거 아닌가요?

PushService.registerPushToken(KakaoSDK.getAdapter().getPushConfig().getTokenRegisterCallback(), FirebaseInstanceId.getInstance().getToken(), KakaoSDK.getAdapter().getPushConfig().getDeviceUUID(), Utility.getAppVersion(getApplicationContext())); 이렇게 직접 등록하니까 되긴하는데요 그럼 Tokenrefresh()함수가 작동안되는것같습니다 manifest에 추가도 했는데 왜 Tokenrefresh()함수가 작동되지 않는건가요 ?

안녕하세요! 카카오 푸시 SDK에서는 FirebaseInstanceIndSevice를 상속하고 있는 KakaoFirebaseInstanceIdService의 onTokenRefresh() 메소드가 불릴 때마다 자동으로 토큰과 UUID를 등록하고 있는데요. 이 onTokenRefresh()는 새로운 유저가 로그인할 때마다 불리는 것이 아니라, 앱 설치, 앱 업데이트 등의 이벤트가 있을 때만 불리는 메소드에요. FIrebase SDK 자체가 그렇게 구현되어 있습니다. 그래서 매번 한 유저가 로그아웃하고 다른 유저가 로그인할 때마다 등록을 해주고 있지는 않아요. 좀 더 정확히 말씀드라지면 PushService와 KakaoFirebaseInstanceIdService가 해주는 일은 onTokenRefresh()가 불리는 경우마다

  1. 만약 카카오 로그인이 되어 있다면 그 유저의 토큰으로 UUID와 같이 등록하고
  2. 로그인되어 있지 않다면, SharedPreferences에 저장한 후, 추후 유저 로그인이 있을 경우 등록하고 캐시에서 지움

이렇게 두가지 입니다.

물론 유저가 로그인할 때마다 FirebaseInstnaceId.getInstnace.getToken()의 값을 강제로 등록하게 할수도 있지만 대부분의 유저의 경우 하나의 카카오 계정으로 로그인하기 때문에 업데이트할 필요가 없어 그러지 않기로 SDK 내에서 정책적인 결정을 한 것입니다. SDK에서는 최소한으로 필요한 경우 (onTokenRefresh()의 경우) 에만 자동 등록을 해주는 것이지요. 만약 새 유저가 로그인할 때마다 등록을 강제하고 싶다면 이미 처리하신대로 로그인 시마다 PushService.registerToken()을 불러주시면 됩니다.

만약 이 부분에 개선이 필요하다고 생각하시면 자유롭게 의견 주시면 감사하겠습니다. :slight_smile:

1개의 좋아요

완벽한 답이되었습니다! 감사합니다 그러면 한 휴대폰에서 A라는 사용자가 사용하고있다가 B라는 사용자로 아이디를 바꿔도 B사람한테는 푸쉬가 안오는게 맞군요 ?

네네 PushService.init(()만 호출하신 상태에서는 그렇구요. ISessionCallback 등을 이용하거나 로그인 후에 안착하게 되는 액티비티 등에서 말씀해주신 PushService.registerPushToken()을 직접 호출하시면 될 것 같아요… 해당 내용은 가이드에도 제대로 나와있지 않은 것 같아 조금 혼란스러울 수 있는 부분인 것 같아요 ㅠ.ㅠ 또 질문이 있으시면 댓글 달아주세요 :slight_smile:

1개의 좋아요