122

アプリを GCM から FCM に移行しています。

新しいユーザーがアプリをインストールすると、onTokenRefresh()が自動的に呼び出されます。問題は、ユーザーがまだログインしていないことです (ユーザー ID がありません)。

onTokenRefresh()ユーザーがログインした後にトリガーするにはどうすればよいですか?

4

12 に答える 12

182

このonTokenRefresh()メソッドは、新しいトークンが生成されるたびに呼び出されます。アプリのインストール時に、すぐに生成されます (実際にそうであることがわかっています)。トークンが変更されたときにも呼び出されます。

FirebaseCloudMessagingガイドによると:

単一の特定のデバイスに通知を送信できます。アプリの最初の起動時に、FCM SDK はクライアント アプリ インスタンスの登録トークンを生成します。

スクリーンショット

ソースリンク: https://firebase.google.com/docs/notifications/android/console-device#access_the_registration_token

これは、トークンの登録がアプリごとであることを意味します。ユーザーがログインした後にトークンを利用したいようです。私が提案するのは、onTokenRefresh()メソッド内のトークンを内部ストレージまたは共有設定に保存することです。次に、ユーザーがログインした後にストレージからトークンを取得し、必要に応じてトークンをサーバーに登録します。

を手動で強制するonTokenRefresh()場合は、IntentService を作成してトークン インスタンスを削除できます。その後、getToken を呼び出すと、onTokenRefresh()メソッドが再度呼び出されます。

コード例:

public class DeleteTokenService extends IntentService
{
    public static final String TAG = DeleteTokenService.class.getSimpleName();

    public DeleteTokenService()
    {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        try
        {
            // Check for current token
            String originalToken = getTokenFromPrefs();
            Log.d(TAG, "Token before deletion: " + originalToken);

            // Resets Instance ID and revokes all tokens.
            FirebaseInstanceId.getInstance().deleteInstanceId();

            // Clear current saved token
            saveTokenToPrefs("");

            // Check for success of empty token
            String tokenCheck = getTokenFromPrefs();
            Log.d(TAG, "Token deleted. Proof: " + tokenCheck);

            // Now manually call onTokenRefresh()
            Log.d(TAG, "Getting new token");
            FirebaseInstanceId.getInstance().getToken();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    private void saveTokenToPrefs(String _token)
    {
        // Access Shared Preferences
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = preferences.edit();

        // Save to SharedPreferences
        editor.putString("registration_id", _token);
        editor.apply();
    }

    private String getTokenFromPrefs()
    {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        return preferences.getString("registration_id", null);
    }
}

編集

FirebaseInstanceIdService

public class FirebaseInstanceIdService extends Service

このクラスは非推奨です。FirebaseMessagingService で onNewToken をオーバーライドすることを支持します。実装が完了したら、このサービスを安全に削除できます。

onTokenRefresh() は非推奨ですonNewToken()で使用MyFirebaseMessagingService

public class MyFirebaseMessagingService extends FirebaseMessagingService {

@Override
public void onNewToken(String s) {
    super.onNewToken(s);
    Log.e("NEW_TOKEN",s);
    }

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    }
} 
于 2016-06-01T22:36:43.183 に答える
17

FirebaseInstanceIdServiceリフレッシュトークンを取得する実装を試みます。

登録トークンにアクセスします。

FirebaseInstanceIdServiceを拡張することで、トークンの値にアクセスできます。マニフェストにサービスを追加したことを確認してからgetToken、 のコンテキストで呼び出し、次のonTokenRefreshように値をログに記録します。

     @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);
}

完全なコード:

   import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;


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);
    }
    // [END refresh_token]

    /**
     * Persist token to third-party servers.
     *
     * 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.
    }
}

ここで私の答えを見てください。

編集:

自分でFirebaseInstanceIdServiceを開始するべきではありません。

トークンを更新する必要があるとシステムが判断したときに呼び出されます。アプリケーションは getToken() を呼び出し、すべてのアプリケーション サーバーにトークンを送信する必要があります。

これはあまり頻繁には呼び出されません。キーのローテーションと、次の理由によるインスタンス ID の変更を処理するために必要です。

  • アプリがインスタンス ID を削除する
  • アプリは新しいデバイス ユーザーに復元されます
  • アプリのアンインストール/再インストール
  • ユーザーがアプリのデータを消去する

システムは、トークンの更新でアプリケーション サーバーが過負荷になるのを避けるために、すべてのデバイスで更新イベントを抑制します。

以下の方法を試してください

メインスレッドのどこか (サービス、AsyncTask など) でFirebaseInstanceID.getToken()を呼び出し、返されたトークンをローカルに保存してサーバーに送信します。その後、 が呼び出されるたび に、 FirebaseInstanceID.getToken()onTokenRefresh()を再度呼び出し 、新しいトークンを取得し、それをサーバーに送信します (おそらく古いトークンも含めて、サーバーがそれを削除し、新しいものに置き換えることができます)。 .

于 2016-05-29T12:12:56.767 に答える
2
FirebaseMessaging.getInstance().getToken().addOnSuccessListener(new 
OnSuccessListener<String>() {
    @Override
    public void onSuccess(String newToken) {
        ....
    }
});
于 2020-12-09T05:02:56.310 に答える
0

この回答はインスタンス ID を破棄せず、代わりに現在の ID を取得できます。また、更新されたものを共有設定に保存します。

Strings.xml

<string name="pref_firebase_instance_id_key">pref_firebase_instance_id</string>
<string name="pref_firebase_instance_id_default_key">default</string>

Utility.java (環境設定を設定/取得する任意のクラス)

public static void setFirebaseInstanceId(Context context, String InstanceId) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor;
    editor = sharedPreferences.edit();
    editor.putString(context.getString(R.string.pref_firebase_instance_id_key),InstanceId);
    editor.apply();
}

public static String getFirebaseInstanceId(Context context) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    String key = context.getString(R.string.pref_firebase_instance_id_key);
    String default_value = context.getString(R.string.pref_firebase_instance_id_default_key);
    return sharedPreferences.getString(key, default_value);
}

MyFirebaseInstanceIdService.java (FirebaseInstanceIdService を拡張)

@Override
public void onCreate()
{
    String CurrentToken = FirebaseInstanceId.getInstance().getToken();

    //Log.d(this.getClass().getSimpleName(),"Inside Instance on onCreate");
    String savedToken = Utility.getFirebaseInstanceId(getApplicationContext());
    String defaultToken = getApplication().getString(R.string.pref_firebase_instance_id_default_key);

    if(CurrentToken != null && !savedToken.equalsIgnoreCase(defaultToken))
    //currentToken is null when app is first installed and token is not available
    //also skip if token is already saved in preferences...
    {
        Utility.setFirebaseInstanceId(getApplicationContext(),CurrentToken);
    }
    super.onCreate();
}

@Override
public void onTokenRefresh() {
     .... prev code
      Utility.setFirebaseInstanceId(getApplicationContext(),refreshedToken);
     ....

}

Android 2.0 以降onCreateのサービスは、自動起動時に呼び出されません ( source )。代わりonStartCommandにオーバーライドされて使用されます。しかし、実際の FirebaseInstanceIdService では final として宣言されており、オーバーライドできません。ただし、startService() を使用してサービスを開始すると、サービスが既に実行されている場合は、その元のインスタンスが使用されます(これは良いことです)。onCreate() (上記で定義) も呼び出されました。

これは、MainActivity の開始時、またはインスタンス ID が必要と思われる時点で使用します。

MyFirebaseInstanceIdService myFirebaseInstanceIdService = new MyFirebaseInstanceIdService();
Intent intent= new Intent(getApplicationContext(),myFirebaseInstanceIdService.getClass());
//Log.d(this.getClass().getSimpleName(),"Starting MyFirebaseInstanceIdService");
startService(intent); //invoke onCreate

そして最後に、

Utility.getFirebaseInstanceId(getApplicationContext())

startservice() コードを getFirebaseInstanceId メソッドに移動することで、これをさらに強化できることに注意してください。

于 2016-08-23T19:45:13.843 に答える