如何解决与react-native-device-info相关的React Native Firebase错误(messaging().getToken())

Ser*_*afa 10 javascript typescript react-native react-native-firebase react-native-device-info

我正在将react-native-device-info从v2迁移到v3,并且我有一个重大变化。在更新包之前,一切正常。该错误出现在所有模拟器和真实设备上。

\n\n

我得到的错误是:

\n\n
NativeFirebaseError: [messaging/unregistered] You must be registered for remote notifications before calling get token, see messaging().registerForRemoteNotifications() or requestPermission().\n
Run Code Online (Sandbox Code Playgroud)\n\n

环境信息:

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

我的代码:

\n\n
export interface LoginParams {\n    token?: string;\n    useProduct?: string;\n    useUser?: string;\n    ssoToken?: string;\n}\n\n// TODO: Should be switched out with tv-ui-common once the whole app starts using Product model.\ninterface AuthenticationResponse {\n    noCacheToken: string;\n    products: ProductData[];\n    currentUserId: number;\n}\ninterface ProductsResponse {\n    currentProductCode: string;\n    products: ProductData[];\n}\n\nconst getInitialIsLoggedIn = () => false;\nconst getInitialAuthenticating = () => false;\nconst getInitialProducts = () => [];\nconst getInitialSelectedProduct = () => null;\nconst getInitialCurrentUserId = () => null;\n\nexport default class AuthenticationStore {\n    private static async authenticate({ token, useProduct, useUser, ssoToken }: LoginParams) {\n        const params = new URLSearchParams();\n        params.append(\'ui\', UI);\n        params.append(\'uuid\', DeviceInfo.getUniqueId());\n        params.append(\'model\', DeviceInfo.getSystemName());\n        params.append(\'hwVersion\', DeviceInfo.getModel());\n        params.append(\'swVersion\', DeviceInfo.getSystemVersion());\n        params.append(\'uiVersion\', getUiVersion());\n        if (useProduct) {\n            params.append(\'useProduct\', useProduct);\n        }\n        if (useUser) {\n            params.append(\'useUser\', useUser);\n        }\n\n        try {\n            const notificationToken = await messaging().getToken();\n            params.append(\'pushToken\', notificationToken);\n            console.log(notificationToken, \'notificationToken\');\n        } catch (error) {\n            // iPhone Simulator does not give a token\n            console.log("error", error);\n        }\n\n        try {\n            // If we have token, meaning user authenticated via TV pairing\n            if (token) {\n                params.append(\'token\', token);\n                return await Api.post<AuthenticationResponse>(\n                    \'authentication/token\',\n                    params.toString(),\n                    undefined,\n                    \'3.0\',\n                );\n            }\n            if (ssoToken) {\n                params.append(\'ssoToken\', ssoToken);\n            }\n            return await Api.post<AuthenticationResponse>(\n                \'authentication/sso\',\n                params.toString(),\n                undefined,\n                \'3.0\',\n            );\n        } catch (error) {\n            console.log(\'err\', error);\n            if (error.response.status === 423) {\n                throw new ProductNotAvailableError(error.response.data.products);\n            } else {\n                throw error;\n            }\n        }\n    }\n\n    @observable public isLoggedIn = getInitialIsLoggedIn();\n    @observable public authenticating = getInitialAuthenticating();\n    @observable public products: ProductData[] = getInitialProducts();\n    @observable public selectedProduct: ProductData | null = getInitialSelectedProduct();\n    @observable public currentUserId: number | null = getInitialCurrentUserId();\n\n    constructor() {\n        this.registerPushNotificationToken = this.registerPushNotificationToken.bind(this);\n        this.loadProducts = this.loadProducts.bind(this);\n    }\n\n    @action public reset() {\n        this.isLoggedIn = getInitialIsLoggedIn();\n        this.authenticating = getInitialAuthenticating();\n        this.products = getInitialProducts();\n        this.selectedProduct = getInitialSelectedProduct();\n        this.currentUserId = getInitialCurrentUserId();\n    }\n\n    public async registerPushNotificationToken(token: string) {\n        if (this.isLoggedIn) {\n            await Api.post(\'push-token-update\', { token }, undefined, \'3.0\');\n        }\n    }\n\n    public async login(params: LoginParams = {}): Promise<boolean> {\n        this.setAuthenticating(true);\n\n        try {\n            const response = await AuthenticationStore.authenticate(params);\n            setNoCacheToken(response.data.noCacheToken);\n\n            const products = response.data.products || [];\n\n            this.setProducts(products);\n            if (response.status === 202) {\n                if (products.length === 1) {\n                    const [product] = products;\n                    return this.login({ useProduct: product.code });\n                }\n                if (products.length > 1) {\n                    throw new ProductNotSelectedError();\n                }\n            }\n            this.setSelectedProduct(products[0]);\n\n            this.setAuthenticating(false, true, response.data.currentUserId);\n            analytics().setUserId(response.data.currentUserId.toString());\n        } catch (error) {\n            this.setAuthenticating(false, false);\n\n            if (error.response && error.response.status === 401) {\n                if (error.response.data.errorCode === \'E_UNAUTHORIZED\') {\n                    // Silently fail error if user was not authenticated while doing sso request.\n                    // We do not need to handle that \'error\'. It\'s common case for cookies\n                    // to expire.\n                    return false;\n                }\n                throw new NoProductsError();\n            }\n            if (\n                (error.response && error.response.status === 400)\n                || error instanceof ProductNotSelectedError\n            ) {\n                throw error;\n            } else if (error instanceof ProductNotAvailableError) {\n                // Product is suspended or in debt and thus not usable\n\n                const selectedProduct = error.products.find(\n                    product => product.code === params.useProduct,\n                );\n                this.setProducts(error.products, selectedProduct);\n                throw error;\n            } else {\n                // Something went wrong with authentication on server side.\n                throw new Error(`Unexpected authentication error: ${error}`);\n            }\n        }\n\n        return this.isLoggedIn;\n    }\n\n    public async loadProducts() {\n        try {\n            // Logged in version of fetching products\n            const { data: { products, currentProductCode } } = await Api.get<ProductsResponse>(\'products\');\n            const selectedProduct = products.find(product => product.code === currentProductCode);\n            this.setProducts(products, selectedProduct);\n        } catch (error) {\n            if (error.response.status === 401) {\n                // Logged out version of fetching products\n                try {\n                    const response = await AuthenticationStore.authenticate({});\n                    const products = response.data.products || [];\n                    this.setProducts(products);\n                } catch (loginError) {\n                    // TODO: Handle error\n                }\n            }\n            // TODO: Handle failed request on loading products\n        }\n    }\n\n    @action public setAuthenticating(\n        authenticating: boolean = false,\n        isLoggedIn: boolean = this.isLoggedIn,\n        currentUserId: number |\xc2\xa0null = this.currentUserId,\n    ) {\n        this.authenticating = authenticating;\n        this.isLoggedIn = isLoggedIn;\n        this.currentUserId = this.isLoggedIn ? currentUserId : null;\n    }\n\n    @action private setProducts(\n        products: ProductData[],\n        selectedProduct: ProductData | null = null,\n    ) {\n        this.products = products;\n        this.setSelectedProduct(selectedProduct);\n    }\n\n    @action private setSelectedProduct(product: ProductData | null = null) {\n        this.selectedProduct = product;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我在网上查了一下,但似乎找不到任何类似的东西,有人知道我可以尝试什么吗?

\n

小智 -1

该错误表明您需要在调用 getToken 之前请求用户的通知权限。你试过这个吗?https://rnfirebase.io/messaging/usage