Bagaimana cara menangani situasi, ketika pengguna log out dari aplikasi saya dan saya tidak ingin dia untuk menerima pemberitahuan untuk perangkat.
Aku mencoba
FirebaseInstanceId.getInstance().deleteToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)
Tapi aku masih menerima pemberitahuan untuk perangkat saya's registration_id
.
Saya juga membuat yakin bahwa ini adalah tanda saya harus menghapus:
FirebaseInstanceId.getInstance().getToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)
atau hanya FirebaseInstanceId.getInstance().method gettoken()
).
Saya juga mencoba FirebaseInstanceId.getInstance().deleteInstanceId()
, tapi kemudian waktu berikutnya saya sebut FirebaseInstanceId.getInstance.method gettoken
aku menerima null (bekerja pada percobaan kedua).
Saya kira, setelah deleteInstanceId
aku bisa segera memanggil method gettoken()
lagi, tapi sepertinya hack. Dan juga ada's jawaban ini yang menyatakan bahwa seharusnya't harus dilakukan, tapi itu mengusulkan menghapus token yang rupanya doesn't bekerja.
Jadi apa adalah metode yang tepat untuk menangani hal ini?
Oke. Jadi saya berhasil melakukan beberapa pengujian dan menyimpulkan sebagai berikut:
deleteToken()
adalah mitra dari method gettoken(String, String)
, tapi tidak untuk method gettoken()
.Ini hanya bekerja jika Pengirim ID anda akan melewati yang berbeda Sender ID (bukan ID yang sama yang dapat dilihat di google-jasa.json). Misalnya, anda ingin untuk memungkinkan Server yang berbeda untuk mengirim ke aplikasi anda, anda menelepon method gettoken("THEIR_SENDER_ID", "FCM")
untuk memberikan otorisasi untuk mengirim ke aplikasi anda. Ini akan mengembalikan sejumlah yang berbeda token pendaftaran yang sesuai hanya untuk pengirim tertentu.
Di masa depan, jika anda memilih untuk menghapus mereka otorisasi untuk mengirim ke aplikasi anda, anda'll maka harus menggunakan deleteToken("THEIR_SENDER_ID", "FCM")
. Ini akan membatalkan yang bersangkutan token, dan ketika Pengirim mencoba untuk mengirim pesan, seperti yang dimaksudkan perilaku, mereka akan menerima NotRegistered
kesalahan.
deleteInstanceId()
.Khusus menyebutkan hal ini jawaban @Prince, secara khusus kode sampel untuk membantu saya dengan ini.
Seperti @MichałK sudah lakukan dalam posting-nya, setelah memanggil deleteInstanceId()
, method gettoken()
harus disebut dalam rangka untuk mengirim permintaan untuk token baru. Namun, anda don't harus menyebutnya kedua kalinya. Jadi selama onTokenRefresh()
onNewToken()
dilaksanakan, seharusnya secara otomatis memicu menyediakan token baru.
Untuk jangka pendek, deleteInstanceId()
> method gettoken()
> cek onTokenRefresh()
onNewToken()
.
Catatan: Memanggil deleteInstanceId()
ini tidak hanya akan menghapus token untuk aplikasi anda sendiri. Ini akan menghapus semua topik langganan dan semua tanda-tanda lain yang berhubungan dengan contoh aplikasi.
Apakah anda positif anda're calling deleteToken()
benar? Nilai untuk penonton harus (juga dilihat dari jawaban saya bahwa anda terhubung) adalah "set untuk aplikasi server's ID pengirim". Anda're melewati getId()
nilai yang tidak sama dengan Sender ID (ini berisi contoh aplikasi nilai id). Juga, bagaimana anda mengirim pesan (Aplikasi Server atau Pemberitahuan Console)?
method gettoken()
dan method gettoken(String, String)
mengembalikan token yang berbeda. Lihat jawaban saya di sini.
saya juga mencoba
FirebaseInstanceId.getInstance().deleteInstanceId()
, tapi kemudian waktu berikutnya saya sebutFirebaseInstanceId.getInstance.method gettoken
aku menerima null (bekerja pada kedua mencoba).
It's mungkin karena pertama kali anda're memanggil method gettoken()
, it's masih sedang dibuat. It's hanya ditujukan perilaku.
saya kira, setelah
deleteInstanceId
aku bisa segera memanggilmethod gettoken()
lagi, tapi sepertinya hack.
Tidak benar-benar. It's bagaimana anda'll mendapatkan dihasilkan baru (asalkan sudah dihasilkan) token. Jadi saya pikir itu's baik-baik saja.
Saya bekerja pada masalah yang sama, ketika saya sudah selesai saya logout()
dari aplikasi saya. Tapi masalahnya adalah bahwa setelah log out, saya masih mendapatkan pemberitahuan push dari Firebase. Saya mencoba untuk menghapus Firebase token. Tapi setelah menghapus token di logout()
metode, itu adalah null
ketika saya query untuk itu saya login()
metode. Setelah bekerja 2 hari akhirnya saya mendapat solusi.
logout()
metode, menghapus Firebase token di latar belakang karena anda tidak dapat menghapus Firebase token dari thread utamabaru AsyncTask<Batal,Batal,Batal>() { @Override protected Void doInBackground(Void... params) { mencoba { FirebaseInstanceId.getInstance().deleteInstanceId(); } catch (IOException e) { e.printStackTrace(); } return null; }
@Override protected void onPostExecute(Void hasil) { // Memanggil Aktivitas anda di mana anda ingin ke tanah setelah log out } }.execute();
login()
metode, menghasilkan Firebase token lagi.baru AsyncTask<Batal,Batal,Batal>() { @Override protected Void doInBackground(Void... params) { String token = FirebaseInstanceId.getInstance().method gettoken(); // Digunakan untuk mendapatkan firebase token sampai nol sehingga akan menyelamatkan anda dari null pointer exeption sementara(token == null) { token = FirebaseInstanceId.getInstance().method gettoken(); } return null; } @Override protected void onPostExecute(Void hasil) { } }.execute();
Saya melakukan penelitian singkat tentang apa yang akan menjadi solusi yang paling elegan untuk mendapatkan kembali kontrol penuh (berlangganan dan berhenti berlangganan FCM) seperti sebelumnya. Mengaktifkan dan menonaktifkan FCM setelah pengguna masuk atau keluar.
Langkah 1. - Mencegah auto inisialisasi
Firebase sekarang menangani InstanceID
dan segala sesuatu yang lain yang perlu untuk menghasilkan token pendaftaran. Pertama-tama anda perlu untuk mencegah auto inisialisasi. Berdasarkan official set-up dokumentasi yang anda butuhkan untuk menambahkan ini meta-data nilai untuk anda AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<application>
<!-- FCM: Disable auto-init -->
<meta-data android:name="firebase_messaging_auto_init_enabled"
android:value="false" />
<meta-data android:name="firebase_analytics_collection_enabled"
android:value="false" />
<!-- FCM: Receive token and messages -->
<service android:name=".FCMService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
Sekarang anda dinonaktifkan otomatis permintaan token proses. Pada saat yang sama anda memiliki pilihan untuk mengaktifkan lagi pada saat runtime dengan kode.
Langkah 2. - Menerapkan enableFCM()
dan disableFCM()
fungsi
Jika anda mengaktifkan auto inisialisasi lagi maka anda menerima token baru segera, jadi ini adalah cara sempurna untuk menerapkan enableFCM()
metode.
Semua berlangganan informasi ditugaskan untuk InstanceID, jadi ketika anda menghapusnya kemudian memulai untuk berhenti berlangganan semua topik. Pada cara ini, anda mampu melaksanakan disableFCM()
metode, baru saja kembali dari auto-init sebelum anda menghapusnya.
public class FCMHandler {
public void enableFCM(){
// Enable FCM via enable Auto-init service which generate new token and receive in FCMService
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
}
public void disableFCM(){
// Disable auto init
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
new Thread(() -> {
try {
// Remove InstanceID initiate to unsubscribe all topic
// TODO: May be a better way to use FirebaseMessaging.getInstance().unsubscribeFromTopic()
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
Langkah 3. - FCMService
implementasi - token dan menerima pesan
Pada langkah terakhir yang perlu anda menerima token baru dan mengirim langsung ke server anda. Lainnya tangan anda'll menerima data anda pesan dan lakukan saja apa yang anda inginkan.
public class FCMService extends FirebaseMessagingService {
@Override
public void onNewToken(String token) {
super.onNewToken(token);
// TODO: send your new token to the server
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String from = remoteMessage.getFrom();
Map data = remoteMessage.getData();
if (data != null) {
// TODO: handle your message and data
sendMessageNotification(message, messageId);
}
}
private void sendMessageNotification(String msg, long messageId) {
// TODO: show notification using NotificationCompat
}
}
Saya pikir ini adalah solusi yang jelas, sederhana dan transparan. Saya diuji dalam lingkungan produksi dan's bekerja. Saya berharap itu membantu.
Pengusaha harus pernah membatalkan registrasi aplikasi klien sebagai mekanisme untuk logout atau untuk beralih di antara pengguna, untuk alasan berikut:
pendaftaran token isn't berhubungan dengan login pengguna. Jika aplikasi client membatalkan pendaftaran dan kemudian re-register, aplikasi ini dapat menerima pendaftaran sama token atau token pendaftaran.
pembatalan pendaftaran dan pendaftaran ulang di masing-masing dapat mengambil hingga lima menit untuk menyebarkan. Selama waktu ini, pesan dapat ditolak karena tidak terdaftar negara, dan pesan dapat pergi ke salah pengguna. Untuk membuat pastikan bahwa pesan yang pergi untuk pengguna yang dituju:
aplikasi server dapat mempertahankan pemetaan antara pengguna saat ini dan token pendaftaran.
aplikasi klien dapat kemudian periksa untuk memastikan bahwa pesan yang diterima sesuai dengan login pengguna.
kutipan ini dari usang google dokumentasi
Tetapi ada alasan untuk percaya ini adalah masih benar - bahkan jika dokumentasi di atas adalah usang.
Anda dapat mengamati hal ini di sini - memeriksa bagaimana mereka melakukannya di codelab https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js
dan di sini https://github.com/firebase/friendlychat-web/blob/master/cloud-functions/public/scripts/main.js
Sejak method gettoken()
adalah usang, menggunakan getInstanceId()
untuk meregenerasi token baru sebagai gantinya. Ini memiliki efek yang sama.
public static void resetInstanceId() {
new Thread(new Runnable() {
@Override
public void run() {
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
FirebaseInstanceId.getInstance().getInstanceId();
Helper.log(TAG, "InstanceId removed and regenerated.");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
Aku tahu aku terlambat untuk pesta. deleteInstanceId()
harus disebut dari latar belakang benang sejak itu's pemblokiran panggilan. Hanya memeriksa metode deleteInstanceId()
di [FirebaseInstanceId()](https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId.html#deleteInstanceId()) kelas.
@WorkerThread
public void deleteInstanceId() throws IOException {
if (Looper.getMainLooper() == Looper.myLooper()) {
throw new IOException("MAIN_THREAD");
} else {
String var1 = zzh();
this.zza(this.zzal.deleteInstanceId(var1));
this.zzl();
}
}
Anda dapat memulai IntentService untuk menghapus contoh id dan data-data yang berhubungan dengan itu.
Sebut saja deleteToken metode di Thread latar belakang di atas Logout:
FirebaseInstanceId.getInstance().deleteToken(getString(R.string.gcm_defaultSenderId), "FCM")
Argumen pertama mengambil SenderID seperti yang didefinisikan dalam FireBaseConsole
Dibutuhkan beberapa detik untuk update - dan setelah itu, anda tidak akan lagi mendapatkan FCM pemberitahuan.