how to keep pusher running in background in vue and js - vue.js

I am trying to keep pusher running in when my app is in background . I am creating pusher instance as global variable like this
app.config.globalProperties.pusher = new Pusher("1", {
cluster: "ap2",
wsHost: "siloc.xyz",
wsPort: 6001,
wssPort: 6001,
forceTLS: false,
// enabledTransports: ['wss'],
encrypted: true,
authEndpoint: "https://abcd.com/api/pusher/auth",
});
Here is my background mode code
BackgroundMode.on('activate').subscribe((res) => {
///Here it should work
});
Reason of doing that is it stops working after five minutes when app is in background

Related

React-Native Expo: Background location service never end

Hi I'm very new to react native and facing big challenge for how to stop background processing when app is killed.
Quick Background:
Tracking location using 'expo-location' library:
await Location.startLocationUpdatesAsync(LOCATION_TRACKING, { accuracy: Location.Accuracy.Highest, showsBackgroundLocationIndicator: true, foregroundService: { notificationTitle: 'App Title', notificationBody: 'Location tracking in background',},});
and using 'TaskManager' to process on background (ref: Expo Task Manager)
It is not perfect but I can collect location data while running on foreground and background 👍.
Major problem is... if I don't stop using stopLocationUpdatesAsync method, it continuous running even you kills app until delete the app for stop process from settings.
May I ask your precious suggestion around this issue?
To close all tasks when the app is exited you can add the following to your App.tsx:
useEffect(() => {
return () => {
console.log("STOPPING ALL REGISTERED TASKS");
TaskManager.unregisterAllTasksAsync();
};
}, []);
You will notice your location task stops when a user closes the app.

Capacitor / Ionic / Vue Local Notification eventlistener

I'm trying to get Local Notifications working in an Ionic Vue app (using capacitor).
I did get scheduling notifications working, but now i want to listen to clicks on the notification.
in main.js I bind LocalNotifications to this.$LocalNotifications:
import { Plugins } from '#capacitor/core';
const { LocalNotifications } = Plugins;
Vue.prototype.$LocalNotifications = LocalNotifications;
in my Root component App I have this:
created() {
console.log('Created!')
document.addEventListener('deviceready', () => {
console.log('ready');
this.$LocalNotifications.addListener('localNotificationReceived', (notification) => {
console.log('Notification action received', notification);
});
}, false);
}
When I build and run on the ios-emulator, i get the following output in my log:
APP ACTIVE
To Native Cordova -> Badge load Badge1248600129 ["options": []]
⚡️ [log] - onscript loading complete
To Native Cordova -> Device getDeviceInfo Device1248600130 ["options": []]
⚡️ To Native -> Storage get 90127150
⚡️ TO JS {"value":null}
⚡️ [log] - Created!
To Native Cordova -> LocalNotification launch LocalNotification1248600131 ["options": []]
To Native Cordova -> LocalNotification ready INVALID ["options": []]
⚡️ To Native -> LocalNotifications addListener ⚡️ [log] - ready
90127151
⚡️ WebView loaded
⚡️ To Native -> App addListener 90127152
When I schedule a Notification, the notification does show up, but I think something doesn't go quite well when i'm adding the listener:
INVALID ["options":[]]
Does anyone have any idea how to solve this?
Or does anyone have a code example of working notifications in an Ionic Vue app?
Kind regards,
Bram
To sum up:
You should use localNotificationActionPerformed instead of localNotificationReceived. The latter is called when notifications are displayed, while the other is listening to actions performed on a notification (as it's stated in the docs), that of course includes clicking / tapping on it.
So your code would look like this:
this.$LocalNotifications.addListener('localNotificationActionPerformed', (notification) => {
console.log('Notification action received', notification.actionId);
});
...which would output "tap". Since you did write 'Notification action received', I assume you wanted to get the action, so I added .actionId after 'notification', which only by itself would be logged as [object Object] or as the object tree.
You also asked for code example, so here it comes:
// 1.
import { LocalNotifications } from '#capacitor/local-notifications';
// 2.
await LocalNotifications.requestPermissions();
// 3.
await LocalNotifications.registerActionTypes({
types: [
{
id: 'your_choice',
actions: [
{
id: 'dismiss',
title: 'Dismiss',
destructive: true
},
{
id: 'open',
title: 'Open app'
},
{
id: 'respond',
title: 'Respond',
input: true
}
]
}
]
});
// 4.
LocalNotifications.schedule({
notifications: [
{
id: 1,
title: 'Sample title',
body: 'Sample body',
actionTypeId: 'your_choice'
}
]
});
// 5.
LocalNotifications.addListener('localNotificationActionPerformed', (notification) => {
console.log(`Notification ${notification.notification.title} was ${notification.actionId}ed.`);
});
1: Since your question, plugins have been placed into their own npm packages, so one needs to install #capacitor/local-notifications and import from there.
2: You should make sure that notifications are allowed, ask for permissions if needed.
3: Tapping was your question's topic, but you can define a lot more than that.
4: This is how you actually create & send a notification at once.
5: Logs "Notification Sample title was taped / opened / dismissed / responded.", according to the given action (but not always according to grammar).
Finally, if someone's just getting into local notifications, check out the really nice documentation on what else (a whole lot more!) can be done and also watching this video might give one a head start. At least that's what I did.

Close redis connection when using NestJS Queues

I'm trying to setup E2E tests in a NestJS project, however, jest output looks like this:
Jest did not exit one second after the test run has completed
After a lot of reading this is because there are some resources, not yet liberated, after some debugging it turns there's an open connection to redis created by ioredis which is used by bull which is used by NestJS to do task queue processing. The thing is that I don't have a reference to the connection in the test code, so how can I close it? I'm tearing down the Nest application in the afterAll jest's hook like this:
afterAll(async () => {
await app.close();
});
but it does nothing, the connection is still there and the jest error message persists. I know I can just add the --forceExit to the jest command but that is not solving anything, it's just hiding the problem under the rug.
This took me awhile to figure out. You need to close the module in the afterAll hook. I was able to find this from looking at the tests in the nestJS Bull repo.
describe('RedisTest', () => {
let module: TestingModule;
beforeAll(async () => {
module = Test.createTestingModule({
imports: [
BullModule.registerQueueAsync({
name: 'test2',
}),
],
});
});
afterAll(async () => {
await module.close();
});
});
https://github.com/nestjs/bull/blob/master/e2e/module.e2e-spec.ts
After struggling almost to getting depressed i found a solution that worked for me.
I'm using "#nestjs/bull": "^0.3.1", "bull": "^3.21.1".
because the queue from bull package uses redis, it keeps the connection open although the module & app are closed.
await moduleRef.close();
await app.close();
i realized that when using --detectOpenHandles while relying on leaked-handles library for more information, you will see something like this in the console:
tcp stream {
fd: 20,
readable: true,
writable: false,
address: {},
serverAddr: null
}
tcp handle leaked at one of:
at /media/user/somePartitionName/Workspace/Nest/project-
name/node_modules/ioredis/built/connectors/StandaloneConnector.js:58:45
tcp stream {
fd: 22,
readable: true,
writable: true,
address: { address: '127.0.0.1', family: 'IPv4', port: 34876 },
serverAddr: null
}
Solution
using beforEach() & afterEach()
in beforEach(), add this instruction to get an instance of your queue :
queue = moduleRef.get(getQueueToken("queuename"));
in afterEach(), close the queue like so: (also close your app & module for better practice)
await queue.close();
Note
using beforAll() & afterAll() doesn't work and the same problem occurs, at least from what i have tried, both beforEach() & afterEach() work combined.
You don't have to add queue.close() to every test, just close queues in their own service/provider using OnModuleDestroy Hook:
#Injectable()
export class ServicesConsumer implements OnModuleDestroy {
constructor(
#InjectQueue('services')
private readonly servicesQueue: Queue,
) { }
async onModuleDestroy() {
await this.servicesQueue.close();
}

Showing fcm notification message in JSON format when app is killed or in background in react-native-fcm

I am using react-native-fcm library for android device. I am getting notification properly when my application is running, but when my application is in the background or killed then I am getting notification data in JSON format similarly in an image I shared here.
componentDidMount() {
// iOS: show permission prompt for the first call. later just check permission in user settings
// Android: check permission in user settings
FCM.requestPermissions().then(()=>console.log('granted')).catch(()=>console.log('notification permission rejected'));
/*FCM.getFCMToken().then(token => {
console.log('Token',token)
// store fcm token in your server
});*/
this.notificationListener = FCM.on(FCMEvent.Notification, async(notif) => {
console.log('FCM notification', notif)
this.sendRemote(notif)
});
// initial notification contains the notification that launchs the app. If user launchs app by clicking banner, the banner notification info will be here rather than through FCM.on event
// sometimes Android kills activity when app goes to background, and when resume it broadcasts notification before JS is run. You can use FCM.getInitialNotification() to capture those missed events.
// initial notification will be triggered all the time even when open app by icon so send some action identifier when you send notification
/*FCM.getInitialNotification().then(notif => {
console.log('FCM', notif)
this.sendRemote(notif)
//console.log('Initial Notification',notif)
});*/
FCM.getInitialNotification().then((notif: any) => {
// for android/ios app killed state
console.log("ifAny",notif)
if (notif) {
console.log("Any",notif)
// there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
}
});
}
sendRemote(notif) {
var data = notif.fcm.body;
var title = notif.fcm.title;
FCM.presentLocalNotification({
title: 'App Name',
body: title,
big_text: title,
large_icon: 'ic_launcher',
priority: 'high',
sound: "default",
click_action: this.clickActions(notif),
show_in_foreground: true,
wake_screen: true,
local: true,
param: notif.notify_about,
paramData: data
});
}
notify_about:'',
fcm:{action:null,
body:"{data:'',time:''}",
color:null,
icon: '',
tag:null,
title:"Notification title"}
this is my data format which I am sending from the server.
Here I want to show only data body. But when the app is killed or in the background, it shows the complete body in the notification.And Its working fine when the app is running.

Multiple realms in React Native don't query realm object server correctly on first launch of app after install

I am having an issue dealing with multiple realms in React Native. I'm working on an app that allows users to use the app without having a subscription (using a local realm) and then at any point in their app journey they have the option of upgrading to a subscription with syncing (which uses sync to a realm object server).
When I start the app I check to see if they are using sync and if so I initialize a synced realm with their user and everything works great. I get all the data I expect.
However, when the app starts on first launch after install (that part about first launch after install is crucial) and I see that they don't use sync I initialize a local realm which I save data to until they decide to log in to their sync account (if they have one). At this point I attempt to pull information from the synced realm but it does not have the information that I saw when I only initialized the synced realm (in the case that on app startup I detect they use sync).
I am able to log in as the sync user but the data isn't there if I've previously initialized a local realm AND this logic gets run on the first launch of the app after install. The data only shows up from the realm object server when I initialize a local and synced realm on a secondary launch of the app (no reinstall before launching).
Here's a simple test script with dummy data in it with which I've been able to replicate the observed behavior:
const username = 'testuser2';
const password = 'supersecret';
const tld = 'REALM_OBJECT_SERVER_TLD';
class Test extends Realm.Object {}
Test.schema = {
name: 'Test',
properties: {
id: {
type: 'string',
},
}
};
function initLocalRealm() {
return new Realm({
path: 'local.realm',
schema: [Test],
});
}
function initSyncedRealmWithUser(user) {
return new Realm({
path: 'synced.realm',
sync: {
user,
url: `realm://${tld}:9080/~/data`,
},
schema: [Test],
});
}
function writeTestObjectWithId(realm, id) {
realm.write(() => {
realm.create('Test', {
id,
});
alert(`Test object with id: ${id}`);
});
}
initLocalRealm();
// setup
// uncomment this and comment out the login section to setup user on first run
// Realm.Sync.User.register(`http://${tld}:9080`, username, password, (error, user) => {
// if (error) {
// return;
// }
// const syncedRealm = initSyncedRealmWithUser(user);
// writeTestObjectWithId(syncedRealm, '1');
// });
// login
Realm.Sync.User.login(`http://${tld}:9080`, username, password, (error, user) => {
if (error) {
return;
}
const syncedRealm = initSyncedRealmWithUser(user);
alert(`Synced realm test objects: ${syncedRealm.objects('Test').length}`);
});
If you create a react native app and then add this code to the main components componentDidMount function you should see that on the first run of the app (after you've uncommented the register code once) you will see the Test collection length at 0, but then when you refresh you will see the Test collection length at 1.
Any help on this would be awesome.
Thanks!
running your code snippet, I get a length of 1 immediately as soon as I uncomment the login section. Could you try observing your synchronized realm with the Realm Browser and see if it seems to have the data you are expecting after registering the user?