I want to show my notification to the user till i desired by default it is shown up to 19 sec approx. can somebody tell me about any trick regarding this?
i also tried to update again and again to keep it showing but not succeed, actually not got appropriate syntax for doing that.
currently i am using below code to register service worker.
by this code i am able show notification for 19 sec approx, but i want to show it for 1 min.
var url = "https://example.com/json-data.php?param="+Math.random();
self.addEventListener('push', function(event) {
event.waitUntil(
fetch(url).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.log('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
return self.registration.showNotification(title, {
body: message,
icon: icon,
data: {
url: data.notification.url
}
});
});
}).catch(function(err) {
console.log('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var icon = 'img/design19.jpg';
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});
// The user has clicked on the notification ...
self.addEventListener('notificationclick', function(event) {
console.log(event.notification.data.url);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWind`enter code here`ow(event.notification.data.url);
}`enter code here`
})
);
});
There is no parameter as of now on setting the timeout for the notification. It is by default that the notification will show for 20 seconds then the desktop version of Chrome will auto-minimize the notification.
Alternatively, there is a parameter in the options requireInteraction which is false by default. By enabling this to true will make the notification stay visible until the user has interacted with it.
I think you can't directly set how long a notification should be shown.
A possible hacky way to do it would be, once browsers will support persistent notifications (I don't know if Chrome or Firefox do at the moment), to show a persistent notification and then close it after a timeout.
According to hacky way Marco said, It Works!
"notification" => [
"title" => isset($arrData['title']) ? $arrData['title'] : '',
"body" => isset($arrData['description']) ? $arrData['description'] : '',
"icon" => s3_url("images/push-logo.jpg"),
"click_action" => isset($arrData['target_url']) ? $arrData['target_url'] : '',
"image" => isset($arrData['image']) ? $arrData['image'] : '',
],
"data" => [
"requireInteraction" => true,
"duration" => (20 * 1000), // 20 sec
],
"to" => "/topics/$topic",
And set the requireInterationTrue on onMessage , after push notification is shown take duration from data and close notification inside a setTimeout
messaging.onMessage(function(payload) {
console.log('Message received. ', payload.data);
const noteTitle = payload.notification.title;
const noteRequireInteraction = (payload.data.requireInteraction === 'true');
const noteDuration = payload.data.duration;
const noteOptions = {
body: payload.notification.body,
icon: payload.notification.icon,
image: payload.notification.image,
requireInteraction: noteRequireInteraction,
};
if (!document.hidden) {
var notification = new Notification(noteTitle, noteOptions);
setTimeout(function () {
notification.close();
}, noteDuration);
notification.onclick = function(event) {
event.preventDefault();
if(typeof payload.notification.click_action != 'undefined' && payload.notification.click_action != '')
window.open(payload.notification.click_action,'_blank');
notification.close();
}
}
});
Related
im trying webrtc for the first time for a video chat app , i want up to 3 person in each chat ... my code works fine with 2 person chat
but as soon as 3rd person joins the chat everything goes wrong ... i get multiple video tags in the page and none of them are from the 3rd pear .... i'd appreciate any pointers or suggestion most tutorials cover 2 person chat
here is working url
https://chate-test-3000.herokuapp.com/
here is my code
const PEARS = [];
var video_counter = 0 ;
const STREAMES = [] ;
var myVideoArea = document.querySelector('#myvideo');
var configuration = {
'iceServers': [{
'url': 'stun:stun.l.google.com:19302'
}]
};
var rtcPeerConn;
const ROOM = 'caht1';
const SIGNAL_ROOM = 'newsingal1234567898765';
io = io.connect("" , {transports:['websocket']});
io.emit('ready' , { chat_room : ROOM , signaling_room : SIGNAL_ROOM});
io.emit('signal' , { text :'ready for video ? ' , room : SIGNAL_ROOM , type : 'user_here'});
io.on('signlaing_message' , function(data){
console.log('signal recived');
console.log(data);
if(!PEARS.includes(data.pear_id))
{
console.log('adding new pear --- ' , data.pear_id);
PEARS.push(data.pear_id);
startSignaling(data.pear_id);
}
if (data.type != "user_here")
{
var message = JSON.parse(data.message);
if (message.sdp) {
rtcPeerConn.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
// if we received an offer, we need to answer
if (rtcPeerConn.remoteDescription.type == 'offer') {
rtcPeerConn.createAnswer(sendLocalDesc, logError);
}
}, logError);
}
else {
rtcPeerConn.addIceCandidate(new RTCIceCandidate(message.candidate));
}
}
})
function startSignaling(pear_id) {
if(!rtcPeerConn)
rtcPeerConn = new RTCPeerConnection(configuration);
// send any ice candidates to the other peer
rtcPeerConn.onicecandidate = function (evt) {
if (evt.candidate)
io.emit('signal',{"type":"ice candidate", "message": JSON.stringify({ 'candidate': evt.candidate }), "room":SIGNAL_ROOM});
displaySignalMessage("completed that ice candidate...");
};
// let the 'negotiationneeded' event trigger offer generation
rtcPeerConn.onnegotiationneeded = function () {
displaySignalMessage("on negotiation called");
rtcPeerConn.createOffer(sendLocalDesc, logError);
}
// once remote stream arrives, show it in the remote video element
rtcPeerConn.ontrack = function (evt) {
displaySignalMessage("going to add their stream...");
video_counter++ ;
let vid = 'video-box-'+video_counter ;
console.log('adding new STREAM !!')
console.log('###### streams ' , evt.streams);
if(!STREAMES.includes(evt.streams[0].id))
{
STREAMES.push(evt.streams[0].id);
$('#video-wrapper').append(`<video data-id="${evt.streams[0].id}" id="${vid}" autoplay loop autobuffer muted playsinline controls></video>`);
console.log(' video length ..... ' , $('#video-wrapper').find('#'+vid).length );
var theirVideoArea = $('#video-wrapper').find('#'+vid)[0];
console.log(theirVideoArea);
theirVideoArea.srcObject = evt.streams[0] ;
theirVideoArea.play();
}
};
// get a local stream, show it in our video tag and add it to be sent
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({
'audio': true,
'video': true
}, function (stream) {
displaySignalMessage("going to display my stream...");
myVideoArea.srcObject = stream
myVideoArea.play();
for (const track of stream.getTracks()) {
rtcPeerConn.addTrack(track, stream);
}
}, logError);
}
function sendLocalDesc(desc) {
rtcPeerConn.setLocalDescription(desc, function () {
displaySignalMessage("sending local description");
io.emit('signal',{"type":"SDP", "message": JSON.stringify({ 'sdp': rtcPeerConn.localDescription }), "room":SIGNAL_ROOM});
}, logError);
}
function logError(error) {
$('#error-area').append(`<div> ${error.name} : ${error.message}</div>`);
}
function displaySignalMessage(text ){
$('#signal-area').append(`<div>${text}</div>`);
}
i also use a simple nodejs server for signaling and use socket.io to connect to the server
------------------------- EDIT - PEER.JS -----------------
here is my code after switching to peerjs
const SIGNAL_ROOM = 'zxsingalroom';
var MY_PEER_ID = '' ;
const CurrentPeers = [] ;
io = io.connect("" , {transports:['websocket']});
io.emit('ready' , { chat_room : ROOM , signaling_room : SIGNAL_ROOM});
var peer = new Peer({
config: {'iceServers': [
{ url: 'stun:stun.l.google.com:19302' },
]} /* Sample servers, please use appropriate ones */
});
peer.on('open', function(id) {
console.log('My peer ID is: ' + id);
MY_PEER_ID = id ;
io.emit('peer_id_offer' , { chat_room : ROOM , id : id});
});
peer.on('call' , function (call) {
navigator.mediaDevices.getUserMedia({ video : true , audio : true })
.then((stream) => {
call.answer(stream);
call.on('stream' , function(remoteStream){
if(!CurrentPeers.includes(call.peer))
{
CurrentPeers.push(call.peer);
addRemoteVideo(remoteStream);
}
})
})
.catch( (e)=>{
console.log('error2' , e );
});
})
io.on('peer_id_recived' , function(data){
console.log(`peer id recived : `);
console.log(data);
for (let [key, value] of Object.entries(data.peer_ids)) {
if(value.peer_id != MY_PEER_ID)
{
callPeer(value.peer_id);
}
}
});
function callPeer( id )
{
console.log('calling peers 1 .... ');
navigator.mediaDevices.getUserMedia({ video : true , audio : true })
.then( (stream) => {
console.log('calling peers 2 .... ' + id);
addOurVideo(stream);
let call = peer.call(id , stream);
console.log( typeof call);
call.on('stream' , function(remoteStream){
console.log('calling peers 3 .... ');
if(!CurrentPeers.includes(call.peer))
{
CurrentPeers.push(call.peer);
addRemoteVideo(remoteStream);
}
})
})
.catch( (e)=>{
console.log('error1' , e );
});
}
function addRemoteVideo(stream){
console.log(' adding remote stream!!!');
let total_perrs = CurrentPeers.length ;
let vid = `video-box-${total_perrs}`;
$('#video-wrapper').append(`<video id="${vid}" autoplay loop autobuffer muted playsinline controls></video>`);
var theirVideoArea = $('#video-wrapper').find('#'+vid)[0];
theirVideoArea.srcObject = stream ;
theirVideoArea.play();
}
function addOurVideo(stream){
console.log(' adding our stream');
var ourVideArea = $('#video-wrapper').find('#our-video')[0];
ourVideArea.srcObject = stream ;
ourVideArea.play();
}
You should use some sort of P2P or Media Server to handle multiple simultaneous connections from different clients PeerJS is a great option.
for the WebRTC: ICE failed, add a TURN server and see about:webrtc for more details error its exactly what it says STUN servers are used to create the connection but if the P2P connection cannot be established, the fallback is that all the communication goes through a TURN server, so they need high resources and bandwidth.
TURN servers are generally not free but one open source option that might fix your problem is using a COTURN server https://github.com/coturn/coturn
you should put the following example config in your PeerJS options
"iceServers": [
{
"urls": "stun:vc.example.com:3478"
},
{
"urls": "turn:vc.example.com:3478",
"username": "coturnUser",
"credential": "coturnUserPassword"
}
],
you could specify "iceTransportPolicy": "relay" before urls to only use relay server(without P2P)
This problem came from NFC tag is too sensitive.
When I put an NFC tag once, then too many values are entered momentarily.
So if one NFC tag value is entered, then wish to stop the NFC event listener at that moment. How do I implement it?
I think NFC reading speed is so fast in between device and NFC-tag than EventListener cancellation in program side.
this ionic page working like this...
*1) First load ionViewDidEnter()
2) Add addListenNFC()
3) If NFC tagged, then value send to onNfcLogin(tagId)
4) In onNfcLogin(tagId), this is included "Http post service provider" as userService.nfclogin()
5) Finally get the json type return from server side.*
{
"dependencies": {
"ionic-native/core": "4.7.0",
"ionic-angular": "3.9.2",
"typescript": "~2.6.2"]
},
"test device": "Galaxy8",
"NFC Tag": "cheaped NFC stick"
}
ionViewDidEnter() {
this.nfc.enabled().then((resolve) => {
this.addListenNFC();
}).catch((reject) => {
alert("NFC is not supported by your Device");
});
}
addListenNFC() {
this.nfc.addTagDiscoveredListener().subscribe(data => {
//window.removeEventListener; //this is not working.
if (data && data.tag && data.tag.id) {
this.tagId = this.nfc.bytesToHexString(data.tag.id);
if (this.tagId) {
this.scanned = true;
this.onNfcLogin(this.tagId);
} else {
alert('NFC_NOT_DETECTED');
}
}
});
}
onNfcLogin(tagId) {
this.userService.nfclogin(tagId).subscribe(data => {
// "this.userService.nfclogin()" is at Http post service provider
this.getData = JSON.stringify(data);
if (this.getData) {
this.granted = true;
this.loading.dismiss();
this.events.publish('user:login');
this.navCtrl.setRoot(HomePage);
}
this.resetScanData;
},
error => {
this.loading.dismiss();
this.showError(error);
});
}
showError(error) {
console.log(error);
let alert = this.alertCtrl.create({
title: 'Login Error',
message: error.json().message,
buttons: ['OK']
});
alert.present();
}
resetScanData() {
this.granted = false;
this.scanned = false;
this.tagId = "";
}
You can take only the first subscription with observable.take(1).subscribe(...) .
And then re-create a subscription later.
I solved with this code.
this.myListener = this.nfc.addNdefListener(() => {
console.log(‘successfully attached ndef listener’);
},(err) => {
console.log(‘error attaching ndef listener’, err);
}).subscribe((event) => {
. . .
});
//remove listener
this.myListener.unsubscribe();
thanks to Avdm in Ionic forum.
https://forum.ionicframework.com/t/remove-listener-nfc-plugin/113393
I have a messages entry that looks like this:
firbaseapp
messages
-KiG85eYMH7jfKph4bl3
created: 1492788734743
title: "title"
message: "message"
I want to send a notification when new entries are added to this list so
I added this cloud function:
exports.sendMessageNotification = functions.database.ref('/messages/').onWrite(event => {
event.data.forEach(message => {
if (message.val().notificationSent) {
return;
}
admin.messaging().sendToTopic(...)
.then(res => {
return db.ref('/messages').child(message.key).update({
notificationSent: (new Date()).getTime(),
});
})
});
});
Problem is message.key is messages-KiG85eYMH7jfKph4bl3 so when I try to save it, it creates a new entry instead of updating the existing one:
firbaseapp
messages
-KiG85eYMH7jfKph4bl3
created: 1492788734743
title: "title"
message: "message"
-messages-KiG85eYMH7jfKph4bl3
notificationSent: 123434554534
What I wanted is for notificationSent to be set on the existing entry.
I also tried using message.ref but I get the same result.
So what is the best way to update a list item in firebase in a cloud function?
I think this accomplishes what you want to do and also answers your questions in the comments:
exports.sendMessageNotification = functions.database.ref('/messages/{messageId}')
.onWrite(event => {
const messageId = event.params.messageId;
console.log('messageId=', messageId);
if (event.data.current.child('notificationSent').val()) {
console.log('already sent');
return;
}
const ref = event.data.ref; // OR event.data.adminRef
admin.messaging().sendToTopic(...)
.then(res => {
return ref.update({
// Caution: this update will cause onWrite() to fire again
notificationSent: (new Date()).getTime(),
});
})
});
I have come to post this question after 2 days of torture not being able to understand how I can actually publish the historic messages stored on my pubnub storage account. To try and understand it at its most basic I have made a chat app and used the history function as described in the SDK but still every time I refresh the page the messages are lost. I have tried the backfill and the restore attributes in subscribe with no luck. All I want to do is click refresh on chrome and see the messages still there.
<div><input id=input placeholder=you-chat-here /></div>
Chat Output
<div id=box></div>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.4.0.min.js"></script>
<script>(function(){
var pubnub = new PubNub({ publishKey : 'demo', subscribeKey : 'demo' });
function $(id) { return document.getElementById(id); }
var box = $('box'), input = $('input'), channel = 'chat';
pubnub.addListener({
message: function(obj) {
box.innerHTML = (''+obj.message).replace( /[<>]/g, '' ) + '<br>' + box.innerHTML
}});
pubnub.history({
channel: 'chat',
reverse: true, // Setting to true will traverse the time line in reverse starting with the oldest message first.
count: 100, // how many items to fetch
callback : function(msgs) {
pubnub.each( msgs[0], chat );
}
},
function (status, response) {
// handle status, response
console.log("messages successfully retreived")
});
pubnub.subscribe({channels:[channel],
restore: true,
backfill: true,
ssl: true});
input.addEventListener('keyup', function(e) {
if ((e.keyCode || e.charCode) === 13) {
pubnub.publish({channel : channel, message : input.value,x : (input.value='')});
}
});
})();
</script>
</body>
EDIT: updated link that was broken. New version of history function is called fetchMessages.
I think your history code is not correct. No need for the callback as your code response will be in the function argument. This example is from the JavaScript SDK docs.
// deprecated function
pubnub.history(
{
channel: 'chat',
},
function (status, response) {
var msgs = response.messages;
if (msgs != undefined && msgs.length > 0) {
// if msgs were retrieved, do something useful
console.log(msgs);
}
}
);
// latest function (response output format has changed)
pubnub.fetchMessages(
{
channels: ['chat']
},
(status, response) => {
console.log(msgs);
}
);
I am new to Google Chrome Push notifications and I was just reading some questions and answers here, on stackoverflow and I have ended with this easy push notification javascript.
navigator.serviceWorker.register('sw.js');
function notify() {
Notification.requestPermission(function(result) {
if (result === 'granted') {
navigator.serviceWorker.ready.then(function(registration) {
registration.showNotification('test notification', {
body: 'Hey I am test!',
icon: 'image.png',
});
});
}
});
}
Its just simple notification, but I need open a new window with other webpage after click on notification.
I know it is possible, but I cant find examples using "serviceWorker" syntax.
Please help. Thanks.
I am guessing you are in a Service Worker context, because that's where Push Notifications are received. So you have the self object to add a event listener to, that will react to a click on the notification.
(Place this code in your sw.js file, which is your Service Worker script.)
self.addEventListener('notificationclick', function(event) {
let url = 'https://example.com/some-path/';
event.notification.close(); // Android needs explicit close.
event.waitUntil(
clients.matchAll({type: 'window'}).then( windowClients => {
// Check if there is already a window/tab open with the target URL
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
// If so, just focus it.
if (client.url === url && 'focus' in client) {
return client.focus();
}
}
// If not, then open the target URL in a new window/tab.
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});
If you want to open website with dynamic URL received from FCM push notification or any other web push notification then
BELOW IS AN EXAMPLE OF SERVICE WORKER USED FOR FCM PUSH NOTIFICATION
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
var notificationTitle = payload.data.title; //or payload.notification or whatever your payload is
var notificationOptions = {
body: payload.data.body,
icon: payload.data.icon,
data: { url:payload.data.click_action }, //the url which we gonna use later
actions: [{action: "open_url", title: "Read Now"}]
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
and handle click event with below code
self.addEventListener('notificationclick', function(event) {
switch(event.action){
case 'open_url':
clients.openWindow(event.notification.data.url); //which we got from above
break;
case 'any_other_action':
clients.openWindow("https://www.example.com");
break;
}
}
, false);
Hope it helps!
(This code refers to firebase messaging) I was also searching for a soluting and the answer was very easy, but there was no doc saying it clearly. You need to put "click_action" = "your url" inside the notification json. Here is an example:
notification: {
title: "Come",
icon: '../../../../assets/logo.png',
vibrate: [300,100,400,100,400,100,400],
body: "some text",
click_action : "your link"
}
Hope it helps.
{
"notification": {
"title": "Hey there",
"body": "Subscribe to might ghost hack youtube channel",
"click_action" : "http://localhost:4200"
},
"to":"YOUR_TOKEN"
}
This worked for me
"#angular/fire": "^6.1.5",
"firebase": "^7.0 || ^8.0"