I am integrating OneSignal native code into a capacitor app.
I’m using the Quasar Framework, which uses Capacitor.
I can receive notifications and process them on the swift side of things. My receive-notification-logic resides in AppDelegate file.
I now want to pass the notification data over to Capacitor. So when the user logs in, I can retrieve his/her/their OneSignal id and send it to my API.
Or the other way around: When AppDelegate knows the OneSignal ID, trigger an event so the bridge can listen to this and send it via event or in a window variable to the Vue code.
Is there any way to achieve this?
I would be very grateful for any help.
Thank you very much for your response. I tried to use “CAPBridge”, but its not working in application(), where I had to put the OneSignal code. Do I have to create a plugin, like @pitahausen noted?
Here’s the code I tried:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// START OneSignal initialization code
...
// promptForPushNotifications
OneSignal.promptForPushNotifications(userResponse: { accepted in
CAPBridge.triggerWindowJSEvent(eventName: "onOneSignalOptin", data: "test_id_1234")
})
// END OneSignal initializataion code
return true
}
Error message is: Instance member "triggerWindowJSEvent" cannot be used on type "CAPBridge"; did you mean to use a value of this type instead?
If that doesn’t work I would try to create a plugin (you can just do it right in your native code, you don’t have to create a separate plugin project). Then have that plugin listen for a NotificationCenter event and send it from here instead of accessing CAPBridge
@max Thank you very much again. I created a plugin (Files: OneSignalPlugin.swift and OneSignalPlugin.m).
But how can I initialize the Plugin? Is there any kind of constructor or automatic init method or can I call my initPlugin() method from anywhere?
// OneSignalPlugin.swift
import Capacitor
extension Notification.Name {
static let onOneSignalOptin = Notification.Name("onOneSignalOptin")
}
@objc(OneSignalPlugin)
public class OneSignalPlugin: CAPPlugin {
/**
* Add event listener for NotificationCenter
*
* @see AppDelegate.swift
*/
@objc func initPlugin(_ call: CAPPluginCall) {
print("Init OneSignalPlugin")
NotificationCenter.default.addObserver(self, selector: #selector(optin(_:)), name: .onOneSignalOptin, object: nil)
call.resolve()
}
/**
* Executes on "onOneSignalOptin" event.
*
* How to listen in Javascript:
* window.addEventListener('onOneSignalOptin', (oneSignalId) => { /* YOUR CODE HERE */ }
*/
@objc func optin(_ notification:Notification) {
print("OneSignalPlugin: optin")
if let data = notification.userInfo as? [String: String]
{
for (identifier, value) in data
{
if (identifier == "oneSignalId")
{
self.bridge.triggerWindowJSEvent(eventName: "onOneSignalOptin", data: value)
}
}
}
}
}
@max thank you so much! This is how it worked! I’m so happy! I couldn’t use the window event but instead added a getStatus() to call from my javascript code.
Here is the full plugin:
import Capacitor
extension Notification.Name {
static let onOneSignalOptin = Notification.Name("onOneSignalOptin")
}
@objc(OneSignalPlugin)
public class OneSignalPlugin: CAPPlugin {
var notificationsEnabled: Bool = false
var oneSignalId: String = "undefined"
/**
* Add event listener for NotificationCenter
*
* @see AppDelegate.swift
*/
public override func load() {
print("Init OneSignalPlugin")
NotificationCenter.default.addObserver(self, selector: #selector(optin(_:)), name: .onOneSignalOptin, object: nil)
}
/**
* Executes on "onOneSignalOptin" event.
* Set oneSignalId so you can call getStatus() in your javascript code.
*
* e.g.: await window.Capacitor.Plugins.OneSignalPlugin.getStatus()
*/
@objc func optin(_ notification:Notification) {
print("OneSignalPlugin: optin")
let oneSignalId = notification.userInfo?["oneSignalId"] ?? "undefined"
let notificationsEnabled = notification.userInfo?["notificationsEnabled"] ?? false
self.oneSignalId = oneSignalId as! String
self.notificationsEnabled = notificationsEnabled as! Bool
}
@objc func getStatus(_ call: CAPPluginCall) {
call.resolve([
"notificationsEnabled": self.notificationsEnabled,
"oneSignalId": self.oneSignalId
])
}
}
Also thanks to @pitahausen. Unfortunately I’m not using ionic framework, so I don’t have any .ts file. Otherwise I’m sure your solution would have worked.
You should also be able to do something like this to get the CAPBridgeViewController and then use its bridge to call triggerWindowJSEvent or other bridge methods.
if let vc = window?.rootViewController as? CAPBridgeViewController {
vc.bridge?..triggerWindowJSEvent(eventName: "onOneSignalOptin", data: "test_id_1234")
}
@the5kyliner Thanks for suggestion on notifications, I am also using Quasar Capacitor Can you please help me configuring the push notifications in swift IOS.