Firebase(FCM)トークンの取得方法


92

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にトークンが表示されます。しかし、logcatには何も見つかりません。@ Shubhank
wyx

この行のコメントを外します String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

回答:


120

プロトタイプにとって最速かつ優れた

簡単な解決策は、それをsharedPrefsに保存し、このロジックをonCreate、MainActivityまたは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
ただし、2番目のアプローチは、共有設定がクリアされるまで機能します。アプリのデータが消去され、その文字列値が失われた場合はどうなりますか?新しいトークンがないため、Androidは「onNewtoken()」を呼び出しません。しかし、どうやってトークンをリクエストするのでしょうか?どこでも「onNewToken()を使用する」と書かれていますが、そのメソッドは新しいトークンがある場合にのみ実行されます。そのメソッドはすでに実行されているが、トークンを保存する必要がないとしましょう。後でチェックを実行して、トークンが設定されていないことを確認します。FCMをトリガーしてトークンを再度通知するにはどうすればよいですか?
JeneralJames


1
FirebaseInstanceId.getInstance().getInstanceId()代わりに使用できます。この回答をFirebaseInstanceId.getInstance().getToken()参照してください
Vadim Kotov

24

重要な情報。

グーグルプレイサービスがハングしているか実行されていない場合、fcmリターントークン= null

Playサービスが適切に機能している場合、FirebaseInstanceId.getInstance().getToken()メソッドは戻りますtoken

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

はい、しかし、これは非常に頻繁に起こります
Hoang Duc Tuan 2017年

トークンは、一度フェッチされた後にキャッシュされます(おそらくメモリ内)。つまり、これを一度フェッチするか、Firebaseで別のトークンを何らかの方法で再発行する必要があります。手動でフェッチする方法については、こちらを参照してくださいstackoverflow.com/a/51630819/2102748を
milosmns

20

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を

13

ドクによると

GCMクライアントアプリをFCMに移行する

onTokenRefresh()

InstanceIDトークンが更新された場合にのみ呼び出されます

そのため、デバイスにアプリをインストールしたときに初めて呼び出されます。

だから私はあなたのアプリを手動でアンインストールしてもう一度実行してみることをお勧めします

間違いなくトークンを取得します


2
インストールせず、手動でアンインストールしてからプロジェクトを実行します
Gaurav

この行のコメントを外します String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

1
@Gaurav、2回目のログイン後にトークンを取得する方法 onTokenRefresh各ログインを呼び出さない。ログイン画面でトークンを取得するにはどうすればよいですか?
delavega66 2017年

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を実行して、Androidモニターに出力します。


nullを返します
Kishan Solanki

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を削除します
  • アプリは新しいデバイスで復元されます
  • ユーザーがアプリをアンインストール/再インストールした
  • ユーザーがアプリのデータを消去します。

インスタンスID FirebaseInstanceId.getInstance()。deleteInstanceId()を削除する必要がありましたが、サービスエラーが発生しました
Hardik9850

2
FirebaseInstanceId.getInstance().deleteInstanceId()別のスレッドで実行する必要があります
rockar06

5

同時に、トークンIDを受け取るためにこれをマニフェストファイルに含めることを忘れないでください

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

4

firebase-messaging:17.1.0FirebaseInstanceIdServiceが廃止されて以降、あなたが得ることができるonNewTokenFirebaseMessagingServiceに説明したように、クラス https://stackoverflow.com/a/51475096/1351469

しかし、いつでもトークンを取得したい場合は、次のように実行できます。

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

4

このメソッド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()));

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.