Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does anyone know if this works with iOS 13 without issue? #16

Open
Bobisback opened this issue Dec 23, 2019 · 37 comments
Open

Does anyone know if this works with iOS 13 without issue? #16

Bobisback opened this issue Dec 23, 2019 · 37 comments

Comments

@Bobisback
Copy link

I am just wondering if anyone has used this with ionic 4 and iOS 13?

Does anyone know if it is compatible with https://github.com/WebsiteBeaver/CordovaCall?

I am trying to build a VOIP app with proper push notification support. Has anyone done this in Ionic before?

Thanks,
Bob

@mattkhaw
Copy link

I'm currently developing VOIP functionality for my app and I'm using the latest Cordova and iOS 12 (since I don't have a newer device). All I can say is it only works on foreground since WKWebView doesn't execute any Javascript code when the app is on the background. I'm also looking an answer for this.

To answer your question, yes. It works quite well only when the app is on the foreground. I'm using the same plugin as you stated above. For now, the only way to handle this is using Objective C code to handle the incoming call portion during background state. For closed state, I think it is similar to background state. Luckily I don't need to use this to handle during foreground state but I'm having headaches on how to pass back to Cordova when incoming call is reported. I wish someone can give me some hints for that.

@Bobisback
Copy link
Author

Ya right now I have a project that has similar requirements. I am trying to figure out how to tie into callkit with apps in the background that works with cordova and ios 13.

Probably going to start with figuring out android though before i try and tackle iOS. Looks like I may just have to write a cordova plugin to get this to work :(

@mattkhaw
Copy link

For Android, it seems to be way easier. I haven't do the actual implementation but it should be very straight forward. For Android, it should be just pushing a silent notification and handle everything there. It is just iOS being pain in the ass.

AFAIK, the issue lies in the WKWebView. When app is pushed to the background, WKWebView just suspends all activities, making this plugin's callback worthless. From what I've searched so far, this plugin will work if the app is built using iOS 12 SDK but unfortunately, all app updates will be rejected if it is not built on iOS 13 SDK starting from April 2020. So, no matter what, we still need to figure out on how to implement. It feels redundant when we need to redo some portion of the code if we are using CordovaCall plugin since it is the same code. I'm trying to modify the plugin to be able to call the other plugin internally. However, I'm not very well versed with Objective C and I need time to read back most of the materials I've forgotten.

My current idea is to report the incoming call and end it immediately just to fulfil the requirement for iOS 13 SDK and hope that the callback triggers later when the app is successfully launched. Maybe you can give that a go and if it works, please share the code as well. I'm also running on a strict deadline and also running out of ideas.

@Bobisback
Copy link
Author

Bobisback commented Jan 16, 2020

Maybe we should collaborate on this? I would love to get a second head to bounce things off of.

I was thinking android would be similar to what you are saying, but I need certain things like being able to answer with bluetooth devices, integration with existing telephony services, and similar functionality for both background, foreground, and app closed situations.

Since I know iOS is a pain point I offered my clients android first then deal with iOS. I am just scared because I am not 100% sure if cordova call will do all these things for android. I for sure do not want a situation where I use cordova call just for android but do something completely different for iOS. Would rather deal with it all at once.

I am actually decent in objective C, but I have never built a cordova plugin before. SO just to make sure I am understanding correctly, what plugin are you trying to get cordova call to talk with? Are you trying to get this to interface with the phonegap-plugin-push? Or are you just writing a new plugin that basically fulfills the requirements of callkit and iOS but just starts your code and kills the phone call?

@mattkhaw
Copy link

mattkhaw commented Jan 16, 2020

I don't mind collaborating. I'm in dire need of any suggestions I can get.

For Android, it should work based on my suggestion. The only issue is that Android is using regular push so, delays might occur. For foreground processing, it is super easy. I'm using SignalR for that so, it will arrive immediately.

For your question on CordovaCall library, CordovaCall will do the same for both Android and iOS. I've actually implemented this in the current version of my project. The plugin is good enough to handle all the incoming and outgoing interfaces. The only thing we need to handle is the signalling part, which now involves push notifications to wake the devices up and execute the Javascript code of our app.

I'm not really well versed in Objective C but I've used them before last time. But that's a long time ago. I've built Cordova plugins for both Android and iOS. So back to your question, I'm using this plugin to receive VOIP pushes and then callback to Cordova and execute CordovaCall so that I can show the incoming call screen. That's the idea, however, like I've stated in my previous comments, iOS is making this very difficult since WKWebView is paused when it is sent to the background, hence the plugin callback on this plugin won't work, as a result, CordovaCall will never be executed. Also, I'm not using phonegap-plugin-push for my notifications. I'm using OneSignal for the regular pushes. But that's unrelated to this topic for now since we are talking about iOS. That scenario will be applicable to Android later.

The reason why I was thinking like that as stated in my previous comment is because in order to avoid your app not being killed by the OS is to report an incoming call once you received a VOIP push notification. Since Javascript code cannot be executed, the only way to do so is to modify this plugin to just include an instance of CallKit and report a new incoming call then immediately end it so that the screen doesn't appear to trick the app to launch and execute the plugin callback just to run our Javascript code. Not sure whether it will work, but I think by doing so, your app won't shutdown immediately after receiving that said notification. This applies to the current iOS 13 SDK.

I don't wish to create another plugin just handle this situation since we've already included CordovaCall plugin as well, the code is already there. It will be quite redundant to just add another instance to this plugin. That's why I was thinking to just call it from Objective C as stated above.

I think maybe we should take this to a messenger app. Easier to exchange thoughts instead of waiting for replies here. It seems faster that way for discussions.

@Hitman666
Copy link
Owner

Hey all,

Yeah, unfortunately, my focus shifted and I can no longer support this plugin :(

To give my two cents on:

Since Javascript code cannot be executed, the only way to do so is to modify this plugin to just include an instance of CallKit and report a new incoming call then immediately end it so that the screen doesn't appear to trick the app to launch and execute the plugin callback just to run our Javascript code. Not sure whether it will work, but I think by doing so, your app won't shut down immediately after receiving that said notification.

You have to keep in mind that your app for iOS will be tested by an actual human, and (in my experience) it varies greatly on the actual reviewer. So, while the idea to immediately end the call and thus not have the app crash may be a good one from the technical perspective, but you'll have to think about how you're going to explain to the reviewer why you need the VoIP push if he catches you just ending the call.

This will be a very unpopular answer (and trust me, I had to go through that too as I was a big supporter of hybrid solutions, and it was hard to accept that something came that Ionic/Cordova/Hybrid can't handle) but if your app leans a lot on the newest physical features of the phone or newest API features that the newest version of iOS supports, it may be a good long term solution to go with the native approach.

We had 33 (yes, 33) plugins in our app, some of which (4) I wrote because they didn't exist at the time. At that number of plugins, the hybrid advantage of write-once diminishes and you have to still learn iOS/Android to be able to write the plugin. Not to mention the additional code that handles the 'bridge' communication.

Now, don't get me wrong, I'd still advocate hybrid for the majority of the business apps where you have to fetch some data from an API, filter, sort, etc and you're done. However, there are cases (sure, very few) where it's not applicable. This seems to be one of them.

I wish you good luck with your projects!

@Bobisback
Copy link
Author

I am not sure the best way to exchange contact information on github, do they have a direct message feature?

@mattkhaw
Copy link

@Hitman666 Thanks for the reply. Not to say I can't write in native code. I just want to simplify the code writing portion for my colleagues since they don't have the knowledge to write in native code. I do understand that our apps will be tested by humans but at the end of the day, I'm not trying to break any regulations they set but more on workaround them. I'm just redirecting it to somewhere else. Also, I've already included in CallKit via Cordova plugin. So it doesn't make any sense to write something extra as well. However, the issue here is in this scenario, I don't think the plugins will be able to talk to each other due to the fact that I can't even retrieve them via getPlugin function. Even if I do, I need to initialise first before I can do anything with it.

One more thing is that we have to prepare our apps starting now is because starting April 2020, iOS 13 SDK will be the norm since Apple doesn't accept any app updates if you use iOS 12 SDK to build them. I know those big names like WhatsApp are doing that but it won't affect them due to the fact that it is written in native. It is Cordova which is giving me a big headache. That's why the more suggestions, the better.

I've partially modified your plugin to suit my payload delivery. This is the final puzzle. The reason why I wish to redirect back to Cordova is because all of the logic is written there, I don't wish to repeat the code in native. If native is the only option, then I'll have to write them but the current plugin as is will not work in iOS 13 SDK due to the requirement that I've mentioned before. I guess the best way might just be adding CallKit instance into your plugin and handle plugin callbacks for this purpose only.

@Bobisback Well, maybe discord or FB messenger or some collaboration app which has instant messaging will work fine. I don't intend to chat in GitHub anyways. We still can exchange thoughts here but for brainstorming ideas, I feel that instant messaging will be faster. We just have to do whatever we can in order to achieve our goals. I'll be testing some methods or workarounds today. I'll let you know the results later.

@mattkhaw
Copy link

@Bobisback I've tested my method, apparently there's a slight delay to end the call. But the callback works as intended. I might need to find a way to get the CordovaCall plugin instance within Objective C. I've only tested on background. I haven't tested closed state yet.

@Bobisback
Copy link
Author

Cool great that you made some progress, better than me at the moment.

I am fine with whatever program we use and agree it would be better to use a chat app. Just not excited about publishing my contact info on github hahahahah. Wondering if there is a better way to do it.

I use slack for most of the developer communications, I have some workspaces I could invite you to.

@mattkhaw
Copy link

mattkhaw commented Jan 17, 2020

Understandable. I'm down with any. Unfortunately I don't have a Slack account. Need to create one.

At the moment, could you help me with finding a command which I can get CordovaCall's instance from this plugin? I have an idea but I'm struggling to find this specific command. It would be a big help if you can tell me how to get that particular instance. Thanks.

Reason why this might be important is because if I can get the CordovaCall's instance, all the states of that particular plugin will be retained, meaning when you post a callback to Cordova later, all the information will be shared. Easier for state management. I'm going crazy over this because I need to read and catch up with Objective C and at the same time, solving this particular problem. If the instance is not accessible, then I do think that there's no choice but to have this plugin merge with CordovaCall plugin so that all is working as intended.

@Bobisback
Copy link
Author

I would have to look at the code to help with your question, I do not know enough about it to answer off the top of my head.

Maybe we can create a fork of this or cordova call and merge the two together and work on that fork. Would be cool if we could add in android as well and solve all the problems with one plugin.

@mattkhaw
Copy link

Upon doing some trial and error, I've decided to merge the 2 plugins so that CordovaCall can retain its state when VOIP push notification is received. This is the final answer to this question. Reason being is because in iOS 13 SDK, it is required to report any incoming calls otherwise the app will be terminated as stated previously.

I've tried all scenarios, foreground, background and closed states. It worked fine after the merge. The only thing left for me to take care of is to handle resume and launch states. I'll report back once I've done all the code. This is only for iOS. As for Android, just use silent notifications for this purpose. That should work. Other than app state handling, I also need to put back CordovaCall's Android functionality as well.

@Bobisback
Copy link
Author

Bobisback commented Jan 21, 2020

Using silent notifications on android can this still intagerate correctly with the android telephony system using cordova call?

Edit: Also when you say merged the two plugins do you mean CordovaCall and this VOIP Push plugin?

@mattkhaw
Copy link

For Android, yes. I do think that's the way to go. Since you are now working on Android, maybe you should give it a try. I'm now focusing on fixing my app. I'll get to Android when I've finished with iOS.

Yes, I'm merging CordovaCall and this plugin together to make it work. I can't think of a better way to solve my current problem and it seems that CDVPlugin doesn't have any commands to get plugin instances from your app.

@mattkhaw
Copy link

mattkhaw commented Feb 5, 2020

@Bobisback Do you have any progress on this issue?

@mattkhaw
Copy link

Just an update, I've already completed the integration for VOIP Push with CordovaCall for both Android and iOS. I've also found out that you don't actually need to merge those plugins together if you don't want to for iOS. But no matter what, still need to modify the plugins based on your requirements. So, downloading both of them is mandatory.

For the actual implementation, all you need to do is to separate the interface from CordovaCall.m to CordovaCall.h and declare a static instance variable so that later you can import it into VOIP Push plugin. Next, access the CordovaCall instance in VOIP Push plugin where the notification actually fires, and call receiveCall function. That's all you need to do for iOS. As for Android, just use notification extender to handle it. Beyond this will be handling app states in Cordova side.

Thanks @Hitman666 for this plugin. It really made me understand on how VOIP Push works on iOS side and made my job a little easier. As for the steps mentioned above, that will not be the route I'm gonna take since I've already merged the plugins into one to lessen the total plugins installed and also because of iOS 13's mandatory requirement of reporting incoming calls when VOIP notification is received.

@Hitman666
Copy link
Owner

Hitman666 commented Feb 13, 2020 via email

@Haroon6138
Copy link

@mattkhaw I need to do the same as you but i am unable to understand this all as i do not know native iOS development. It would be great if you can share the merged code. Thanks

@mattkhaw
Copy link

mattkhaw commented Mar 9, 2020

@Haroon6138 At first I don't either but I roughly get what I need to do. As I've mentioned previously, it is not mandatory to merge the 2 plugins into 1 single plugin, but modifying on the native level is. No matter what, you still need to know some objective C or swift due to the changes being implemented in iOS 13 SDK. WebView portion doesn't initialize at the VOIP push notification level because of one simple reason, the app hasn't been started yet. The app only starts when it reports a new incoming call. That's the key here. Also, VOIP push notifications have to be modified as well because each project has different payloads that they need to process. Hence, you still need some knowledge.

I might post it on GitHub once I've done with the npm packaging thing so that it is easier to access but now I got my hands tied at the moment due to the current workload I have. I wish I have another pair of hands that I can easily use. I'll post an update when I've done so.

@mattkhaw
Copy link

@Bobisback @Haroon6138 Just an update, I've uploaded the plugin to GitHub and done with the NPM. Just follow the link to get my take on this. I do hope that this will help you guys. This is as far as I go. The rest is up to you guys. Good luck with your current projects!

@Bobisback
Copy link
Author

Hey thanks a ton for the work on this. My client ran out of money so I have not been able to do anything in this area.

Looks like you got it figured out though. Thanks for doing this!

@mattkhaw
Copy link

@Bobisback It took a while but in the end, I did figure it out. That's unfortunate that you couldn't proceed further. But I've posted the solution anyways, maybe one day you might need it.

@Bobisback
Copy link
Author

Bobisback commented Mar 18, 2020 via email

@Qvadis
Copy link

Qvadis commented Apr 1, 2020

I just want to thank you guys for this contribution, @mattkhaw in particular, for your great job.
I was stuck for several weeks trying to modify the push plugin to comply with the new ios13 voip policy. Your new plugin works perfect and handle voip notifications properly.
I really appreciate your job.
Thank you so much!

@mattkhaw
Copy link

mattkhaw commented Apr 1, 2020

@Qvadis I'm glad that my tinkering helped you. I just found the solution by accident after some trial and error. All the work still goes to both creators of those functions.

Now I wish Apple would give us a push notification function to wake the app up so that we can use Cordova to handle everything. I guess the reason for this change is other developers are sort of abusing it hence the policy is in place. That's my guess.

@Qvadis
Copy link

Qvadis commented Apr 1, 2020

Yeah, I´m sure that´s the reason behind the policy change.
I also wish Apple providing us with reliable push notifications to wake the app (I´ve experienced that an alert push notification with the content-available payload wakes the app many times, but not always), but not really confident.

@savgiannis
Copy link

savgiannis commented Apr 23, 2020

@mattkhaw Hi, I've read all the conversation and well done on creating your plugin to fix the issue. I am working on a video call app and I've searched all the internet just to find out that this is not the easiest thing to do with cordova. Anyway, I use twilio-video sdk to create video rooms for 1 to 1 video calls. I also use signal r to inform the user that has incoming call (if the app is in foreground) and push notifications if the app is in the background. When the user taps the push notifications the app opens, and this is what I want to change. I want to open a call UI like viber/messenger/whatsapp do and open the twilio video there somehow. Is that possible with cordova and the cordovaCall plugin? I would appreciate your help since i did not find anything after days of searching.

@mattkhaw
Copy link

@savgiannis To answer your question, yes. The merged plugin I've created will do the job if you are using iOS 13 SDK to build. The way that viber/messenger/whatsapp is doing is by using an earlier version of the SDK to build and uses VOIP push notification to open the app and display their custom UI. With iOS 13 SDK, they can't do that anymore because after receiving the notification, developers are required to report the incoming call to the OS or else it will be terminated prematurely or banned from getting further notifications until the next reinstall. I know that might not be relevant, but good to know on how they managed to do it.

As what I've said earlier, it is not mandatory to use my plugin. But after explaining on how it is done, the current plugins need to be modified anyways. So, to save time, I've decided to share this with everyone. I have a similar setup with yours and so far, it works as intended.

If you are still not convinced, there's a post in StackOverflow where someone has used my plugin and did say that it works as intended. You can find it here.

@mattkhaw
Copy link

Yeah, I´m sure that´s the reason behind the policy change.
I also wish Apple providing us with reliable push notifications to wake the app (I´ve experienced that an alert push notification with the content-available payload wakes the app many times, but not always), but not really confident.

@Qvadis The reason why that is not working reliably is because normal push notifications are not sent immediately. The other reason is content-available payload only works if the app is running. If the app is killed, it will never reach client side. That's why developers used VOIP push notifications instead since it is delivered immediately and because of that, they used it for other purposes as well.

@savgiannis
Copy link

savgiannis commented Apr 24, 2020

@mattkhaw Thanks for responding immediately. I have not yet started to restructure my app because I am trying to understand the flow first because I am not sure I understand it correctly. So, as I see it there are two challenges: One is to wake up the app and one is to show custom call UI. On android the app wakes up with a silent notification and on ios with VOIP push notification and thats what your plugin solves, right? Assuming I wake up the app successfully how exactly I show my custom UI with the twillio video(webrtc) integrated? The cordova call plugin opens a generic ui similar to the phone call ui, while I want a component of my app to show up even if the app is killed and the phone is locked.Seriusly, if i manage to do it i'll make a youtube video about it since i've seen many questions for creating this with ionic/cordova and none has an answer!

@Qvadis
Copy link

Qvadis commented Apr 24, 2020

@Qvadis The reason why that is not working reliably is because normal push notifications are not sent immediately. The other reason is content-available payload only works if the app is running. If the app is killed, it will never reach client side. That's why developers used VOIP push notifications instead since it is delivered immediately and because of that, they used it for other purposes as well.

@mattkhaw, you´re right, and actually, that´s what theory says, but what I noticed in practice was a little bit different, and that unreliable behaviour got me crazy for some time.
In my testing, regarding time of arrival of the notification:

  • VoIP notifications always reaches the terminal within a second.
  • Push notifications reaches the terminal in less than 3 seconds, 99% of the times (pretty good actually, and valid for most purposes).

Regarding the wake up of the app:

  • VoIP always wakes up the app. simple.
  • Push notification (content-available and some kind of alert, which makes it no silent: badge, sound or alert message) almost always (90% of the times) wakes the app, even if it was explicitly killed by the user and the iphone was locked for half an hour! with no other activity. Pretty weird... sure there´s something related to the background modes that i´m missing...

@mattkhaw
Copy link

@savgiannis To answer custom UI part, you can't do that at all with iOS 13 SDK. Apple has locked it down. I'm just explaining that part on how they managed to do it, that's all. For upcoming releases, you pretty much will be stuck using their CallKit UI. As for Android, most likely you can use a custom UI but you pretty much need to modify the plugin so that the native UI won't appear. In doing so, your app on iOS will be very different in terms of look and feel. So, I don't think you will want that.

To answer the other part about waking the app up, I only solved the iOS portion. I didn't touch the Android portion since it can be done natively with any push notification plugin that supports background notifications. You have to implement that part yourself.

@Qvadis Yes, you are exactly right. The reason why developers are abusing VOIP push notifications on previous SDKs is because VOIP notifications always wake the app up and it will always guarantee arrival (from what I've tested). Also, it works even if your app is killed by the user. That's why in my previous reply, I did mention that background push notifications will not reach the user at all if the app is killed by the user and only works if the app is active/in background. That's by design. Even if you enabled all the modes given, this behaviour won't change.

@savgiannis
Copy link

@mattkhaw Ah, now I get it. But apart from the UI can I integrate twilio video (or any webrtc video) in the plugin's ui or that also needs native modification? As I see in the cordova-call docs in the ios UI(callKit?) there is a button to open video while in android there is not. But even if there is an "open video" button is it possible to tell it to open my webrtc video (and of course run js code to initialize it) while the app is in bg and the phone is locked?

@mattkhaw
Copy link

@savgiannis Everything else is fine and yes, UI is fixed. As for that particular button, the only thing we can change is the icon. As for Android, the button is there on stock Android. As for custom ROMs, it depends on the manufacturer. That part we can't control.

That button will redirect to your app. I'll let you figure out the event handling from there since there are a few frameworks out there and I might not be using the same as yours so, I'm not gonna comment on that. If you are still unsure on how that button works, I remembered that Snapchat has implemented CallKit for iOS and Android. You can download that and give it a try.

@AleksandarTokarev
Copy link

AleksandarTokarev commented Sep 8, 2020

@savgiannis did you manage to get this working? It seems for me @mattkhaw's plugin works fine when app is in foreground, but not when it is minimized/killed.
We have a WebRTC application in which we have Custom In App UI for calling. What i need to do is wake up the app, present the user a notification Accept/Decline, and if the User Answers take the user to the app. This can be done with https://github.com/WebsiteBeaver/CordovaCall

One thing i have noticed is, when the app is closed or in background, notifications are not coming.
I am using Meteor Cordova and this is on my local machine.
I am running on IOS 13
Sometimes when app is in background notification is coming, but i am getting this exception in XCode

Exception	NSException *	"Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback."	0x0000000281a58a20

Here is the code where i am receiving the notification

push.on('notification', function(data) {
    Logger.info("notification callback called")
    Logger.info(JSON.stringify(data))
    if (instance.state.isInBackground) {
        instance.state.gotInitiatedInBackground = true
        cordova.plugins.CordovaCall.setVideo(true);
        cordova.plugins.CordovaCall.receiveCall(data.extra.Username);
    }
    // do something based on received data
});

@mattkhaw
Copy link

mattkhaw commented Sep 9, 2020

@AleksandarTokarev I've just replied to your issue. Just check there. I highly suggest that you read up on how push notifications work in Apple's documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants