Javascript 如何解决与React-Native设备信息相关的React-Native Firebase错误(messaging().getToken())

Javascript 如何解决与React-Native设备信息相关的React-Native Firebase错误(messaging().getToken()),javascript,typescript,react-native,react-native-firebase,react-native-device-info,Javascript,Typescript,React Native,React Native Firebase,React Native Device Info,我正在将react本机设备信息从v2迁移到v3,我有一个突破性的变化。在更新软件包之前,一切正常。错误出现在所有模拟器和真实设备上 我得到的错误是: NativeFirebaseError: [messaging/unregistered] You must be registered for remote notifications before calling get token, see messaging().registerForRemoteNotifications() or req

我正在将react本机设备信息从v2迁移到v3,我有一个突破性的变化。在更新软件包之前,一切正常。错误出现在所有模拟器和真实设备上

我得到的错误是:

NativeFirebaseError: [messaging/unregistered] You must be registered for remote notifications before calling get token, see messaging().registerForRemoteNotifications() or requestPermission().
环境信息:

   System:
    OS: macOS 10.15.4
    CPU: (8) x64 Intel(R) Core(TM) i7-6920HQ CPU @ 2.90GHz
    Memory: 6.44 GB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.14.0 - ~/.nvm/versions/node/v12.14.0/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.13.4 - ~/.nvm/versions/node/v12.14.0/bin/npm
  SDKs:
    iOS SDK:
      Platforms: iOS 13.4, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 28, 29
      Build Tools: 28.0.3, 29.0.3
      System Images: android-28 | Google Play Intel x86 Atom
  IDEs:
    Android Studio: 3.6 AI-192.7142.36.36.6241897
    Xcode: 11.4.1/11E503a - /usr/bin/xcodebuild
  npmPackages:
    react: 16.12.0 => 16.12.0 
    react-native: 0.61.5 => 0.61.5 
  npmGlobalPackages:
    create-react-native-app: 2.0.2
    react-native-cli: 2.0.1
    react-native-debugger-open: 0.3.24
我的代码:

export interface LoginParams {
    token?: string;
    useProduct?: string;
    useUser?: string;
    ssoToken?: string;
}

// TODO: Should be switched out with tv-ui-common once the whole app starts using Product model.
interface AuthenticationResponse {
    noCacheToken: string;
    products: ProductData[];
    currentUserId: number;
}
interface ProductsResponse {
    currentProductCode: string;
    products: ProductData[];
}

const getInitialIsLoggedIn = () => false;
const getInitialAuthenticating = () => false;
const getInitialProducts = () => [];
const getInitialSelectedProduct = () => null;
const getInitialCurrentUserId = () => null;

export default class AuthenticationStore {
    private static async authenticate({ token, useProduct, useUser, ssoToken }: LoginParams) {
        const params = new URLSearchParams();
        params.append('ui', UI);
        params.append('uuid', DeviceInfo.getUniqueId());
        params.append('model', DeviceInfo.getSystemName());
        params.append('hwVersion', DeviceInfo.getModel());
        params.append('swVersion', DeviceInfo.getSystemVersion());
        params.append('uiVersion', getUiVersion());
        if (useProduct) {
            params.append('useProduct', useProduct);
        }
        if (useUser) {
            params.append('useUser', useUser);
        }

        try {
            const notificationToken = await messaging().getToken();
            params.append('pushToken', notificationToken);
            console.log(notificationToken, 'notificationToken');
        } catch (error) {
            // iPhone Simulator does not give a token
            console.log("error", error);
        }

        try {
            // If we have token, meaning user authenticated via TV pairing
            if (token) {
                params.append('token', token);
                return await Api.post<AuthenticationResponse>(
                    'authentication/token',
                    params.toString(),
                    undefined,
                    '3.0',
                );
            }
            if (ssoToken) {
                params.append('ssoToken', ssoToken);
            }
            return await Api.post<AuthenticationResponse>(
                'authentication/sso',
                params.toString(),
                undefined,
                '3.0',
            );
        } catch (error) {
            console.log('err', error);
            if (error.response.status === 423) {
                throw new ProductNotAvailableError(error.response.data.products);
            } else {
                throw error;
            }
        }
    }

    @observable public isLoggedIn = getInitialIsLoggedIn();
    @observable public authenticating = getInitialAuthenticating();
    @observable public products: ProductData[] = getInitialProducts();
    @observable public selectedProduct: ProductData | null = getInitialSelectedProduct();
    @observable public currentUserId: number | null = getInitialCurrentUserId();

    constructor() {
        this.registerPushNotificationToken = this.registerPushNotificationToken.bind(this);
        this.loadProducts = this.loadProducts.bind(this);
    }

    @action public reset() {
        this.isLoggedIn = getInitialIsLoggedIn();
        this.authenticating = getInitialAuthenticating();
        this.products = getInitialProducts();
        this.selectedProduct = getInitialSelectedProduct();
        this.currentUserId = getInitialCurrentUserId();
    }

    public async registerPushNotificationToken(token: string) {
        if (this.isLoggedIn) {
            await Api.post('push-token-update', { token }, undefined, '3.0');
        }
    }

    public async login(params: LoginParams = {}): Promise<boolean> {
        this.setAuthenticating(true);

        try {
            const response = await AuthenticationStore.authenticate(params);
            setNoCacheToken(response.data.noCacheToken);

            const products = response.data.products || [];

            this.setProducts(products);
            if (response.status === 202) {
                if (products.length === 1) {
                    const [product] = products;
                    return this.login({ useProduct: product.code });
                }
                if (products.length > 1) {
                    throw new ProductNotSelectedError();
                }
            }
            this.setSelectedProduct(products[0]);

            this.setAuthenticating(false, true, response.data.currentUserId);
            analytics().setUserId(response.data.currentUserId.toString());
        } catch (error) {
            this.setAuthenticating(false, false);

            if (error.response && error.response.status === 401) {
                if (error.response.data.errorCode === 'E_UNAUTHORIZED') {
                    // Silently fail error if user was not authenticated while doing sso request.
                    // We do not need to handle that 'error'. It's common case for cookies
                    // to expire.
                    return false;
                }
                throw new NoProductsError();
            }
            if (
                (error.response && error.response.status === 400)
                || error instanceof ProductNotSelectedError
            ) {
                throw error;
            } else if (error instanceof ProductNotAvailableError) {
                // Product is suspended or in debt and thus not usable

                const selectedProduct = error.products.find(
                    product => product.code === params.useProduct,
                );
                this.setProducts(error.products, selectedProduct);
                throw error;
            } else {
                // Something went wrong with authentication on server side.
                throw new Error(`Unexpected authentication error: ${error}`);
            }
        }

        return this.isLoggedIn;
    }

    public async loadProducts() {
        try {
            // Logged in version of fetching products
            const { data: { products, currentProductCode } } = await Api.get<ProductsResponse>('products');
            const selectedProduct = products.find(product => product.code === currentProductCode);
            this.setProducts(products, selectedProduct);
        } catch (error) {
            if (error.response.status === 401) {
                // Logged out version of fetching products
                try {
                    const response = await AuthenticationStore.authenticate({});
                    const products = response.data.products || [];
                    this.setProducts(products);
                } catch (loginError) {
                    // TODO: Handle error
                }
            }
            // TODO: Handle failed request on loading products
        }
    }

    @action public setAuthenticating(
        authenticating: boolean = false,
        isLoggedIn: boolean = this.isLoggedIn,
        currentUserId: number | null = this.currentUserId,
    ) {
        this.authenticating = authenticating;
        this.isLoggedIn = isLoggedIn;
        this.currentUserId = this.isLoggedIn ? currentUserId : null;
    }

    @action private setProducts(
        products: ProductData[],
        selectedProduct: ProductData | null = null,
    ) {
        this.products = products;
        this.setSelectedProduct(selectedProduct);
    }

    @action private setSelectedProduct(product: ProductData | null = null) {
        this.selectedProduct = product;
    }
}
导出接口登录图{
令牌?:字符串;
useProduct?:字符串;
useUser?:字符串;
ssoToken?:字符串;
}
//待办事项:一旦整个应用程序开始使用产品型号,应使用tv ui common关闭。
接口身份验证响应{
noCacheToken:string;
产品:ProductData[];;
currentUserId:数字;
}
接口产品响应{
currentProductCode:字符串;
产品:ProductData[];;
}
const getInitialIsLoggedIn=()=>false;
const getInitialAuthentication=()=>false;
常量getInitialProducts=()=>[];
const getInitialSelectedProduct=()=>null;
const getInitialCurrentUserId=()=>null;
导出默认类AuthenticationStore{
私有静态异步身份验证({token,useProduct,useUser,ssoToken}:LoginParms){
const params=新的URLSearchParams();
参数append('ui',ui);
params.append('uuid',DeviceInfo.getUniqueId());
append('model',DeviceInfo.getSystemName());
append('hwVersion',DeviceInfo.getModel());
append('swVersion',DeviceInfo.getSystemVersion());
append('uiVersion',getUiVersion());
如果(使用产品){
参数append('useProduct',useProduct);
}
如果(使用用户){
参数append('useUser',useUser);
}
试一试{
const notificationToken=等待消息传递().getToken();
params.append('pushToken',notificationToken);
log(notificationToken,'notificationToken');
}捕获(错误){
//iPhone模拟器不提供令牌
console.log(“错误”,error);
}
试一试{
//如果我们有令牌,这意味着用户通过TV配对进行身份验证
如果(令牌){
参数append('token',token);
返回等待Api.post(
“身份验证/令牌”,
params.toString(),
未定义,
'3.0',
);
}
如果(ssoToken){
参数append('ssoToken',ssoToken);
}
返回等待Api.post(
“身份验证/sso”,
params.toString(),
未定义,
'3.0',
);
}捕获(错误){
console.log('err',error);
if(error.response.status==423){
抛出新产品NotAvailableError(error.response.data.products);
}否则{
投掷误差;
}
}
}
@可观测公共isLoggedIn=getInitialIsLoggedIn();
@可观察的公共身份验证=GetInitialAuthentication();
@可观察的公共产品:ProductData[]=getInitialProducts();
@可观察的公共选择产品:ProductData | null=getInitialSelectedProduct();
@可观察的公共currentUserId:number | null=getInitialCurrentUserId();
构造函数(){
this.registerPushNotificationToken=this.registerPushNotificationToken.bind(this);
this.loadProducts=this.loadProducts.bind(this);
}
@行动公众重置(){
this.isLoggedIn=getInitialIsLoggedIn();
this.authentication=getInitialAuthentication();
this.products=getInitialProducts();
this.selectedProduct=getInitialSelectedProduct();
this.currentUserId=getInitialCurrentUserId();
}
公共异步注册表PushNotificationToken(标记:字符串){
if(this.isLoggedIn){
wait Api.post('push-token-update',{token},未定义,'3.0');
}
}
公共异步登录(params:LoginParams={}):承诺{
此项。设置身份验证(true);
试一试{
const response=wait AuthenticationStore.authenticate(参数);
setNoCacheToken(response.data.noCacheToken);
const products=response.data.products | |[];
这是一套产品(产品);
如果(response.status==202){
如果(products.length==1){
常数[产品]=产品;
返回this.login({useProduct:product.code});
}
如果(产品长度>1){
抛出新产品NotSelectedError();
}
}
此.setselected产品(产品[0]);
this.setAuthentication(false、true、response.data.currentUserId);
analytics().setUserId(response.data.currentUserId.toString());
}捕获(错误){
此设置验证(false,false);
if(error.response&&error.response.status==401){
如果(error.response.data.errorCode==='E_UNAUTHORIZED'){
//如果用户在执行sso请求时未经过身份验证,则出现静默失败错误。
//我们不需要处理那个“错误”。这是cookies的常见情况
//到期。
返回false;
}
抛出新的NoProductsError();
}
如果(
(error.response&&error.response.status==400)
||ProductNotSelected的错误实例错误
) {
投掷误差;
}else if(ProductNotAvailableError的错误实例){
//产品被暂停或负债,因此无法使用
const selectedProduct=error.products.find(
product=>product.code==params.useProduct,
);
此.setProducts(error.products,selec