Firebase FCM gücü onTokenRefresh () çağrılacak


111

Uygulamamı GCM'den FCM'ye geçiriyorum.

Yeni bir kullanıcı uygulamamı yüklediğinde onTokenRefresh(), otomatik olarak çağrılıyor. Sorun, kullanıcının henüz oturum açmamış olmasıdır (Kullanıcı kimliği yok).

onTokenRefresh()Kullanıcı oturum açtıktan sonra nasıl tetikleyebilirim ?


1
Aşağıdaki bağlantıda çok benzer bir soru zaten sorulmuştu. Cevabın sizin için yararlı olup olmadığını kontrol edin: stackoverflow.com/questions/37517254/…
Diego Giorgini

Yanıtlar:


172

onTokenRefresh()Yöntem yeni bir belirteç oluşturulur zaman çağrılacak gidiyor. Uygulama yüklendikten sonra, hemen oluşturulacaktır (sizin de bulduğunuz gibi). Ayrıca belirteç değiştiğinde de çağrılacaktır.

Rehbere göre FirebaseCloudMessaging:

Bildirimleri tek, belirli bir cihaza hedefleyebilirsiniz. Uygulamanızın ilk başlangıcında, FCM SDK, istemci uygulama örneği için bir kayıt jetonu oluşturur.

Ekran görüntüsü

Kaynak Bağlantı: https://firebase.google.com/docs/notifications/android/console-device#access_the_registration_token

Bu, jeton kaydının uygulama başına olduğu anlamına gelir. Bir kullanıcı oturum açtıktan sonra belirteci kullanmak istediğiniz gibi görünüyor. Size önereceğim şey, onTokenRefresh()yöntemdeki simgeyi dahili depolamaya veya paylaşılan tercihlere kaydetmenizdir . Ardından, bir kullanıcı oturum açtıktan sonra jetonu depodan alın ve jetonu gerektiği şekilde sunucunuza kaydedin.

El ile zorlamak onTokenRefresh()isterseniz, bir IntentService oluşturabilir ve belirteç örneğini silebilirsiniz. Daha sonra getToken'ı çağırdığınızda, onTokenRefresh()yöntem yeniden çağrılacaktır.

Örnek Kod:

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

DÜZENLE

FirebaseInstanceIdService

genel sınıf FirebaseInstanceIdService, Hizmeti genişletir

Bu sınıf kullanımdan kaldırıldı. FirebaseMessagingService'te onNewToken'ı geçersiz kılma lehine. Bu uygulandığında, bu hizmet güvenli bir şekilde kaldırılabilir.

onTokenRefresh () kullanımdan kaldırıldı . Kullanım onNewToken()yılındaMyFirebaseMessagingService

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

27
Kullanıcı oturum açmadan önce onTokenRefresh () çağrılsa bile, yerel olarak depolama işi yapmak yerine, kullanıcı oturum açtığında jetonu FirebaseInstanceId.getInstance (). GetToken () kullanarak alabilir ve sunucuya gönderebilirsiniz. Kayıt için. (sunucunuzdan eski bir belirteci silmek için yerel olarak saklamak istemiyorsanız)
geekoraul

10
FireBase akıllıdır ve yalnızca belirteç yoksa (silinirse veya ilk kez çağrılırsa) veya başka bir şey olursa ve simge değiştirilirse onTokenRefresh () yöntemini çağırır. Biri onTokenRefresh'i çağırmak isterse jetonu silebilir ve ardından FirebaseInstanceId.getInstance (). GetToken () 'i çağırabilir. FirebaseInstanceId.getInstance () Operasyonu. DeleteInstanceId () AsyncTask veya yeni Thread içinde olması gerekiyor, MainThread'de olamaz !!!
Stoycho Andreev

3
Neden FirebaseInstanceId.getToken'ı çağırmıyorsunuz?
2016

1
iyi, IntentService'de arama yaparken mükemmel çalıştı ve tercihlerde belirteç kaydetmeye gerek yok, sanırım. FirebaseInstanceId.getInstance () tarihine kadar değer değişmediğinden deleteInstanceId (); denir. Günümü kurtardı. :)
Detoxic-Soul

5
Jetonu neden paylaşılan tercihlere kaydedelim - eğer FirebaseInstanceId.getInstance (). GetToken () 'i değerini almak için istediğiniz zaman çağırabiliyorsanız ?
Alexander Farber

18

FirebaseInstanceIdServiceYenileme belirteci almak için uygulamayı deneyin .

Kayıt jetonuna erişin:

FirebaseInstanceIdService'i genişleterek jetonun değerine erişebilirsiniz . Hizmeti bildiriminize eklediğinizden emin olun , ardından getTokenbağlamında arayın onTokenRefreshve değeri gösterildiği gibi kaydedin :

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

Tam Kod:

   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.
    }
}

Cevabımı gör burada .

DÜZENLEMELER:

Bir FirebaseInstanceIdService başlatmamalısınızKendiniz .

Sistem, belirteçlerin yenilenmesi gerektiğini belirlediğinde Çağrılacaktır. Uygulama getToken () 'i çağırmalı ve belirteçleri tüm uygulama sunucularına göndermelidir.

Bu çok sık çağrılmaz, anahtar rotasyonu için ve aşağıdaki nedenlerden dolayı Örnek Kimliği değişikliklerini işlemek için gereklidir:

  • Uygulama, Örnek Kimliğini siler
  • Uygulama yeni bir cihaza geri yüklendi Kullanıcı
  • uygulamayı kaldırır / yeniden yükler
  • Kullanıcı, uygulama verilerini temizler

Sistem, uygulama sunucularının belirteç güncellemeleriyle aşırı yüklenmesini önlemek için yenileme olayını tüm cihazlarda yavaşlatır.

Aşağıdaki yolu deneyin :

Ana iş parçacığınız (bir hizmet, AsyncTask, vb.) dışında herhangi bir yerde FirebaseInstanceID.getToken () 'ı çağırır , döndürülen jetonu yerel olarak depolar ve sunucunuza gönderirsiniz. Daha sonra her onTokenRefresh()çağrıldığında, FirebaseInstanceID.getToken () 'i tekrar çağırırsınız , yeni bir jeton alırsınız ve bunu sunucuya gönderirsiniz (muhtemelen eski jeton da dahil olmak üzere sunucunuz onu kaldırabilir, yenisiyle değiştirebilir) .


2
FirebaseInstanceIdService'i uyguladım, sorun şu ki, kullanıcı uygulamayı yükledikten hemen sonra onTokenRefresh () çağrılıyor. Oturum Açma / Kaydolma gerçekleştirdikten sonra çağrılmasına ihtiyacım var
TareK Khoury

1
FirebaseInstanceId'i silmek, jetonu yeniler, teşekkürler!
Louis CAD

GCM'den FCM'ye, FirebaseInstanceId.getInstance (). getToken (); her zaman boş döndür. Herhangi bir çözüm?
Govinda Paliwal

@TareKhoury Token almak için gereken her yerde bu yöntemi çağırabilirsiniz. . FirebaseInstanceId.getInstance () getToken ();
sssvrock

İstemci uygulaması güncellemesi durumunda @pRaNaY onTokenRefresh()aranır mı?
Piyush Kukadiya

2

Paylaşılan pref'te, gcm belirtecinin sunucuya gönderilip gönderilmediğini gösteren bir bayrak tutuyorum. Açılış ekranında sendDevicetokenToServer yöntemlerinden birini her çağırdığımda. Bu yöntem, kullanıcı kimliğinin boş olup olmadığını ve gcm gönderme durumunu kontrol eder ve ardından jetonu sunucuya gönderir.

public static void  sendRegistrationToServer(final Context context) {

if(Common.getBooleanPerf(context,Constants.isTokenSentToServer,false) ||
        Common.getStringPref(context,Constants.userId,"").isEmpty()){

    return;
}

String token =  FirebaseInstanceId.getInstance().getToken();
String userId = Common.getUserId(context);
if(!userId.isEmpty()) {
    HashMap<String, Object> reqJson = new HashMap<>();
    reqJson.put("deviceToken", token);
    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);

    Call<JsonElement> call = apiService.updateDeviceToken(reqJson,Common.getUserId(context),Common.getAccessToken(context));
    call.enqueue(new Callback<JsonElement>() {
        @Override
        public void onResponse(Call<JsonElement> call, Response<JsonElement> serverResponse) {

            try {
                JsonElement jsonElement = serverResponse.body();
                JSONObject response = new JSONObject(jsonElement.toString());
                if(context == null ){
                    return;
                }
                if(response.getString(Constants.statusCode).equalsIgnoreCase(Constants.responseStatusSuccess)) {

                    Common.saveBooleanPref(context,Constants.isTokenSentToServer,true);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<JsonElement> call, Throwable throwable) {

            Log.d("", "RetroFit2.0 :getAppVersion: " + "eroorrrrrrrrrrrr");
            Log.e("eroooooooorr", throwable.toString());
        }
    });

}

}

MyFirebaseInstanceIDService sınıfında

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

    // 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.
    Common.saveBooleanPref(this,Constants.isTokenSentToServer,false);
    Common.sendRegistrationToServer(this);
    FirebaseMessaging.getInstance().subscribeToTopic("bloodRequest");
}

2

Arkadaşlar çok basit bir çözümü var

https://developers.google.com/instance-id/guides/android-implementation#generate_a_token

Not: Uygulamanız, deleteInstanceID tarafından silinen jetonlar kullandıysa, uygulamanızın değiştirme jetonları oluşturması gerekir.

Örnek kimliğini silmek yerine, yalnızca jetonu silin:

String authorizedEntity = PROJECT_ID;
String scope = "GCM";
InstanceID.getInstance(context).deleteToken(authorizedEntity,scope);

2
Benim için çalışmadı. DeleteToken () çağrıldıktan sonra getToken () önceki ile aynı belirteci döndürür ve onTokenRefresh çağrılmadı.
Lera

1

Bu, bir kullanıcının uygulamanızdan çıkış yaptığı ve diğer kullanıcıların oturum açtığı senaryoda RxJava2'dedir (Aynı Uygulama) Oturum açmak ve oturum açmak için (Kullanıcının cihazının etkinlik başladığında daha önce internet bağlantısı yoksa ve jeton göndermemiz gerekiyorsa) giriş api)

Single.fromCallable(() -> FirebaseInstanceId.getInstance().getToken())
            .flatMap( token -> Retrofit.login(userName,password,token))
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(simple -> {
                if(simple.isSuccess){
                    loginedSuccessfully();
                }
            }, throwable -> Utils.longToast(context, throwable.getLocalizedMessage()));

Oturum aç

@FormUrlEncoded
@POST(Site.LOGIN)
Single<ResponseSimple> login(@Field("username") String username,
                         @Field("password") String pass,
                         @Field("token") String token

);

0

Bu cevap örnek kimliğini yok etmez, bunun yerine mevcut olanı alabilir. Yenilenmiş olanı da Paylaşılan tercihlerde depolar.

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 (tercihleri ​​ayarlamak / almak istediğiniz herhangi bir sınıf)

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'i genişletir)

@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 ve üstü onCreatehizmet, otomatik olarak başlatıldığında çağrılmaz ( kaynak ). Bunun yerine onStartCommandgeçersiz kılınır ve kullanılır. Ancak gerçek FirebaseInstanceIdService'de nihai olarak bildirilir ve geçersiz kılınamaz. Bununla birlikte, startService () kullanarak hizmeti başlattığımızda, hizmet zaten çalışıyorsa, orijinal örneği kullanılır (ki bu iyidir). Bizim onCreate () (yukarıda tanımlanan) da çağrıldı !.

Bunu MainActivity'nin başlangıcında veya örnek kimliğine ihtiyacınız olduğunu düşündüğünüz her noktada kullanın.

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

Ve sonunda,

Utility.getFirebaseInstanceId(getApplicationContext())

Not , sen detayli getFirebaseInstanceId yöntemine startservice () kodunu hareket ettirmeye çalışarak bu artırabilir.


Uygulamayı sıfırlarsanız / ilk kez çalıştırırsanız, belirtecin yenilenmesi biraz zaman alır. Böylece, bir veya iki dakika boyunca "varsayılan" dizesini alacaksınız.
Varun Garg

0
    [Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
class MyFirebaseIIDService: FirebaseInstanceIdService
{
    const string TAG = "MyFirebaseIIDService";
    NotificationHub hub;

    public override void OnTokenRefresh()
    {
        var refreshedToken = FirebaseInstanceId.Instance.Token;
        Log.Debug(TAG, "FCM token: " + refreshedToken);
        SendRegistrationToServer(refreshedToken);
    }

    void SendRegistrationToServer(string token)
    {
        // Register with Notification Hubs
        hub = new NotificationHub(Constants.NotificationHubName,
                                    Constants.ListenConnectionString, this);
        Employee employee = JsonConvert.DeserializeObject<Employee>(Settings.CurrentUser);
        //if user is not logged in 
        if (employee != null)
        {
            var tags = new List<string>() { employee.Email};
            var regID = hub.Register(token, tags.ToArray()).RegistrationId;

            Log.Debug(TAG, $"Successful registration of ID {regID}");
        }
        else
        {
            FirebaseInstanceId.GetInstance(Firebase.FirebaseApp.Instance).DeleteInstanceId();
            hub.Unregister();
        }
    }
}

0

FirebaseInstanceIdService

Bu sınıf kullanımdan kaldırıldı. FirebaseMessagingService'te onNewToken'ı geçersiz kılma lehine. Bu uygulandığında, bu hizmet güvenli bir şekilde kaldırılabilir.

Bunu yapmanın yeni yolu, onNewTokenyöntemi geçersiz kılmak olacaktır .FirebaseMessagingService

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

Ayrıca hizmeti Manifest.xml dosyasına eklemeyi unutmayın.

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

0

Cihazımı nasıl güncellerim

İlk olarak oturum açtığımda, kullanıcı koleksiyonunun altındaki ilk cihaz jetonunu ve mevcut oturum açmış kullanıcıyı gönderiyorum.

Bundan sonra, sadece geçersiz onNewToken(token:String)skinTenimde FirebaseMessagingService()ve yeni bir jeton o kullanıcı için oluşturulan eğer sadece bu değeri güncellemek

class MyFirebaseMessagingService: FirebaseMessagingService() {
    override fun onMessageReceived(p0: RemoteMessage) {
        super.onMessageReceived(p0)
    }

    override fun onNewToken(token: String) {
    super.onNewToken(token)
    val currentUser= FirebaseAuth.getInstance().currentUser?.uid
    if(currentUser != null){
        FirebaseFirestore.getInstance().collection("user").document(currentUser).update("deviceToken",token)
    }
 }
} 

Uygulamanız her açıldığında yeni bir jeton olup olmadığını kontrol eder, kullanıcı henüz oturum açmadıysa jetonu güncellemez, kullanıcı zaten oturum açmışsa newToken

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.