Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I've created an app similar to Instagram, using Firebase as my back-end database. The app has all the features i.e users can like your post, comment on your post etc. But, now I am stuck with notifications part. I've read some docs about FCM and followed some tutorials. However, I couldn't find any specific tutorial on how to create notification with the title as the name of the person who liked/commented on the post, and body of message as the content of the comment. Do I have to use PHP and mySQL to do this all? Or it can be done solely using JAVA?
Don't have enough rep to comment so I'll put this here.
Firebase released Firebase Functions recently.
Functions integrates the Firebase platform by letting you write code that responds to events and invokes functionality exposed by other Firebase features.
Lucky for you, the problem of sending notifications when one of your users follows another user is one of the example use cases for Firebase Functions.
You can check it out here.
Yes you'll need to make an app server to send notifications from device to another. Your app server will have the API of firebase FCM, and service account of Firebase database.
Following is a node.js code.The function listenForNotifications() is a listener attached to your database as to whenever you want to send lets say a follow request. On follow button click in your app you will add the an entry in your database in "Following" root node. Then as the entry is added from your mobile app the request.on("child_added"..) gets fired as there is an entry. Then the function routes the message to the person you want to send request to via the Token. i.e request.requestToToken
Database Structure of "Following" node:
+--Root
+-.
+--.
+----Following
+---------pushKey /auto-generated
+----------------requestToToken /token of device you want to send notification
+---------------- requestFromToken / token of device that sent the notification
var firebase = require('firebase-admin');
var request = require('request');
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.status(200).send('Hello, world!');
});
// Start the server
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
console.log('Press Ctrl+C to quit.');
});
var API_KEY = ".......your key"; // Your Firebase Cloud Messaging Server API
// Fetch the service account key JSON file contents
var serviceAccount = require("....your database service account.json");
// Initialize the app with a service account, granting admin privileges
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount),
databaseURL: "https://dropit-b357a.firebaseio.com"
});
ref = firebase.database().ref();
process.stdout.write("I AM HERE... SERVER RUNNING MAYBE: ");
function listenForNotificationRequests() {
var requests = ref.child('Following');
requests.on('child_added', function(requestSnapshot) {
var request = requestSnapshot.val();
sendNotificationToUser(
request.requestToToken,
request.requestFrom,
function() {
return;
}
);
}, function(error) {
console.error(error);
});
};
function sendNotificationToUser(username, message, onSuccess) {
request({
url: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: {
'Content-Type' :' application/json',
'Authorization': 'key='+API_KEY
},
body: JSON.stringify({
notification: {
title: message
},
to : username
})
}, function(error, response, body) {
if (error) { console.error(error); }
else if (response.statusCode >= 400) {
console.error('HTTP Error: '+response.statusCode+' '+response.statusMessage);
}
else {
onSuccess();
}
});
}
// start listening
listenForNotificationRequests();
Related
We have 2 Android apps in one Firebase project container, the first app has FCM implementation on Cloud Function and it works well, but the second app will received this notification as well so using restricted_package_name in messaging option is what we are looking for. However the question is, do we need to update the app as well or just the function in Cloud Function? Thus everything related to filtering of push notif. will be handled by its API and all we need is to provide the package name for the target app.
According to documentation of restrictedPackageName
The package name of the application which the registration tokens must match in order to receive the message.
Do we need to handle token as well? Do we need to update the code in the app or just add the option in the function with NodeJs?
const options = { priority: 'high' };
exports.announcement = functions.firestore.document("Announcement/{doc_id}").onCreate((added) => {
const title = added.data().title;
const description = added.data().description;
const bigImage = added.data().bigImage;
const link = added.data().link;
const environment = added.data().environment;
const payload = {
data: {
title: title,
description: description,
bigImage: bigImage,
link: link,
environment: environment,
}
};
return admin.messaging().sendToTopic("Announcement", payload, options)
.then(val => {
console.log("Success!\n" + JSON.stringify(payload), val);
return true;
})
.catch(error => {
console.error("Failed to send notification.", error);
return true;
});
});
From Firebase side it is not recommended to use same project for 2 different applications, which was also mentioned in this blog. If you want to use restricted_package_name you need to update the code so that the object sends it in notification. You can find a small example here.
I am trying to measure the latency between having a message exit Firebase Servers and being received on an Android app via the Firebase SDK. I have BigQuery integrated with my Firebase project, and have tried adding the following code:
// In the manifest:
<meta-data android:name= "delivery_metrics_exported_to_big_query_enabled"
android:value="true"/>
// In my Application object:
FirebaseMessaging.getInstance().setDeliveryMetricsExportToBigQuery(true);
The code seems to be exporting data to BigQuery. However, to calculate what I want I need timestamps for two different types of events associated to the same message id, "MESSAGE_ACCEPTED" and "MESSAGE_DELIVERED". Then, all I have to do is run a simple query that calculates the timestamp difference between those two.
My problem is: I can never seem to get the "MESSAGE_DELIVERED" variant for a given message id. I only ever get the "MESSAGE_ACCEPTED" side of the equation.
I am sending messages to the Android device via my own JavaScript app, and the request I make is like so:
app.get('/triggerAnt', function(req, res){
axios.post('https://fcm.googleapis.com/fcm/send', {
to:<TOKEN_FOR_DEVICE_GOES_HERE>,
notification:{
"title":"TESTNOTIFICATIONLATENCY",
"body":"TESTINGLATENCY"
},
fcm_options: {
analytics_label:<LABEL_HERE>
}
}, {headers: headers})
.then((response) => {
console.log(response.status);
}, (error) => {
console.log(error);
});
})
I would like to point out that the notification does effectively reach the device and I can open it too.
Is this delay on BigQuery's side or am I doing something wrong?
Thank you.
I see how execute a Cloud Function on user account creation:
exports.myFunction = functions.auth.user().onCreate(event => {
But I need my function to execute when the user logs in. Is there a onLogin trigger?
And can someone with 1500 points create a tag for firebase-cloud-functions?
There's no event for login, because only the client side can define exactly when a login happens. Different clients may define this in different ways. If you need to trigger something on login, figure out when that point is in your app, then trigger it from the client via a database or HTTP function.
This worked in the controller:
firebase.auth().onAuthStateChanged(function(user) { // this runs on login
if (user) { // user is signed in
console.log("User signed in!");
$scope.authData = user;
firebase.database().ref('userLoginEvent').update({'user': user.uid}); // update Firebase database to trigger Cloud Function
} // end if user is signed in
else { // User is signed out
console.log("User signed out.");
}
}); // end onAuthStateChanged
And this is the trigger in the Cloud Function:
exports.getWatsonToken = functions.database.ref('userLoginEvent').onUpdate(event => { // authentication trigger when user logs in
I made a location in Firebase Database called userLoginEvent.
One confusing bit is that in the functions console it's /userLoginEvent but in your code you must leave out the slash.
You can create your own analytics event, like login and used it as the trigger for your cloud function.
Then in your app, when the user successfully authenticate you use firebase analytics to send an event with the name you defined, like login
exports.sendCouponOnPurchase = functions.analytics.event('login').onLog((event) => {
const user = event.user;
const uid = user.userId; // The user ID set via the setUserId API.
});
You can trigger an https onCall firebase cloud function on login
ex: This is your login button trigger function which calls an https onCall function after authenticating the user.
_login() {
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then(function (user) {
var addMessage = firebase.functions().httpsCallable('myCloudFunctionName');
addMessage("whatever variable I want to pass")
.catch(error => {
console.log("I triggered because of an error in addMessage firebase function " + error)
)}
}).catch(error => {
console.log(error);
});
}
There is also another way you can do this inside Google Cloud if you enable Identity Platform for a project. Then you can follow this guide:
https://cloud.google.com/functions/docs/calling/logging
And trigger cloud functions for any of these Firebase Authentication events:
https://cloud.google.com/identity-platform/docs/activity-logging?authuser=1&_ga=2.226566175.-360767162.1535709791#logged_operations
The only problem I've just noticed is that the logs generated for Sign In event do not include the firebase app id or anything to determine which client the user logged in on which is really annoying as this was the main reason we needed to do this!
I just had my first contacts with the ionic framework. I've worked with Phonegap and AngularJS before however, so it was not all that new to me.
I found out that there is this new feature to use Google Cloud Messaging push notifications in Ionic, through the Ionic Push feature (http://blog.ionic.io/announcing-ionic-push-alpha/).
Related lines of code from app.js
angular.module('starter', ['ionic','ionic.service.core', 'starter.controllers', 'starter.services'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleLightContent();
}
// enable push notifications
Ionic.io();
// enable users (http://docs.ionic.io/docs/user-quick-start)
// this will give you a fresh user or the previously saved 'current user'
var user = Ionic.User.current();
// if the user doesn't have an id, you'll need to give it one.
if (!user.id) {
user.id = Ionic.User.anonymousId();
// user.id = 'your-custom-user-id';
}
console.log('user-id:' + user.id);
//persist the user
user.save();
var push = new Ionic.Push({
"debug": true,
"onNotification": function(notification) {
var payload = notification.payload;
console.log(notification, payload);
},
"onRegister": function(data) {
console.log(data.token);
}
});
push.register(function(token) {
console.log("Device token:",token.token);
});
push.addTokenToUser(user);
console.log('token added to user');
});
})
Log from ionic serve
ionic $ 0 361081 log Ionic Core:, init
1 361083 log Ionic Core:, searching for cordova.js
2 361085 log Ionic Core:, attempting to mock plugins
3 361155 log user-id:1cc3d21c-b687-4988-b944-ad07b1a677c8
4 361158 log Ionic Push:, a token must be registered before you can add it to a user.
5 361159 log Ionic Push:, token is not a valid Android or iOS registration id. Cannot save to user.
6 361159 log token added to user
7 361160 log Ionic Push:, register
8 361160 error ReferenceError: PushNotification is not defined, http://localhost:8100/lib/ionic-platform-web-client/dist/ionic.io.bundle.min.js, Line: 2
9 361526 log Ionic User:, saved user
Any input is welcome, I am also more than happy to provide more information if needed.
EDIT 10/05/2015:
found out that dev_push = false only works on physical devices, not in browser
I tried to add token to user before even registering the user
I'm having the same problem, seems not many answers online at the moment.
but even on real device, it won't save the token to user.
I just had to decide go live without push first, then use ionic deploy to follow up.
also I think you have to put this line
push.addTokenToUser(user);
inside the register callback according to this doc
http://docs.ionic.io/docs/push-usage
You also need to declare 'ionic.service.push' as a dependency in your angular module if you'd like to use it.
angular.module('starter', ['ionic','ionic.service.core', 'ionic.service.push'])
I have it like this and it works:
Ionic.io();
var user = Ionic.User.current();
if (!user.id) {
user.id = Ionic.User.anonymousId();
// save our newly created user
user.save();
}
var push = new Ionic.Push({});
push.register(function (token) {
console.log("Got Token:", token.token);
// now we have token, so add it to user
push.addTokenToUser(user);
// don't forget to save user to Ionic Platform with our new token
user.save();
});
// set this user as current, so we can acess him later
Ionic.User.current(user);
Did you use this
ionic config set dev_push true-if testing in emulator or laptop
ionic config set dev_pushfalse - if testing on the phone
ionic push --google-api-key Your API Key
ionic config set gcm_key Project Number
Your token is the registration id that is unique for a particular device. That is sent to you by android.
Your Phone (With the API Key)---------> to Google's GCM
Google GCM (recognises it's you via your Project number and API key) -----> Oh it's you let me make a note of it. (Save a token id in it's DB and send's one to you.)
You get a registration id unique for your device(will change if an app is uninstalled).
You call your server say hey it's me your user. Please Notify me if you get something.
Server obliges, says, okay dude, I got this. Saves the registration id with your details probably your username in it's DB.
Now from Server.
I need to inform my users about a great deal(or an accident or something).
Pull up all targeted registration Id's from DB(maybe on some condition)
registrationIds.push(regId) //in a loop
and sender.send(message, registration, function(err, result){
});
Send to Google. Google see's oh only these many people(not all maybe) from this API Key need a notification. no Problem I will notify them and you receive a notification, my dear friend.
As mentioned in the link , Adding token to the $ionicUser is done by doing , user.addPushToken(pushToken); .
For this to work you should first configure the app not to use developement pushes by ,
ionic config set dev_push true
After initialising Ionic.io and Ionic.push , load the user or create one with a new random id ,
Ionic.io();
var push = new Ionic.Push();
Ionic.User.load(localStorage.id).then(function (user) {
Ionic.User.current(user);
pushFactory.register(push, user);
}, function (error) {
/*the user with that id is not present , so create one with a random id and register the push */
});
The push factory is defined as below,
function pushFactory() {
return {
'register': function (push, user) {
push.register(function (pushToken) {
user.addPushToken(pushToken);
user.save().then(function (answer) {
console.log('user saved'+answer);
})
})
}
}
}
So I am trying to add a login with facebook / twitter option to my mobile app. I have installed ngcordova oauth plugin and everything is working. User clicks login, it takes them to FB, they accept the permissions, takes them back to the app, and I have the access_token object. Perfect. Except what do I do with it now? Now that I have the token I should be able to request the specific info I need (email / name) How is this done? Do I have to install the ios & android facebook sdk and the ios & twitter sdk? Is this built into ionic? can I simply use web calls? I am very confused on how I actually get user email / whatever other info I requested in the access_token after I retrieve permission. Here is my code currently
$scope.facebookLogin = function() {
$cordovaOauth.facebook("xxxxxxxxxxxxx", ["email"]).then(function(result) {
// results
console.log("Success");
console.log(result);
}, function(error) {
// error
console.log("Failure");
console.log(error);
});
}
I am getting in the success block, but now I need to know what to do with the access_token to actually get values.
This is the solution that I found that actually works for future persons
$accessToken = result.access_token;
$http.get("https://graph.facebook.com/v2.4/me", { params: { access_token: $accessToken, format: "json" }}).then(function(result) {
//this is where the user data is stored
var user_data = result.data;
console.log(user_data);
}, function(error) {
console.log(error);
});