Giter Site home page Giter Site logo

masashi-sutou / flutter_ios_voip_kit Goto Github PK

View Code? Open in Web Editor NEW
65.0 4.0 43.0 105 KB

One-to-one video call using CallKit and PushKit with flutter iOS app.

License: MIT License

Kotlin 4.32% Ruby 3.66% Swift 42.07% Objective-C 1.34% Dart 48.61%
flutter callkit pushkit voip webrtc

flutter_ios_voip_kit's Introduction

flutter_ios_voip_kit

One-to-one video call using CallKit and PushKit with flutter iOS app.

Motivation

We need to use CallKit to handle incoming VoIP notifications from iOS 13. Check the WWDC2019 video for more information. So instead of using CallKit and PushKit separately, there is a growing need to use them together. However, there are still few VoIP notification samples on the net that use CallKit and PushKit (especially for Flutter). I decided to create a flutter plugin with the minimum required functions. You can use this plugin, but the actual purpose is to help you create a VoIPKit tailored to your service.

Requirement

  • iOS only, not support Android.
  • iOS 10 or above.
  • one-to-one call only, not support group call.
  • need to a server for pushing VoIP notification with APNs.
  • to actually make a video or call, you need to link to a service such as WebRTC(ex: Agora, SkyWay, Amazon Kinesis Video Streams).

Usage

1. install

  • Add flutter_ios_voip_kit as a dependency in your pubspec.yaml file.

2. setting Capability in Xcode

  1. Select Background Modes > Voice over IP and Remote notifications is ON.
  2. Select Push Notifications.
  3. Changed ios/Runner/Info.plist after selected Capability.
<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
    <string>voip</string>
</array>

2. edit Info.plist

  • Edit ios/Runner/Info.plist as below.
<key>FIVKIconName</key>
<string>AppIcon-VoIPKit</string>
<key>FIVKLocalizedName</key>
<string>VoIP-Kit</string>
<key>FIVKSupportVideo</key>
<true/>
<key>FIVKSkipRecallScreen</key>
<true/>

3. add New Image set for CallKit

  • Add an icon(.png or .pdf) ios/Runner/Assets.xcassets/AppIcon-VoIPKit to use on the screen when a call comes in while locked iPhone.

4. create VoIP Services Certificate

Create .p12 from .cer with KeyChainAccess
openssl pkcs12 -in voip_services.p12 -out voip_services.pem -nodes -clcerts

If you're running OpenSSL version 3 or later, please note that you may need to include the "-legacy" option.

openssl pkcs12 -legacy -in voip_services.p12 -out voip_services.pem -nodes -clcerts

5. request VoIP notification APNs from your server

{
    "aps": {
        "alert": {
          "uuid": <Version 4 UUID (e.g.: https://www.uuidgenerator.net/version4) >,
          "incoming_caller_id": <your service user id>,
          "incoming_caller_name": <your service user name>,
        }
    }
}
  • You can use curl to test VoIP notifications as follows.
curl -v \
-d '{"aps":{"alert":{"uuid":"982cf533-7b1b-4cf6-a6e0-004aab68c503","incoming_caller_id":"0123456789","incoming_caller_name":"Tester"}}}' \
-H "apns-push-type: voip" \
-H "apns-expiration: 0" \
-H "apns-priority: 0" \
-H "apns-topic: <your app’s bundle ID>.voip" \
--http2 \
--cert ./voip_services.pem \
https://api.sandbox.push.apple.com/3/device/<VoIP device Token for your iPhone>

Try out example app

Select call role 🤙 Caller page 🔔 Callee page
🔔 Callee(incoming call) 🔔 Callee(locked) 🔔 Callee(locked) 🔔 Callee(recall)
🔔 Callee(unanswered local notification) 🔔 Callee(unanswered local notification)

Q&A

Does CallKit have a call and outgoing call screen?

  • No. CallKit support incoming call screen only. You need to make your own a call and outgoing call screens.

Can I use remote push device token instead of VoIP device token?

  • No. Since the specifications of VoIP token and push token are different, it is necessary to manage them separately in your database.

Can't get VoIP token on iOS13

  • Please uninstall the app, restart the terminal and reinstall the app. You can get it after a while.

Don't receive VoIP notifications

  • Please check the following items.
    1. Is the VoIP device token correct?
    2. Did you set your app’s bundle ID with .voip to apns-topic?
    3. Did you set voip to apns-push-type?
    4. Is the APNs endpoint(Development or Production) correct?
    5. For iOS13, VoIP notifications may not be received if call kit call fails many times. Please uninstall the app, restart the terminal and reinstall the app.

No icon is displayed on the incoming call screen when locked

  • The icon image should be a square with side length of 40 points. The color is ignored. Please design with the difference of alpha.
  • If created in PDF, checked Preserve Vector Data for Resizing and change Single Scale for Scales.
create icon (e.g.: sketch) Xcode Image Set

Reference

flutter_ios_voip_kit's People

Contributors

http600 avatar masashi-sutou avatar willowwisp avatar x401om avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

flutter_ios_voip_kit's Issues

Pub get warning

Running "flutter pub get" in SureVoIP-Talk...                       0.9s
The plugin `flutter_ios_voip_kit` doesn't have a main class defined in /home/ghenry/development/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_ios_voip_kit-0.0.4+1/android/src/main/java/netkeepingblog/flutter_ios_voip_kit/FlutterIOSVoIPKitPlugin.java or /home/ghenry/development/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_ios_voip_kit-0.0.4+1/android/src/main/kotlin/netkeepingblog/flutter_ios_voip_kit/FlutterIOSVoIPKitPlugin.kt. This is likely to due to an incorrect `androidPackage: netkeepingblog.flutter_ios_voip_kit` or `mainClass` entry in the plugin's pubspec.yaml.
If you are the author of this plugin, fix the `androidPackage` entry or move the main class to any of locations used above. Otherwise, please contact the author of this plugin and consider using a different plugin in the meanwhile. 

Triggering incoming call screen from voIPKit.onDidReceiveIncomingPush

Hi,

In

self.voIPCenter.callKitCenter.incomingCall(uuidString: uuid,

i.e. voIPKit.testIncomingCall, we don't have to do anything like:

self.voIPCenter.callKitCenter.incomingCall(uuidString: uuid,
                                                   callerId: callerId,
                                                   callerName: callerName) { (error)

or are we triggering the native incoming call UI in onDidReceiveIncomingPush? My understanding is that's where I will be calling my own logic, in this case re-connecting my SIP User Agent.

Thanks.

Crash app when app is running on background

I got this error: "Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback"

  • iOS version: 14.1
  • Xcode version: 12.4

VOIP not working when app closed (Background) in iOS 13 above

I have tried re-install app.
Your Example App is working in Foreground only not in Background( when app is closed)
I did receive some message in console but app is not invoked
I have added Background and VOIP capabilities.

My Server Code

var apn = require("apn");
 
  var deviceToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

let provider = new apn.Provider( 
    {
        token: {
            key: "AuthKey_XXXXXXXXX.p8",
            keyId: "XXXXXXXXX",
            teamId: "XXXXXXXXXXX",
            cert:"voip_services.pem"
        },
        production: false
    });

let notification = new apn.Notification();
notification.rawPayload = {
    "aps": {
        "alert": {
            "uuid": "xxxxxxxxxxxxxxxxx",
            "incoming_caller_id": "123456789",
            "incoming_caller_name": "Shivam",
        },
        "badge":2,
        'content-available': 1,
      "data": {
        "appointment_id": "47",
        "caller_name": "Shivam",
        "appointmentUUId": "22222222222222",
        "caller_id": "44",
        "type": "TO_DOCTOR",
        "click_action": "FLUTTER_NOTIFICATION_CLICK",
    },
    }
};
notification.pushType = "voip";
notification.topic = "com.xxxxx.XXXXXXXXX.voip";
notification.expiry = 0;
notification.priority = 5;

provider.send(notification, deviceToken).then((err, result) => {
    if (err) return console.log(JSON.stringify(err));
    return console.log(JSON.stringify(result))
});

Read custom key when accept incoming call

I want to make a video calling service with this and agora for this I need to pass token, channel. I'm passing those through apple but how can I receive those here when accept call

This is the json format I'm passing. How can I access the person object data. How can I access the "Token" object data from my app
{
"aps": {
"alert": {
"uuid" : "ddd",
"incoming_caller_id" : "dddds",
"incoming_caller_name" : "ddd"
},
"sound": "default"
},
"Token": {
"channel": "taddd",
"token": "token123",
"uid": "123"
}
}

active discussion tab in github

It would be cool, to have a "discussion" tab for that package, so questions about the usage can be posted there instead of the "issues" tab. It can be activated within the project settings.

iOS 16 with XCode 14 no support VOIP socket

The following message comes from XCode 14 on iOS 16 iPhone

libsp.dylib`spd_checkin_socket.cold.1:
0x2235d8364 <+0>: adrp x8, 141669
0x2235d8368 <+4>: adrp x9, 0
0x2235d836c <+8>: add x9, x9, #0xa3f ; "Linked against modern SDK, VOIP socket will not wake. Use Local Push Connectivity instead"
0x2235d8370 <+12>: str x9, [x8, #0x400]
-> 0x2235d8374 <+16>: brk #0x1

getVoIPToken hangs

Hi,

I've edited the example via Xcode to use our app identifier and did flutter run after changing the Signing Team. It just sits at getVoIPToken when I go to Your Callee page.

I've generated a VoIP Certificate, so I can test notifications like so:

curl -v \
-d '{"aps":{"alert":{"incoming_caller_id":"01224123456","incoming_caller_name":"Gavin Henry"}}}' \
-H "apns-push-type: voip" \
-H "apns-expiration: 0" \
-H "apns-priority: 0" \
-H "apns-topic: my_valid_identifier.voip" \
--http2 \
--cert ./my_valid_identifier.voip.pem \
https://api.sandbox.push.apple.com/3/device/9727245afdd86fe042950bcaaae5b0ec7762fd2ef6659cd6f01f033303621542

which results in:

* Server certificate:
*  subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
*  start date: Apr 17 17:37:51 2019 GMT
*  expire date: May 16 17:37:51 2021 GMT
*  subjectAltName: host "api.sandbox.push.apple.com" matched cert's "api.sandbox.push.apple.com"
*  issuer: CN=Apple IST CA 2 - G1; OU=Certification Authority; O=Apple Inc.; C=US
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55ad3c2ec460)
> POST /3/device/9727245afdd86fe042950bcaaae5b0ec7762fd2ef6659cd6f01f033303621542 HTTP/2
> Host: api.sandbox.push.apple.com
> User-Agent: curl/7.66.0
> Accept: */*
> apns-push-type: voip
> apns-expiration: 0
> apns-priority: 0
> apns-topic: my_valid_identifier.voip
> Content-Length: 94
> Content-Type: application/x-www-form-urlencoded
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!
* We are completely uploaded and fine
< HTTP/2 400 
< apns-id: B7168B2F-0353-68ED-76C2-0B26B0E8D90B
< 
* Connection #0 to host api.sandbox.push.apple.com left intact
{"reason":"DeviceTokenNotForTopic"}

Now that is the correct device id for my test iPhone 8 as I ran the example previously before changing the identifier. What have I missed? The cert was created against the correct identifier on https://developer.apple.com/account/resources/certificates/add

Thanks.

Is this package must have node js serve to use?

I'm using firebase messaging and agora engine package for push notification and call.
unfortunately, that packages not support on background mode.
yours package can help me voip push but haven't a node js serve.
currently I just use laravel serve for my backend.


have a nice day !
Thank for your effort to builded this package

Unexpectedly found nil while unwrapping an Optional value

I'm getting this error whn try Incomming call.
testIncomingcall function

voIPKit.testIncomingCall(
                  uuid: '12345',
                  callerId: dummyCallId,
                  callerName: dummyCallerName,
                );

App getting terminate and producing this error

2021-03-02 01:58:29.498665+0600 Runner[873:430465] flutter: 🎈 testIncomingCall: 12345, 123456, Dummy Tester
Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/johnsmith/Developer/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_ios_voip_kit-0.0.5/ios/Classes/CallKitCenter.swift, line 80
2021-03-02 01:58:29.503963+0600 Runner[873:430368] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/johnsmith/Developer/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_ios_voip_kit-0.0.5/ios/Classes/CallKitCenter.swift, line 80
(lldb) 

Please let me know the solution

What is the correct way to send VoIP Push using Node (Firebase Cloud Function)

i'm using the @parse/node-apn npm package in my firebase cloud function to request for a push.

i seem to be getting 'notifs sent: 0 failed: 1' when printing results.sent and results.failed.
i'm pretty sure that the VoIP Token being used is the one produced by the voip_kit instance (i checked logs).
please can someone confirm whether I'm calling the APNs properly? any idea where the problem could be?

const options = {
    token: {                                    //  hidden for privacy
        key: __dirname + "/../AuthKey_SECRET_KEYID.p8",
        keyId: "SECRET_KEYID",
        teamId: "SECRET_TEAMID",
    },
    production: true,
};
const apnProvider = new apn.Provider(options);

export const apncallpush = functions.https.onRequest(async (req, res) => {
    const callerid = req.body.callerid;
    const callername = req.body.callername;
    const callertoken = req.body.calleetoken;

    const note = new apn.Notification();
    const deviceToken = `${callertoken}`
    note.payload = {
        "aps": {
            "alert": {
                "uuid": `f579cc8c-7127-4ca3-a9f5-dd4a591a2567`,
                "incoming_caller_id": `${callerid}`,
                "incoming_caller_name": `${callername}`,
            },
        },
    };
    note.contentAvailable = true;
    note.expiry = Math.floor(Date.now() / 1000) + 60;
    note.priority = 10;
    note.pushType = "voip";
    note.topic = "BUNDLE_ID.voip";    //  hidden for privacy

    apnProvider.send(note, deviceToken).then((result) => {
        const r = `DONE! notifs sent: ${result.sent.length} failed: ${result.failed.length}`;
        console.log(r);
    }).catch(() => {
        console.log('NOPE notif not sent');
    });

and i only have 1 iOS device not 2, so sadly i cant try out the example app.
i also tried the CURL command mentioned in the doc. it connects to api.sandbox.apple and my .pem certificate verifies OK.
finally it outputs:

* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!
* We are completely uploaded and fine
< HTTP/2 200 
< apns-id: A2ED1505-EE9D-CD19-955B-84669C7322A2
< 
* Connection #0 to host api.sandbox.push.apple.com left intact
* Closing connection 0

Facing issues in iOS 14.0.1

  • Voip Alerts received when app is in the background or foreground but Event Handlers onDidAcceptIncomingCall, onDidRejectIncomingCall not called when we accept or reject the call.

  • Voip Alert not received when app is terminated. Also app is crashing after that.

When App is Terminated Flutter Callback Events are not working.

Whenever app is in terminated state and I hit Voip notification, it successfully hits on my device and shows calling screen. But on accepting call it doesnt hit callback events onDidReceiveIncomingPush and onDidAcceptIncomingCall. Can you please help?

Voip Token, Device Token, Nodejs Server

first, thanks for this amazing package

have been studying this package for over two days now, and I found some interesting challenges I can't seem to wrap my head around,

  1. How can I get a Device token?

2)Is the Device token unique to the user or to the app?

  1. Is Device Token the same as VoIP Token? and How do I get VoIP Token?

  2. I have seen some code snippets of how the Nodejs server sends a request to APNs but none show how to connect the flutter app to Nodejs. Please how do use this package along with my app make a connection to the Nodejs server

What have done so far

  1. Have downloaded the Voip Certificate, have added it to the keychain
  2. have exported it into the .p12 format
  3. Have generated the .pem file from the .p12 format
  4. Have downloaded the key .p8 file from my apple developer account
  5. I have the key id
  6. I have my team id

Please your insight, article, or video will really be helpful

Please separate self.callKitCenter.incomingCall function into a separate one?

Could you please separate this function into a separate one? So it is possible to customize the incoming screen when the foreground and backgroud should be displayed.

File: flutter_ios_voip_kit/ios/Classes/VoIPCenter.swift

Line 85 and line 106:

self.callKitCenter.incomingCall(uuidString: info?["uuid"] as! String,
callerId: info?["incoming_caller_id"] as! String,
callerName: callerName).

Currently, i cannot disable default incoming of CallKit when app run at foreground.

z2092876646901_7fb83aa8c32e4e734066f27601e9aa32

onTokenRefresh?

Is there something like this like in Firebase Cloud Messaging?

Play sound

Hi!

I use your plugin to integrate it with Agora. But the problem is when device is locked - I answer and ant to play audio message that will help users to understand that they need to tap voip button or video call to get to app.
I tried audio_service for playing sound in background. It works as expected, but after it - all voip event handlers (on Accept etc stop working) Seems there is conflict with isolate or receive port.

Can you help, please

Foreground accept call

Hi!

When my app is in foreground I show custom calling view, and receiving void push notification.
So, user can answer via push or directly via app.

  1. Is there way not to show push notification when app is in foreground?
  2. if no - if I answer via my app - how to hide push calling notification?(without calling endCall()? I tried acceptIncomingCall() with no luck(

Calling type

How I can set call type like incoming call is audio/video

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.