簡體   English   中英

在 Firebase 通知注冊和設備令牌后觸發 Angular 應用程序邏輯

[英]Trigger Angular app logic after Firebase notifications registration and device token

我希望在我的 Angular 13 Ionic 6 應用程序中實現此邏輯:在應用程序啟動時,獲取設備令牌。 使用設備令牌,我執行一些邏輯(查詢數據庫以查看此設備是已知的還是新的)並根據結果 - 路由到頁面:未知設備的注冊頁面和現有的一些主頁。 在這些頁面中的任何一個出現之前,我可能會展示一個微調器或其他東西。

我無法達到使用有效令牌調用 appLauncher() function 的情況。 我嘗試將令牌存儲在本地存儲中 - 但我無法與正在填充的存儲異步。 我嘗試的最后一件事(此處顯示)是使用 @Output 發射器 - 從未調用過 appLauncher。 這是我所擁有的:

app.component.ts - 在這里我還嘗試了嵌套的 Promises。 如果令牌已在本地存儲中找到,並且僅當這是首次運行時,我才可以快速解決第一個 promise - 我將等待一段時間,直到填充此存儲。 但是這里調用 appLauncher 也失敗了,我相信這不是一個優雅的實現方式。 我更喜歡在這里運行節目的反應事件。

import { Component } from '@angular/core';
import { AlertController, Platform } from '@ionic/angular';
import { Router } from '@angular/router';

import { SplashScreen } from '@capacitor/splash-screen';

import { FbNotificationsService } from './services/fb-notifications.service';
import { TigergraphService } from "./services/tigergraph.service";
import { get, set, remove } from './services/storage.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  deviceId: string;
  private _tgdb;
  constructor(
    private platform: Platform,
    private fbNotifications: FbNotificationsService,
    private route: Router,
    public tgdb: TigergraphService,
    public LoggerService: LoggerService,
    private alertCtrl: AlertController
  ) {
    this.initializeApp();
  }

 
  initializeApp() {
    this.platform.ready().then(async (source) => {
      console.log("platform source: " + source);
      // Trigger the push setup 
      this.fbNotifications.initPush();

      get('device-token').then(
        (res) => {
          if (res==null) {
            console.log('No token returned - need to wait for the promise to complete');
            
            return new Promise(function(resolve, reject) {
              setTimeout(function() {
                  // Fetch token again after a delay
                  get('device-token').then(
                    (res) => {
                      resolve(res);
                    }
                  )
                  
               }, 15000);
          });
          } else {
            console.log('app main just received a device token: ', res.value);
            this.appLauncher(res.value);
          }
      },
        (err) => {
          console.error('Error in receiving device token in app main: ', err);
      }).then(function(resToken2: any) {
        console.log('Obtained the device token on second attempt: ', resToken2);
        if (resToken2) {
          this.appLauncher(resToken2);
        }        
    });


      try {
        await SplashScreen.hide();
       } catch (err) {
        console.log('This is normal in a browser: ', err);
       }
    });
  }


  deviceTokenReceived(event) {
    console.log('Device Token received from emitter: ', event);
    if (event) {
      this.appLauncher(event);
    }
  }

  //Based on deviceId and if existing user or not - route
  appLauncher(deviceId: string) {
    console.log('Entered appLauncher: ', deviceId);
    this._tgdb.runQuery("getPersonByDeviceId", {"DeviceId": deviceId}).subscribe(
      res => {
        if(res == null){
          //No person found in DB - need registration routing
          console.log('No person found with DeviceID. Routing to signup');
          this.route.navigate(['/signup']); 
          
        } else {
          //person exists in db
          console.log('TG Query Result PErson by DeviceID: ' + JSON.stringify(res) + ' firstName: ' + res[0].vPerson[0].attributes.firstName);
          set('curr-person', res[0].vPerson[0].attributes); //Store locally for use throughout the app
          console.log('curr-person just saved');
          //Rout based on user type
          
        }
      },
      err => {
        console.log('TG Query Error: ' + err.description);
        //Route to some error page?
        this.showAlert("Network Error", "Ooooops. I can't find any Internet at this time");
      }
  );
  }
}

app.component.html - 僅用於捕獲發出的 @Output 變量事件 - 但從未真正起作用:

<ion-app>
  <ion-item (deviceId)="deviceTokenReceived($event)"></ion-item>
  <ion-router-outlet></ion-router-outlet>
</ion-app>

Firebase服務:

import { EventEmitter, Injectable, Output } from '@angular/core';
import {ActionPerformed, PushNotifications, PushNotificationSchema, Token} from '@capacitor/push-notifications';
import {  Capacitor } from '@capacitor/core';

import { get, set, remove } from './storage.service';

@Injectable({
  providedIn: 'root'
})
export class FbNotificationsService {

  @Output('deviceId') deviceId = new EventEmitter<string>();

  constructor() {}
 
  initPush() {
    if (Capacitor.getPlatform() !== 'web') {
      this.registerPush()
    } else {
      
    }
  }
 
  private registerPush() {
    PushNotifications.requestPermissions().then((permission) => {
      if (permission.receive === 'granted') {
        // Register with Apple / Google to receive push via APNS/FCM
        console.log('FB Permission granted');
        PushNotifications.register(); //Registers app to receive notifications
      } else {
        // No permission for push granted by user on iOS
        console.log('FB NO permissions granted');
      }
    });
 
    PushNotifications.addListener(
      'registration',
      (token: Token) => {
        console.log('My token: ' + JSON.stringify(token));
        //This is the device token.
        this.deviceId.emit(token.value);
        set('device-token', token.value).then( () => {
          remove('curr-person'); //clear local store of current person in app init
        }); //to be picked up in registration
        
      });
 
    PushNotifications.addListener('registrationError', (error: any) => {
      console.log('Error: ' + JSON.stringify(error));
      //Alert that the registration of this device for notifications failed
    });
 
  }
}

為簡潔起見,這里跳過了存儲服務,它只是使用@capacitor/storage 中的存儲服務來獲取/設置令牌值。

請問,這個工作的正確方法是什么? 謝謝!

感謝您的報告 我建議您使用 BehaviorSubject 來解決問題。 嘗試這個。

  1. 在 FBNotificationService.ts 文件中
onFCMTokenChanged: BehaviorSubject<string> = new BehaviorSubject("");
PushNotifications.addListener('registration', (token: Token) => {
   console.log('My token: ' + JSON.stringify(token));
   //This is the device token.
   this.onFCMTokenChanged.next(token);
});
  1. 在 construtor() function 內的 app.component.ts 文件中
this.fbNotifications.onFCMTokenChanged.pipe(takeUntil(this._unsubscribeAll)).subscribe(token => {
   if ((token)&&(!this.appLaunched)) {
      this.appLaunched = true;
      this.appLauncher(token);
   }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM