I am sending push notifications with One Signal to all users from the backend that uses Laravel like this:
OneSignal::sendNotificationToAll($notification->message);
I have set it up on the frontend side like this:
angular.module('coop.services')
.service('PushService', function(
AppSettings,
$rootScope,
$q
) {
var service = {
init: function() {
if (!window.plugins || !window.plugins.OneSignal) {
return;
}
window.plugins.OneSignal
.startInit( AppSettings.oneSignalAppId)
.endInit();
},
receivePush: function(data) {
$rootScope.$broadcast('push:received', data);
},
getDeviceId: function() {
var deferred = $q.defer();
if (window.plugins) {
window.plugins.OneSignal.getIds(function(ids) {
deferred.resolve(ids.userId);
});
}
else {
deferred.reject();
}
return deferred.promise;
}
};
return service;
});
I have tested both from the backend and from the One signal dashboard and when I am sending notification I get two notifications for each I send. One with alarm icon and one without any, what I am doing wrong?
you might have enabled mozila and Chrome with wrong settings, had similar problem I couldn't disactivate the browser though, I just made a new onesignal app and solved.
Related
I have a PWA which works fine both online and offline (but only with the initial files). However, the offline cache (let’s say a javascript file) is not being refreshed so whenever I am offline the old javascript file is used, but when online the new version is used.
On an iPad I can use Safari to go to the website and add the PWA to the home page.
If I then go offline, it works fine – all pages work etc.
But if I make a change to say a javascript file (something like adding an alert) and also change the version in my service worker, when I am online the change is reflected but when offline it remains at the older version
To clarify let’s say from the start, on going into a page it alerts “A1”
I then change the javascript to alert “A2” and change the version in the service worker.
If I run the app when online, sure enough the app says New Update Available and All Good (some alerts from the main.js file)
Then when I go into the actual page o the alert says “A2” – so all good.
Then go offline.
The alert still says “A1”
It seems that when online it uses the server latest files but when it tries to use cache the files are old and at the moment seem to be the original files.
I have read many sites on this with no success – some suggest it will sort itself in 24 hours. Some suggest setting the maxage of the service worker to 0 (but how do you do this?). Some say the files need renaming each time they change which seems very clunky.
The service worker is definitely working
main.js
$(document).ready(function () {
'use strict';
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register("/sw.js")
.then(res => {
console.log("service worker registered");
res.onupdatefound = () => {
const installingWorker = res.installing;
installingWorker.onstatechange = () => {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller){
alert("new update available");
forceReload();
}
else {
alert("all good");
}
break;
}
}
}
})
.catch(err => console.log("service worker not registered", err))
}
});
const forceReload = () =>{
console.log("ForceReload");
navigator.serviceWorker
.getRegistrations()
.then((registrations) =>{
console.log(registrations);
//alert("reg");
Promise.all(registrations.map((r) => r.unregister()))
caches.keys().then(function(names) {
for (let name of names)
caches.delete(name);
});
},
)
.then(() => {setTimeout(() => {
location.reload();
}, 500);
})
}
sw.js
let version =5; // update this to send update.
var cacheName = 'cacheV5'
var filesToCache = [
'/',
'/manifest.json',
'/index.html',
'/sales10.html',
'/getdata.html',
....
....
'/js/siteJS/sales10.js',
'/js/siteJS/getdata.js',
'/js/jquery/3.4.1/jquery.min.js',
'/js/bootstrap/bootstrap.min.js',
'/js/bootstrap/popper.min.js'
];
/* Start the service worker and cache all of the app's content */
self.addEventListener('install', function(e) {
self.skipWaiting();
e.waitUntil(
caches.open(cacheName).then(function(cache) {
return cache.addAll(filesToCache);
})
);
});
/* Serve cached content when offline */
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(stripQueryStringAndHashFromPath(e.request.url.replace(/^.*\/\/[^\/]+/, ''))).then(function(response) {
return response || fetch(e.request);
})
);
});
function stripQueryStringAndHashFromPath(url) { //added this so when url paramerters passed grabbing the cashed js works
return url.split("?")[0].split("#")[0];
}
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
return true;
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
});
I’m using Kuzzle as backend for my realtime chat application.
What is the better approach to sending push notification when user is offline in a mobile chat app?
1. Using custom plugin hooks
// check for every message in chat
this.hooks = {
'document:afterCreate': (request) => {
if (request.input.resource.collection == 'messages') {
let message = request.input.body;
this.context.accessors.sdk.document.get('now', 'user_sessions', message.otherUserId).then((userSession) => {
if (!userSession._source.isOnline) {
userSession._source.devices.forEach(device => {
// send push notification
});
}
})
}
}
}
2. Subscription per user for all users after the Kuzzle server start-up
const app = new Backend('kuzzlebackend')
app.start()
.then(async () => {
// Application started
// Loops through all users and adds their subscriptions to Kuzzle
foreach(user in users) {
app.sdk.realtime.subscribe('now', 'messages', { ‘otherUserId' : user._id }, async (notification: Notification) => {
this.context.accessors.sdk.document.get('now', 'user_sessions', user._id).then((userSession) => {
if (!userSession._source.isOnline) {
userSession._source.devices.forEach(device => {
// send push notification
});
}
})
})
}
})
You should use the hook mechanism on the generic:document:afterWrite event to send notification to offline users when a new message is created.
This event will be triggered every time a document is written with one of the Document controller action, and for the m* action family it you will able to process documents in bulk instead of one by one.
Was hoping to achieve when OneSignal push notification was being opened would redirect to a certain page in the App. Following is my code to redirect to a page called positions but it didn't seem to work. When the push notification is opened, it still opens up the url in the InAppBrowser. Any idea what went wrong? Thanks in advance.
if (this.appConfig.Onesignal_Enable == true) {
this.oneSignal.startInit(this.appConfig.OneSignal_AppID, this.appConfig.GCM_SenderID);
this.oneSignal.handleNotificationReceived().subscribe(() => {
// do something when notification is received
});
this.oneSignal.handleNotificationOpened().subscribe((data) => {
// do something when a notification is opened
// the following two lines pass data I send with the push notification so the app knows what to open
let pushaction = data.notification.payload.additionalData.action;
let pushactionvalue = data.notification.payload.additionalData.actionvalue;
// this fires up the tab-switching
this.runNotificationAction(pushaction, pushactionvalue);
});
this.oneSignal.endInit();
}
runNotificationAction(pushaction, pushactionvalue){
// this is the data passed the the other page
let data = {"action": pushaction, "value:": pushactionvalue};
this.navCtrl.navigateForward('positions');
}
Hello I'm using v4 ionic too and I achieved this with this implementation on my project:
let self = this;
var notificationOpenedCallback = async function(jsonData) {
//I use info data previous saved, but you can use jsonData
switch (self.user.role) {
case "customer":
self.router.navigate(["history-customer"]);
break;
case "provider":
self.router.navigate(["history-provider"]);
}
};
window["plugins"].OneSignal.startInit(
"0*************7",
"1*********2"
)
.handleNotificationOpened(notificationOpenedCallback)
.endInit();
window["plugins"].OneSignal.setSubscription(true);
I use
let self = this
because startInit receive a callback so is necessary to do that, in your case I don't know if inside subscribe need also use "self" and I use Router to navigate between pages.
import { Router } from "#angular/router";
And on my app-routing.module.ts
{ path: 'history-provider', loadChildren: './pages/history-provider/history-provider.module#HistoryProviderPageModule' },
{ path: 'history-customer', loadChildren: './pages/history-customer/history-customer.module#HistoryCustomerPageModule' }
We are currently using the soundcloud API SDK for streaming and it does work on desktop but not 100% on mobile. (using responsive html. same api of course)
Sometime track is not lauch ? sometime it is.
I do not have specific error but on chrome network this line is show in red ??
http://api.soundcloud.com/tracks/146926142/stream?client_id=XXXXX
Redirect
We use a function to stream the track.
function streamTrack(id) {
var defer = $q.defer();
// Stream the track
SC.stream('/tracks/' + id, {
useHTML5Audio: false,
waitForWindowLoad: true,
onfinish: _scope.next,
whileplaying: function () {
var _this = this;
// Since we are in a callback, we need to tell angularJS to apply the change
if (timeout1) $timeout.cancel(timeout1);
timeout1 = $timeout(function () {
// Update the progress bar
_scope.progress = (_this.position / currentTrackDuration * 100) + '%';
_scope.timer = moment(_this.position).format('mm:ss');
$rootScope.$broadcast('trackRunning', { timerunning: _scope.timer });
});
}
}, function (sound) {
if (sound) {
defer.resolve(sound);
} else {
defer.reject();
}
});
return defer.promise;
}
If somebody has an idea pls.
Best Regards
Xavier
I'm building a Metro app using the single-page navigation model. On one of my pages I start an async ajax request that fetches some information. When the request returns I want to insert the received information into the displayed page.
For example:
WinJS.UI.Pages.define("/showstuff.html", {
processed: function (element, options) {
WinJS.xhr(...).done(function (result) {
element.querySelector('#target').innerText = result.responseText;
});
}
};
But how do I know that the user hasn't navigated away from the page in the meantime? It doesn't make sense to try to insert the text on a different page, so how can I make sure that the page that was loading when the request started is still active?
You can compare the pages URI with the current WinJS.Navigation.location to check if you are still on the page. You can use Windows.Foundation.Uri to pull the path from the pages URI to do this.
WinJS.UI.Pages.define("/showstuff.html", {
processed: function (element, options) {
var page = this;
WinJS.xhr(...).done(function (result) {
if (new Windows.Foundation.Uri(page.uri).path !== WinJS.Navigation.location)
return;
element.querySelector('#target').innerText = result.responseText;
});
}
};
I couldn't find an official way to do this, so I implemented a workaround.
WinJS.Navigation provides events that are fired on navigation. I used the navigating event to build a simple class that keeps track of page views:
var PageViewManager = WinJS.Class.define(
function () {
this.current = 0;
WinJS.Navigation.addEventListener('navigating',
this._handleNavigating.bind(this));
}, {
_handleNavigating: function (eventInfo) {
this.current++;
}
});
Application.pageViews = new PageViewManager();
The class increments a counter each time the user starts a new navigation.
With that counter, the Ajax request can check if any navigation occurred and react accordingly:
WinJS.UI.Pages.define("/showstuff.html", {
processed: function (element, options) {
var pageview = Application.pageViews.current;
WinJS.xhr(...).done(function (result) {
if (Application.pageViews.current != pageview)
return;
element.querySelector('#target').innerText = result.responseText;
});
}
};