I have to hide a push notification after 1 minute. What should I do in my service worker to achieve this?
You can use the Notification.close() method. You can get the Notification object with ServiceWorkerRegistration.getNotifications.
For example:
self.addEventListener('push', event => {
event.waitUntil(
self.registration.showNotification('Title', {
body: 'Body.',
})
.then(() => self.registration.getNotifications())
.then(notifications => {
setTimeout(() => notifications.forEach(notification => notification.close()), 60000);
})
);
});
You have to use Notification.close.
Also, to get the notifications, you have to use ServiceWorkerRegistration.getNotifications(). To identify a specific notification, you can use Notification.tag.
Finally, you must keep a Promise alive inside "waitUntil" to prevent the service-worker to shut down before your timeout triggers:
event.waitUntil(
self.registration.showNotification('Title', {body: 'Body.', tag: 'my-unique-tag'})
.then(() => new Promise(resolve => setTimeout(resolve, 60000)) // keep service worker alive
.then(() => self.registration.getNotifications())
.then(notifications => {
const notification = notifications.find(notification => notification.tag === 'my-unique-tag')
if (notification) {
notification.close()
}
})
);
Related
I want to stop push notifications when I log out . Then I unsubscribe. When I am logging back ;then the subscribe service worker again and succeeds, but the push notification is not shown.
const createNotificationSubscription = async pushServerPublicKey => {
//wait for service worker installation to be ready
const serviceWorker = await navigator.serviceWorker.ready;
// subscribe and return the subscription
return await serviceWorker.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: pushServerPublicKey,
});
};
const unsubscribeNotification = async () => {
return navigator.serviceWorker.ready.then(reg => {
reg.pushManager.getSubscription().then(subscription => {
subscription.unsubscribe();
});
});
};
I want to show push notifications only when the user is logged in
Im trying to test getting all users from my REST API.
describe('GET', () => {
let userId;
// Setup create the mock user
beforeAll(async () => {
//Create the user
return await request
.post(routes.users.create)
.set('Accept', 'application/json')
.send(TEST_USER_DATA)
.then(res => userId = res.body.id)
})
// Clean up, deleting all the fake data that we created for this test suite
afterAll(async () => {
// Clean up, delete the user we created
return await request.delete(routes.users.delete(userId));
})
it('should get all users', async () => {
const usersResponse = await request
.get(routes.users.getAll)
.set('Accept', 'application/json')
.expect(200)
.expect('Content-Type', /json/);
// Logs an empty array
console.log(usersResponse.body);
expect(usersResponse.status).to.equal(200);
expect(Array.isArray(usersResponse.body)).to.be.true();
});
});
But it look as though my it() block doesn't wait for beforeAll() to finish, because userResponse.body() is just an empty array. But when I do the same think in Postman(e.g. Create a mock user, then get all users, it displays an array with the user that we created) so the problem is definitely not in the server-side.
I've already tried writing my beforeAll block like that:
beforeAll(async () => {
//Create the user
return await new Promise((resolve) => {
request
.post(routes.users.create)
.set('Accept', 'application/json')
.send(TEST_USER_DATA)
.then(res => userId = res.body.id)
.then(() => resolve)
})
})
And like that:
beforeAll(async (done) => {
//Create the user
request
.post(routes.users.create)
.set('Accept', 'application/json')
.send(TEST_USER_DATA)
.then(res => userId = res.body.id)
.then(() => done());
})
But neither of them worked.
EDIT
As #jonrsharpe suggested I changed my beforeAll a bit to check the response status, and that we actually created a user
beforeAll(async () => {
//Create the user
return await request
.post(routes.users.create)
.set('Accept', 'application/json')
.send(TEST_USER_DATA)
.expect(200)
.then(res => {
userId = res.body.id;
// Log the correct user
console.log(res.body);
})
})
And the beforeAll block doesn't fail, so the creation of a user by itself is working fine.
I am trying to send notifications from firebase console to my react-native app
I followed the poor documentation here as much as I understand: https://invertase.io/oss/react-native-firebase/v6/messaging/quick-start
I installed #react-native-firebase/app and /messaging and here is my code in component:
componentDidMount() {
this.reqNotifications()
this.checkNotificationPermission()
}
reqNotifications() {
requestNotifications(['alert', 'badge', 'sound']).then(({status, settings}) => {
console.log('NOTIFICATION STATUS' + status)
});
}
async checkNotificationPermission() {
const enabled = await messaging().hasPermission();
if (enabled) {
console.log('APPROVED');
await messaging().registerForRemoteNotifications()
messaging().getToken().then(token => console.log('token: >> ' + token))
} else {
console.log('NOT APPROVED');
}
}
I am requesting permission via react-native-permissions and permission request is
working.
My Apple APNs are OK on Apple and Firebase console
And I am getting my token by getToken() method on the code
succesfully.
But I cant send anything to device from firebase; nothing happening on neither foreground nor background . I tried with-token test and also tried normal but no, nothing happens.
I added this code to componentDidMount:
messaging().onMessage(async remoteMessage => {
console.log('FCM Message Data:', remoteMessage.data);
});
As I understand this subscribes for cloud messages and when I send some cloud message notification from firebase-console, I should get console output; but nothing happens.
I dont know what am I missing but I think there is a big update on this package and most of docs are for previous version and I really stuck here thanks for assist
for rnfirebase.io V6
componentDidMount = async () => {
this.checkNotificationPermission();
await messaging().requestPermission({provisional: true});
await messaging().registerDeviceForRemoteMessages();
await this.getFCMToken();
if (Platform.OS === 'android') {
this.createAndroidNotificationChannel();
}
this.backgroundState();
this.foregroundState();
};
checkNotificationPermission = () => {
firebase
.messaging()
.hasPermission()
.then(enabled => {
if (!enabled) {
this.promptForNotificationPermission();
}
});
};
promptForNotificationPermission = () => {
firebase
.messaging()
.requestPermission({provisional: true})
.then(() => {
console.log('Permission granted.');
})
.catch(() => {
console.log('Permission rejected.');
});
};
createAndroidNotificationChannel() {
const channel = new firebase.notifications.Android.Channel(
'channelId',
'Push Notification',
firebase.notifications.Android.Importance.Max,
).setDescription('Turn on to receive push notification');
firebase.notifications().android.createChannel(channel);
}
foregroundState = () => {
const unsubscribe = messaging().onMessage(async notification => {
console.log('Message handled in the foregroundState!', notification);
});
return unsubscribe;
};
// Register background handler
backgroundState = () => {
messaging().setBackgroundMessageHandler(async notification => {
console.log('Message handled in the background!', notification);
});
};
I have an application written in NativeScript. I use Firebase plugin for push notifications. The first problem is that when a device is in the background or it's killed I can't receive any notifications (sending only data parameter) but when I open the app then notification is generating.
The second problem is that when I try to send a push notification (the app is killed) with notification and data parameter the local notification is generating correctly but the callback is executed on notification click, not in the background (my view has not been updated by new data).
Here is part of NativeScript code:
firebase.init({
onMessageReceivedCallback: (message: Message) => {
console.log(`Title: ${message.title}`);
console.log(`Body: ${message.body}`);
console.log(`Data: ${message.data}`);
const data = message.data;
const action = data.action;
// STORE RESERVATION
if (action === ItemConstants.STORE_RESERVATION) {
const item = this.prepareOnlineData(data);
const result = this.databaseService.saveReservation(item);
if (result !== -1) {
console.log("Saved to local database!");
} else {
console.log("Error occurred!");
}
}
// DENY RESERVATION
if (action === ItemConstants.DENY_RESERVATION) {
this.databaseService.setReservationStatus(
ItemConstants.STATUS_DENIED, data.tracking_id
).then(result => {
console.log(result);
}, error => {
console.log(error);
});
}
}
}).catch(error => {});
and the part of PHP code that calls Google Service:
$fields = array(
'to' => $to,
'notification' => [
'title' => 'reservation title',
'body' => 'you have new reservation',
'sound' => 'default'
],
'data' => $data,
'priority' => 'high',
'delay_while_idle ' => true
);
// calling curl - google services.
Does anyone have an idea how to fix this issue?
This is my database structure:
I am trying to list all users with "locale" equal to "Cairo, Egypt" so I made the following query:
exports.calculateMatches = functions.https.onRequest((request, response) => {
// Access users' profiles that are located in the locale of the requesting user
databaseRef.child("users").orderByChild("locale").equalTo(request.query.locale).once("value")
.then(snap => {
snap.forEach(profile => {
console.log(profile);
});
});
});
Note this function is deployed to firebase cloud functions and this is what I get in the logs:
HTTPS type functions require that you send a response to the client in order to terminate the function. Without that, they will always time out, and the client will be waiting the whole time.
For example:
const databaseRef = admin.database().ref('')
exports.calculateMatches = functions.https.onRequest((request, response) => {
databaseRef.child("users").orderByChild("locale").equalTo(request.query.locale).once("value")
.then(snap => {
const profiles = []
snap.forEach(profile => {
profiles.push(profile.val())
});
response.send(profiles)
})
.catch(error => {
response.status(500).send(error)
});
});