Firebase (FCM) 토큰을 얻는 방법


97

FCM을 처음 사용합니다.

firebase / quickstart-android 에서 샘플을 다운로드 하고 FCM 빠른 시작을 설치합니다. 하지만 앱 의 LOG TOKEN 버튼을 눌러도 로그에서 토큰을 얻을 수 없습니다 .

그런 다음 Firebase 콘솔로 메시지를 보내고 내 앱 패키지 이름을 타겟팅하도록 설정합니다. 수신 메시지를 받았습니다.

FCM을 사용할 수 있는지 알고 싶습니다 .GCM은 모두 괜찮습니다.

해결책:

저는 Android 개발자가 아니기 때문에 백엔드 개발자 일뿐입니다. 그래서 그것을 해결하는 데 시간이 걸립니다. 제 생각에는 샘플 앱에 몇 가지 버그가 있습니다.

여기에 이미지 설명 입력

암호:

RegistrationIntentService.java

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";


    public RegistrationIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String token = FirebaseInstanceId.getInstance().getToken();
        Log.i(TAG, "FCM Registration Token: " + token);
    }
}

MyFirebaseInstanceIDService.java

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    /**
     * 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.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
//        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);
//
//        // TODO: Implement this method to send any registration to your app's servers.
//        sendRegistrationToServer(refreshedToken);
//
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]

    /**
     * Persist token to third-party servers.
     * <p>
     * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }
}

MainActivity.java에 추가하십시오.

 Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);

위의 작업을 수행하면 Logcat에서 토큰을 얻습니다. 하지만 마지막으로 편리한 방법 을 찾았 습니다. 디버그 모드를 사용하여 샘플 앱 을 설치하면 처음 설치할 때 토큰을 얻을 수 있습니다.

하지만 설치시 로그를 인쇄 할 수없는 이유를 모르겠습니다. 모바일 시스템과 관련이있을 수 있습니다.

그리고 알림을받을 수없는 이유. FirebaseMessagingService.onMessageReceivedsendNotification을 호출하지 않았습니다.


로그가 적중되면 샘플 앱에 토큰과 함께 표시됩니다
Shubhank

아니요, 샘플 앱은. 버튼을 눌렀을 때만 logcat에 토큰을 표시합니다. 하지만 로그 캣에서 아무것도 찾을 @ Shubhank를.
wyx

이 라인의 주석 String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

답변:


127

프로토 타입에 가장 빠르고 좋음

빠른 해결책은이를 sharedPrefs에 저장하고이 로직을 onCreateMainActivity의 메소드 또는 Application을 확장하는 클래스에 추가하는 것입니다.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(this, instanceIdResult -> {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken", newToken);
    getActivity().getPreferences(Context.MODE_PRIVATE).edit().putString("fb", newToken).apply();
});

Log.d("newToken", getActivity().getPreferences(Context.MODE_PRIVATE).getString("fb", "empty :("));

클리너 방법

더 나은 옵션은 서비스를 만들고 유사한 논리를 유지하는 것입니다. 먼저 새로운 서비스 생성

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);
        Log.e("newToken", s);
        getSharedPreferences("_", MODE_PRIVATE).edit().putString("fb", s).apply();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
    }

    public static String getToken(Context context) {
        return context.getSharedPreferences("_", MODE_PRIVATE).getString("fb", "empty");
    }
}

그런 다음 AndroidManifest 파일에 추가하십시오.

<service
        android:name=".MyFirebaseMessagingService"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
</service>

마지막으로 서비스에서 정적 메서드를 사용할 수 있습니다. MyFirebaseMessagingService.getToken(Context);

가장 빠르지 만 사용이 중단됨

Log.d("Firebase", "token "+ FirebaseInstanceId.getInstance().getToken());

버전 17.xx보다 오래된 firebase 라이브러리를 사용하는 경우 여전히 작동합니다.


6
그러나 두 번째 방법은 공유 된 기본 설정이 지워질 때까지만 작동합니다. 앱 데이터가 지워지고 해당 문자열 값이 손실되면 어떻게됩니까? Android는 토큰 이 없기 때문에 "onNewtoken ()"을 호출하지 않습니다 . 그렇다면 토큰을 어떻게 요청합니까? 모든 곳에서 "단지 onNewToken () 사용"이라고 말하지만이 메서드는 토큰 이있을 때만 실행됩니다 . 해당 메서드가 이미 실행되었지만 토큰을 저장하지 않았다고 가정 해 보겠습니다. 나중에 확인을 수행하고 토큰이 설정되지 않았는지 확인합니다. 그러면 어떻게됩니까? 토큰을 다시 알려주기 위해 FCM을 트리거하려면 어떻게해야합니까?
JeneralJames 2019-04-16


1
당신이 사용할 수있는 FirebaseInstanceId.getInstance().getInstanceId()대신에 FirebaseInstanceId.getInstance().getToken(), 볼 이 답변
바딤 Kotov

@JeneralJames 사용자가 앱 데이터를 지우면 onNewToken항상 여기에있는 문서에서 트리거됩니다. firebase.google.com/docs/cloud-messaging/android/…
sarah

26

Firebase Android SDK 팀은 API를 약간 변경합니다. 다음과 같이 "Token to Server"로직을 구현했습니다.

내 FirebaseMessagingService 인스턴스에서 :

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

    @Override
    public void onNewToken(String token) {
        // sending token to server here
    }

    ...

}

토큰은 기기 단위이며 로그인 로직에 관계없이 Firebase에서 업데이트 할 수 있습니다. 따라서 로그인 및 로그 아웃 기능이있는 경우 추가 사례를 고려해야합니다.

  1. 새 사용자가 로그인 할 때 토큰을 새 사용자에게 바인딩해야합니다 (서버로 전송). 기존 사용자의 세션 중에 토큰이 업데이트 될 수 있고 서버가 새 사용자의 토큰을 알지 못하기 때문입니다.
  2. 사용자가 로그 아웃하면 토큰 바인딩을 해제해야합니다. 사용자가 더 이상 알림 / 메시지를받지 않아야하기 때문입니다.

새 API를 사용하면 다음과 같은 토큰을 얻을 수 있습니다.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
        @Override
        public void onSuccess(InstanceIdResult instanceIdResult) {
            String token = instanceIdResult.getToken();
            // send it to server
        }
    });

행운을 빕니다!


OnSuccess 외부의 값을 얻으려고 시도하면 null이 제공됩니다.
DragonFire

로그인 / 로그 아웃 기능은 푸시 메시지와 관련이 없습니다. 이것은 특정 비즈니스 사용 사례입니다. 예를 들어 일부 마케팅 / 프로모션 알림을 통해 로그 아웃 한 사용자를 대상으로하여 앱에 다시 로그인하도록 할 수 있습니다.이 경우 FCM 토큰이 필요합니다. 그러나 토큰을 얻는 측면에서 대답은 정확합니다.
milosmns

@milosmns, 마케팅 / 프로모션 알림 측면에서 맞습니다. 여전히 토큰 상태 표시가 필요합니다. 간단한 해결책은 어떤 종류의 히스토리 테이블에 언 바운드 토큰을 저장 한 다음 과거 토큰을 사용하여 다시 로그인하도록 권장하는 것입니다.
rzaaeeff

실제로 동일한 토큰을 얼마나 오래 재사용 할 수 있으며 정확히 언제 무효화되는지 잘 모르겠습니다. 토큰이 무효화되면이 내역 / 캐시 / 지속성 테이블을 지워야하므로 조사 할 가치가 있습니다.
milosmns

@milosmns, Firebaseland에서 토큰은 만료되지 않고 갱신됩니다. FCM API로 토큰 관련 활동을 트리거하면 제공된 토큰의 유효성이 검사됩니다. 토큰이 유효하지 않은 경우 error : MissingRegistration 또는 error : InvalidRegistration이 표시됩니다. 여기 이상의 오류 코드를 찾을 수 있습니다 firebase.google.com/docs/cloud-messaging/...
rzaaeeff을

24

중요한 정보.

Google Play 서비스가 중단되거나 실행되지 않는 경우 fcm return token = null

Play 서비스가 제대로 작동하면 FirebaseInstanceId.getInstance().getToken()메서드가 반환됩니다.token

Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());

예, 그러나 이것은 매우 자주 발생
호앙 둑 투안

토큰은 한 번 가져온 후 캐시됩니다 (메모리 내에서 대부분). 즉, 한 번 가져 오거나 Firebase가 어떻게 든 다른 토큰을 재발급하도록해야합니다. 수동으로 가져 오는 방법은 여기를 참조하십시오. stackoverflow.com/a/51630819/2102748
milosmns

13

문서에 따르면

GCM 클라이언트 앱을 FCM으로 마이그레이션

onTokenRefresh()

InstanceID 토큰이 업데이트 된 경우에만 호출됩니다.

따라서 기기에 앱을 설치할 때 처음에만 호출됩니다.

따라서 수동으로 앱을 제거하고 다시 실행 해보세요.

확실히 당신은 토큰 을 얻을 것입니다


2
하지 다시 설치, 제거 , 그것은 수동으로 다음 프로젝트를 실행
Gaurav

이 라인의 주석 String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

1
@Gaurav, 두 번째 로그인 후 어떻게 토큰을 얻을 수 있습니까? onTokenRefresh각 로그인을 호출하지 않습니다. 로그인 화면에서 어떻게 토큰을 얻을 수 있습니까?
delavega66

3
@ de_la_vega_66, 먼저 로그인시 토큰 저장해야
Gaurav

FirebaseInstanceIdService를 확장하고 onTokenRefresh () 콜백 메서드가있는 서비스는 매니페스트 파일에 등록해야합니다. <service android : name = "com.mypackage.name.MyInstanceIdService"android : exported = "true"> <intent-filter> <action android : name = "com.google.firebase.INSTANCE_ID_EVENT"/> </ intent-filter> </ service>
Kirill Karmazin

9

이 시도. 왜 사용하고 RegistrationIntentService있습니까?

public class FirebaseInstanceIDService extends FirebaseInstanceIdService {    
    @Override
    public void onTokenRefresh() {    
        String token = FirebaseInstanceId.getInstance().getToken();    
        registerToken(token);
    }

    private void registerToken(String token) {

    }
}

8

이 줄은 firebase FCM 토큰을 가져옵니다.

String token = FirebaseInstanceId.getInstance().getToken();
Log.d("MYTAG", "This is your Firebase token" + token);

Log.d를 실행하여 안드로이드 모니터에 출력합니다.


null을 반환합니다
Kishan Solanki 2018-08-02

7

대신 :

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
//        Get updated InstanceID token.
//        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);
//
//        TODO: Implement this method to send any registration to your app's servers.
//        sendRegistrationToServer(refreshedToken);
//
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]

이 작업을 수행:

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // Implement this method to send token to your app's server
       sendRegistrationToServer(refreshedToken);

    }
    // [END refresh_token]

그리고 하나 더:

sendRegistrationToServer()서버에서 푸시 알림을 보내는 경우 서버에서 토큰을 업데이트 할 메서드 를 호출해야 합니다.

최신 정보:

다음과 같은 경우 새 Firebase 토큰이 생성됩니다 ( onTokenRefresh()호출 됨).

  • 앱이 인스턴스 ID를 삭제합니다.
  • 앱이 새 기기에 복원되었습니다.
  • 사용자가 앱을 제거 / 재설치합니다.
  • 사용자가 앱 데이터를 지 웁니다.

. 나는 deleteInstanceId를 인스턴스 ID FirebaseInstanceId.getInstance ()을 삭제했다 ()하지만, 서비스 오류가 발생했습니다
Hardik9850

2
FirebaseInstanceId.getInstance().deleteInstanceId()다른 스레드에서 실행해야합니다
rockar06 2017 년

5

동시에 토큰 ID를 받기 위해 매니페스트 파일에 포함하는 것을 잊지 마십시오.

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>

5

이 메서드 getToken()는 더 이상 사용되지 않습니다. getInstanceId()대신 사용할 수 있습니다 .

을 요청할 때 결과를 처리 instanceId(token)하려면이 코드를 확인하세요.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
        if (instanceIdResult != null) {
            String token = instanceIdResult.getToken();
            if (!TextUtils.isEmpty(token)) {
                Log.d(TAG, "retrieve token successful : " + token);
            }
        } else{
            Log.w(TAG, "instanceIdResult should not be null..");
        }
    }).addOnFailureListener(e -> {
        //do something with e
    }).addOnCanceledListener(() -> {
        //request has canceled
    }).addOnCompleteListener(task -> Log.v(TAG, "task result : " + task.getResult().getToken()));

4

이후 firebase-messaging:17.1.0FirebaseInstanceIdService는 더 이상 사용되지 않으며 https://stackoverflow.com/a/51475096/1351469에 설명 된대로 클래스 onNewToken에서 얻을 수 있습니다.FirebaseMessagingService

그러나 언제든지 토큰을 얻고 싶다면 이제 다음과 같이 할 수 있습니다.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this.getActivity(),  new OnSuccessListener<InstanceIdResult>() {
  @Override
  public void onSuccess(InstanceIdResult instanceIdResult) {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken",newToken);
  }
});

이것이 반환 될 수 있습니까? 같은 함수를 여러 곳에서 사용할 수 있습니다. 아니면 firebase의 비동기 특성 때문에 복사하여 붙여 넣어야합니다
DragonFire

3

firebase의 일부 인증 기능을 사용하는 경우 다음을 사용하여 토큰을 가져올 수 있습니다.

//------GET USER TOKEN-------
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
        .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
            public void onComplete(@NonNull Task<GetTokenResult> task) {
                if (task.isSuccessful()) {
                    String idToken = task.getResult().getToken();
                      // ...
                }
            }
        });

사용자가 로그인하면 잘 작동합니다. getCurrentUser ()


2

이 시도

FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(OnSuccessListener<InstanceIdResult> { instanceIdResult ->
             fcm_token = instanceIdResult.token}

1

여기에 착륙하는 사람들 FirebaseInstanceIdService은 지금까지 사용되지 않습니다. 대신 사용하십시오.

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onNewToken(String token) {
        Log.d("MY_TOKEN", "Refreshed token: " + token);

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        // sendRegistrationToServer(token);
    }
}

AndroidManifest에서 선언

<application... >

<service android:name=".fcm.MyFirebaseMessagingService">
    <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
</application>

1
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();

            }
        });

-1

Firebase (FCM)에서 다음을 사용하여 토큰을 가져올 수 있습니다.

FirebaseInstanceId.getInstance().getToken();

2
getToken () 메서드는 더 이상 사용되지 않습니다! 이제 가장 좋은 대답은 @rzaaeeff입니다.
Damiii

-9
Settings.Secure.getString(getContentResolver(),
                     Settings.Secure.ANDROID_ID);

이 코드는 firebase 토큰이 아닌 기기의 Android ID를 가져 오는 것입니다.
Syed Afeef
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.