Javascript 如何解决与React-Native设备信息相关的React-Native Firebase错误(messaging().getToken())
我正在将react本机设备信息从v2迁移到v3,我有一个突破性的变化。在更新软件包之前,一切正常。错误出现在所有模拟器和真实设备上 我得到的错误是: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
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