FCM error: Service messaging is not available - firebase-cloud-messaging

import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getMessaging } from "firebase/messaging";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyA0dAgRPZLlgULgnOp2MH_3xtVbWPs03Cg",
authDomain: "u-63f99.firebaseapp.com",
projectId: "u-63f99",
storageBucket: "u-63f99.appspot.com",
messagingSenderId: "884933400988",
appId: "1:884933400988:web:0b7e0e37b0f23da236d059",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const fireStore = getFirestore(app);
const messaging = getMessaging(app);
export { auth, fireStore, messaging };
i'm getting this error, i don't know why messaging service is missing while i installed firebase SDK

your problem is probably because you're testing this on localhost (http).
if you look at the console logs you might notice beside that error something like:
code: 'messaging/unsupported-browser'
and cloud messaging only support https connections so you'd have to make your localhost run on https somehow to get it to work :)

Related

How to use firebase push notification using laravel and vue js

I have try to make send push notification to admin user when a customer order a product.
When an admin user logged into dashboard will shown a prompt and if user subscribe the prompt user will get notification when a customer make a order in front end.I have used laravel and vue for backend.(Vue inside the laravel application).I have no idea how to prompt shown when user logged in .I have created a account in firebase and get keys.
All tutorial are based on independent vue js.In my case vue js inside the laravel app.
Where i put code which is get from firebase.?
i have tried with
//app.js
import firebase from "firebase/app";
import { initializeApp } from 'firebase/app';
import '#firebase/messaging';
var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxx.firebaseapp.com",
projectId: "xxxxxxxxx-push",
storageBucket: "xxxxxxx.appspot.com",
messagingSenderId: "xxxxxxxxxxx",
appId: "xxxxxxxxxx:c1bae0304ce23d6eae3ccd",
measurementId: "xxxxxxx"
};
firebase.initializeApp(firebaseConfig);
// Using FCM Messaging
const messaging = firebase.messaging();
messaging.usePublicVapidKey("xxxxxxxxxxx");
// Get FCM Token
messaging.getToken().then((currentToken) => {
if (currentToken) {
console.log("Token: " + currentToken);
} else {
// Show permission request.
console.log('No Instance ID token available. Request permission to generate one.');
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
});
Uncaught TypeError: firebase.messaging is not a function
at Module../resources/js/app.js
The issue is related with the version of Firebase you have installed. I think you have "firebase": "^9.X.X"
You are using the Web version 8 api. You can install v.8 if you like, but I wouldn't recommend it. V9 offers great features like tree shaking.
Here's a solution for firebase v9 :
First things first, I hope your firebaseConfig data is a dummy data, if not, you'll have to create a new firebase project because the data you just published here are sensitive and should be kept hidden.
To answer your question :
You need to import getMessaging in order to interact with FCM :
import { getMessaging, getToken } from "firebase/messaging";
Make sure your initializeApp() is inside a variable:
const app = initializeApp(firebaseConfig);
In order to initialize the messaging service :
const messaging = getMessaging(app);
Retrieving the token :
getToken(messaging, { vapidKey: '<YOUR_PUBLIC_VAPID_KEY_HERE>' }).then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
// ...
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
For more info : Firebase docs

Incorrect redirect link (spotify auth in expo app)

The problem is that the built app doesn't connect to spotify. But it works in dev mode.
Here is the context:
we have react native expo app
trying to connect to spotify via useAuthRequest from expo-auth-session (uses Linking under the hood).
sign-in-container.js:
import SignIn from './sign-in-component.js';
import { connect } from 'react-redux';
import {compose} from "ramda";
import React, {useEffect} from 'react';
import {isLogged} from "../../features/user-authentication/user-authentication-reducer";
import {signIn} from "../../features/user-authentication/user-authentication-saga";
import withGradient from "../../HOCs/with-gradient/with-gradient";
import {makeRedirectUri, useAuthRequest} from "expo-auth-session";
const mapStateToProps = state => ({
isLogged: isLogged(state),
});
const redirectUrl = makeRedirectUri();
const clientId = '***';
const discovery = {
authorizationEndpoint: 'https://accounts.spotify.com/authorize',
tokenEndpoint: 'https://accounts.spotify.com/api/token',
};
export default compose(
connect(mapStateToProps, {signIn}),
withGradient,
)(({ isLogged, signIn, navigation }) => {
const [request, response, promptAsync] = useAuthRequest(
{
clientId: clientId,
scopes: ['user-read-email', 'playlist-modify-public'],
usePKCE: false,
redirectUri: redirectUrl,
},
discovery
);
useEffect(() => {
if (response?.type === 'success') {
const { code } = response.params;
signIn(code);
}
}, [response]);
const handlePressSpotifyButton = () => {
promptAsync().then(() => {
navigation.navigate('Onboarding')
});
};
return <SignIn isLogged={isLogged} onPressSpotifyButton={handlePressSpotifyButton}/>;
});
And getting warning when start the project in dev mode (yarn start):
Linking requires a build-time setting scheme in the project's Expo
config (app.config.js or app.json) for production apps, if it's left
blank, your app may crash. The scheme does not apply to development in
the Expo client but you should add it as soon as you start working
with Linking to avoid creating a broken build. Learn more:
https://docs.expo.io/versions/latest/workflow/linking/
Without scheme it doesn't start via expo publish/expo build
Adding 'exp' as scheme for app.json config
"scheme": "exp"
After publishing get an error incorrect redirect link
redirection link in app:
started locally: exp://192.168.0.159:19000 (works)
published: exp://exp.host/#expo-user-name/my-app (incorrect)
How does the redirection link should look like to work not only in dev mode? Is adding 'exp' as scheme is correct?

Ionic 3's PWA & Firebase Cloud Messaging registration

I was following this article here (which is not complete unfortunately) in attempt to learn how to friend Ionic 3 based PWA and Firebase Cloud Messaging: Push Notifications with FCM
What I did:
as advised in the article added FCM libraries into service-worker.js:
'use strict';
importScripts('./build/sw-toolbox.js');
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-messaging');
firebase.initializeApp({
// get this from Firebase console, Cloud messaging section
'messagingSenderId': '47286327412'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler((payload) => {
console.log('Received background message ', payload);
// here you can override some options describing what's in the message;
// however, the actual content will come from the service sending messages
const notificationOptions = {
icon: '/assets/img/appicon.png'
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});
self.toolbox.options.cache = {
name: 'ionic-cache'
};
// pre-cache our key assets
self.toolbox.precache(
[
'./build/main.js',
'./build/vendor.js',
'./build/main.css',
'./build/polyfills.js',
'index.html',
'manifest.json'
]
);
// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.cacheFirst);
// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;
Then created Firebase Messaging based provider here:
import { Injectable } from "#angular/core";
import * as firebase from 'firebase';
import { Storage } from '#ionic/storage';
#Injectable()
export class FirebaseMessagingProvider {
private messaging: firebase.messaging.Messaging;
private unsubscribeOnTokenRefresh = () => {};
constructor(
private storage: Storage
) {
this.messaging = firebase.messaging();
}
public enableNotifications() {
console.log('Requesting permission...');
return this.messaging.requestPermission().then(() => {
console.log('Permission granted');
// token might change - we need to listen for changes to it and update it
this.setupOnTokenRefresh();
return this.updateToken();
});
}
public disableNotifications() {
this.unsubscribeOnTokenRefresh();
this.unsubscribeOnTokenRefresh = () => {};
return this.storage.set('fcmToken','').then();
}
private updateToken() {
return this.messaging.getToken().then((currentToken) => {
if (currentToken) {
// we've got the token from Firebase, now let's store it in the database
return this.storage.set('fcmToken', currentToken);
} else {
console.log('No Instance ID token available. Request permission to generate one.');
}
});
}
private setupOnTokenRefresh(): void {
this.unsubscribeOnTokenRefresh = this.messaging.onTokenRefresh(() => {
console.log("Token refreshed");
this.storage.set('fcmToken','').then(() => { this.updateToken(); });
});
}
}
And now during app initialization I call enableNotifications() and get error that says that default service worker is not found (404):
A bad HTTP response code (404) was received when fetching the script.
:8100/firebase-messaging-sw.js Failed to load resource: net::ERR_INVALID_RESPONSE
If I move service-worker.js firebase related stuff into default service worker in WWW folder - I get general error from Firebase (Error, failed to register service worker).
QUESTIONS:
- is there a fresh guide on Ionic 3's PWA & FCM?
- at high level what is the difference in registering service workers in Ionic 3 vs Angular? I did watch the tutorial about Angular but can't figure how to do the same in Ionic 3.
UPDATE: the below is valid as of today (02/12/2018) and most likely will be less relevant once AngularFire2 supports messaging module. So take the below with that assumption...
OK I researched and finally made it work on my Ionic 3 PWA, so I am posting solution here:
Prerequisites:
I created ionic blank app (just a home page)
installed angularfire2 and firebase ("angularfire2": "5.0.0-rc.4","firebase": "4.9.1") using npm install, I used specifically 5.0.0-rc.4" cause I had stability issues with latest one;(
created config (filename environment.ts in src folder):
export const firebaseConfig = {
apiKey: "Your Stuff Here from FB",
authDomain: "YOURAPPNAME.firebaseapp.com",
databaseURL: "https://YOURAPPNAME.firebaseio.com",
projectId: "YOURAPPNAME",
storageBucket: "YOURAPPNAME.appspot.com",
messagingSenderId: "FROMFIREBASECONEOLE"
};
I modified app.module.ts to add firebase and angularfire2 this way:
...
import { AngularFireModule } from 'angularfire2';
import 'firebase/messaging'; // only import firebase messaging or as needed;
import { firebaseConfig } from '../environment';
import { FirebaseMessagingProvider } from '../providers/firebase-messaging';
...
#NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
AngularFireModule.initializeApp(firebaseConfig),
IonicStorageModule.forRoot()
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [
FirebaseMessagingProvider,
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
Here we also import our provider whose code is below:
in providers folder I created firebase-messaging.ts like this:
import { Injectable } from "#angular/core";
import { FirebaseApp } from 'angularfire2';
// I am importing simple ionic storage (local one), in prod this should be remote storage of some sort.
import { Storage } from '#ionic/storage';
#Injectable()
export class FirebaseMessagingProvider {
private messaging;
private unsubscribeOnTokenRefresh = () => {};
constructor(
private storage: Storage,
private app: FirebaseApp
) {
this.messaging = app.messaging();
navigator.serviceWorker.register('service-worker.js').then((registration) => {
this.messaging.useServiceWorker(registration);
//this.disableNotifications()
this.enableNotifications();
});
}
public enableNotifications() {
console.log('Requesting permission...');
return this.messaging.requestPermission().then(() => {
console.log('Permission granted');
// token might change - we need to listen for changes to it and update it
this.setupOnTokenRefresh();
return this.updateToken();
});
}
public disableNotifications() {
this.unsubscribeOnTokenRefresh();
this.unsubscribeOnTokenRefresh = () => {};
return this.storage.set('fcmToken','').then();
}
private updateToken() {
return this.messaging.getToken().then((currentToken) => {
if (currentToken) {
// we've got the token from Firebase, now let's store it in the database
console.log(currentToken)
return this.storage.set('fcmToken', currentToken);
} else {
console.log('No Instance ID token available. Request permission to generate one.');
}
});
}
private setupOnTokenRefresh(): void {
this.unsubscribeOnTokenRefresh = this.messaging.onTokenRefresh(() => {
console.log("Token refreshed");
this.storage.set('fcmToken','').then(() => { this.updateToken(); });
});
}
}
Please note I init the firebase app and then in constructor we register ionic's default service worker (service-worker.js) that contains the following right after whatever is there by default:
service-worker.js:
// firebase messaging part:
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.9.0/firebase-messaging.js');
firebase.initializeApp({
// get this from Firebase console, Cloud messaging section
'messagingSenderId': 'YOURIDFROMYOURFIREBASECONSOLE'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
console.log('Received background message ', payload);
// here you can override some options describing what's in the message;
// however, the actual content will come from the Webtask
const notificationOptions = {
icon: '/assets/images/logo-128.png'
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});
At this point you also need to make sure you enabled your app as PWA, there is a good guide from Josh Morony and today there was a video stream on youtube that covers it. In TLDR you need to uncomment this in your index.html:
index.html in src uncomment:
<!-- un-comment this code to enable service worker -->
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(() => console.log('service worker installed'))
.catch(err => console.error('Error', err));
}
</script>
OK almost the last thing - your manifest.json (in src) should have exact line:
"gcm_sender_id": "103953800507"
This concludes initial stuff on the client. Please note I didn't implement yet anything to handle notifications while user is in app itself, think for now it just handles when a message is sent from a server while your tab is not in focus (that is what I tested).
Now you want to go to your firebase console and obtain server key (click setting gear icon, then see cloud messaging section there). Copy server key. Also run the client (ionic serve and capture your local token (i just console.logged it). Now try sending yourself the message using a POST method. ( I did it with Postman)
// method: "POST",
//url: "https://fcm.googleapis.com/fcm/send",
// get the key from Firebase console
headers: { Authorization: `key=${fcmServerKey}` },
json: {
"notification": {
"title": "Message title",
"body": "Message body",
"click_action": "URL to your app?"
},
// userData is where your client stored the FCM token for the given user
// it should be read from the database
"to": userData.fcmRegistrationKey
}
So by doing all this I was able to reliable send myself a message WHILE the app was in background. I am yet to handle foreground but this SO question is about how to init default service worker and marry it with FCM.
I hope this will help some learners in future.
I have successfully implemented the process and got success response on API calls. But no notification popup coming on my browser. Any idea?
api: https://fcm.googleapis.com/fcm/send
response got:
{"multicast_id":6904414188195222649,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1545375125056264%e609af1cf9fd7ecd"}]}
cheth the attached url of my console:

how to configure firebase react-native ignite "better practice"

How could set the firebase to infinitered/ignite the best way?
I'm starting now and have several doubts however I think you should add a FirebaseConfig.js in the / Config. Right?
My file FirebaseConfig.js now.
import Config from 'react-native-config'**
const firebase = require ( 'firebase');
// Initialize Firebase
import Config from 'react-native-config'
const firebase = require('firebase');
// Initialize Firebase
const firebaseConfig = {
apiKey: Config.FIREBASE_API_KEY,
authDomain: Config.FIREBASE_AUTH_DOMAIN,
databaseURL: Config.FIREBASE_DATABASE_URL,
storageBucket: Config.FIREBASE_STORAGE_BUCKET,
messagingSenderId: Config.FIREBASE_MESSAGING_SENDER_ID
};
const firebaseApp = firebase.initializeApp(firebaseConfig);

Vue js and Firebase

I am new to Vue Js and Firebase. I want to learn firebase /firestore db connection ,data in/out but i am not getting any proper documentation or tutorial for the same.Please suggest.
I am using VUE CLI 2.
Create a src/firebaseDb.js file then add the following code to establish the real-time database connection in vue with your Firebase configurations details.
import * as firebase from 'firebase';
const firebaseConfig = {
apiKey: "api-key",
authDomain: "project-id.firebaseapp.com",
databaseURL: "https://project-id.firebaseio.com",
projectId: "project-id",
storageBucket: "project-id.appspot.com",
messagingSenderId: "sender-id",
appId: "app-id",
measurementId: "G-measurement-id"
}
const firebaseApp = firebase.initializeApp(firebaseConfig);
export const db = firebaseApp.firestore();
You can check this link its quite easy
https://www.positronx.io/vue-js-firebase-build-vue-crud-app-with-cloud-firestore/
i have created firebaseConfig.js file and connect to fire store.
import firebase from 'firebase/app'
require('firebase/firestore');
// Initialize Firebase
var config = {
apiKey: "AIzaSyC944Kh9T_Pcdn-kTZ6LywsIUATJBmQNTI",
authDomain: "halo-care-38f05.firebaseapp.com",
databaseURL: "https://halo-care-38f05.firebaseio.com",
projectId: "halo-care-38f05",
storageBucket: "halo-care-38f05.appspot.com",
messagingSenderId: "682838402004"
};
const firestore =firebase.initializeApp(config);
const db = firebase.firestore();
export default db;