flutter_callkit_incoming 1.0.2+1 icon indicating copy to clipboard operation
flutter_callkit_incoming: ^1.0.2+1 copied to clipboard

Flutter Callkit Incoming to show callkit screen in your Flutter app.

Flutter Callkit Incoming #

A Flutter plugin to show incoming call in your Flutter app(Custom for Android/Callkit for iOS).

pub package Build Status

Buy Me A Coffee

⭐ Features #

  • Show an incoming call

  • Start an outgoing call

  • Custom UI Android/Callkit for iOS

  • Example using Pushkit/VoIP for iOS


iOS: ONLY WORKING ON REAL DEVICE, not on simulator(Callkit framework not working on simulator) #


🚀  Installation #

  1. Install Packages
  • Run this command:
    flutter pub add flutter_callkit_incoming
    
  • Add pubspec.yaml:
        dependencies:
          flutter_callkit_incoming: any
    
  1. Configure Project
  • Android
    • AndroidManifest.xml
      <manifest...>
          ...
          <!-- 
              Using for load image from internet
          -->
          <uses-permission android:name="android.permission.INTERNET"/>
      </manifest>
    
  • iOS
    • Info.plist
      <key>UIBackgroundModes</key>
      <array>
          <string>processing</string>
          <string>remote-notification</string>
          <string>voip</string>
      </array>
    
  1. Usage
  • Import

    import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
    
  • Received an incoming call

      this._currentUuid = _uuid.v4();
      var params = <String, dynamic>{
        'id': _currentUuid,
        'nameCaller': 'Hien Nguyen',
        'appName': 'Callkit',
        'avatar': 'https://i.pravatar.cc/100',
        'handle': '0123456789',
        'type': 0,
        'textAccept': 'Accept',
        'textDecline': 'Decline',
        'textMissedCall': 'Missed call',
        'textCallback': 'Call back',
        'duration': 30000,
        'extra': <String, dynamic>{'userId': '1a2b3c4d'},
        'headers': <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
        'android': <String, dynamic>{
          'isCustomNotification': true,
          'isShowLogo': false,
          'isShowCallback': false,
          'isShowMissedCallNotification': true,
          'ringtonePath': 'system_ringtone_default',
          'backgroundColor': '#0955fa',
          'backgroundUrl': 'https://i.pravatar.cc/500',
          'actionColor': '#4CAF50'
        },
        'ios': <String, dynamic>{
          'iconName': 'CallKitLogo',
          'handleType': 'generic',
          'supportsVideo': true,
          'maximumCallGroups': 2,
          'maximumCallsPerCallGroup': 1,
          'audioSessionMode': 'default',
          'audioSessionActive': true,
          'audioSessionPreferredSampleRate': 44100.0,
          'audioSessionPreferredIOBufferDuration': 0.005,
          'supportsDTMF': true,
          'supportsHolding': true,
          'supportsGrouping': false,
          'supportsUngrouping': false,
          'ringtonePath': 'system_ringtone_default'
        }
      };
      await FlutterCallkitIncoming.showCallkitIncoming(params);
    
  • Show miss call notification

      this._currentUuid = _uuid.v4();
      var params = <String, dynamic>{
        'id': this._currentUuid,
        'nameCaller': 'Hien Nguyen',
        'handle': '0123456789',
        'type': 1,
        'textMissedCall': 'Missed call',
        'textCallback': 'Call back',
        'extra': <String, dynamic>{'userId': '1a2b3c4d'},
      };
      await FlutterCallkitIncoming.showMissCallNotification(params);
    
  • Started an outgoing call

      this._currentUuid = _uuid.v4();
      var params = <String, dynamic>{
        'id': this._currentUuid,
        'nameCaller': 'Hien Nguyen',
        'handle': '0123456789',
        'type': 1,
        'extra': <String, dynamic>{'userId': '1a2b3c4d'},
        'ios': <String, dynamic>{'handleType': 'generic'}
      };
      await FlutterCallkitIncoming.startCall(params);
    
  • Ended an incoming/outgoing call

      var params = <String, dynamic>{'id': this._currentUuid};
      await FlutterCallkitIncoming.endCall(params);
    
  • Ended all calls

      await FlutterCallkitIncoming.endAllCalls();
    
  • Get active calls. iOS: return active calls from Callkit, Android: only return last call

      await FlutterCallkitIncoming.activeCalls();
    

    Output

    [{"id": "8BAA2B26-47AD-42C1-9197-1D75F662DF78", ...}]
    
  • Get device push token VoIP. iOS: return deviceToken, Android: Empty

      await FlutterCallkitIncoming.getDevicePushTokenVoIP();
    

    Output

    <device token>
    
    //Example
    d6a77ca80c5f09f87f353cdd328ec8d7d34e92eb108d046c91906f27f54949cd
    
    

    Make sure using SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken) inside AppDelegate.swift (Example)

    func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
        print(credentials.token)
        let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
        //Save deviceToken to your server
        SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken)
    }
    
    func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
        print("didInvalidatePushTokenFor")
        SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("")
    }
    
  • Listen events

      FlutterCallkitIncoming.onEvent.listen((event) {
        switch (event!.name) {
          case CallEvent.ACTION_CALL_INCOMING:
            // TODO: received an incoming call
            break;
          case CallEvent.ACTION_CALL_START:
            // TODO: started an outgoing call
            // TODO: show screen calling in Flutter
            break;
          case CallEvent.ACTION_CALL_ACCEPT:
            // TODO: accepted an incoming call
            // TODO: show screen calling in Flutter
            break;
          case CallEvent.ACTION_CALL_DECLINE:
            // TODO: declined an incoming call
            break;
          case CallEvent.ACTION_CALL_ENDED:
            // TODO: ended an incoming/outgoing call
            break;
          case CallEvent.ACTION_CALL_TIMEOUT:
            // TODO: missed an incoming call
            break;
          case CallEvent.ACTION_CALL_CALLBACK:
            // TODO: only Android - click action `Call back` from missed call notification
            break;
          case CallEvent.ACTION_CALL_TOGGLE_HOLD:
            // TODO: only iOS
            break;
          case CallEvent.ACTION_CALL_TOGGLE_MUTE:
            // TODO: only iOS
            break;
          case CallEvent.ACTION_CALL_TOGGLE_DMTF:
            // TODO: only iOS
            break;
          case CallEvent.ACTION_CALL_TOGGLE_GROUP:
            // TODO: only iOS
            break;
          case CallEvent.ACTION_CALL_TOGGLE_AUDIO_SESSION:
            // TODO: only iOS
            break;
          case CallEvent.ACTION_DID_UPDATE_DEVICE_PUSH_TOKEN_VOIP:
            // TODO: only iOS
            break;
        }
      });
    
  • Call from Native (iOS PushKit)

      //Swift
      var info = [String: Any?]()
      info["id"] = "44d915e1-5ff4-4bed-bf13-c423048ec97a"
      info["nameCaller"] = "Hien Nguyen"
      info["handle"] = "0123456789"
      info["type"] = 1
      //... set more data
      SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(flutter_callkit_incoming.Data(args: info), fromPushKit: true)
    

      //OR
      let data = flutter_callkit_incoming.Data(id: "44d915e1-5ff4-4bed-bf13-c423048ec97a", nameCaller: "Hien Nguyen", handle: "0123456789", type: 0)
      data.nameCaller = "Johnny"
      data.extra = ["user": "abc@123", "platform": "ios"]
      //... set more data
      SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data, fromPushKit: true)
    

      //Objective-C
      #if __has_include(<flutter_callkit_incoming/flutter_callkit_incoming-Swift.h>)
      #import <flutter_callkit_incoming/flutter_callkit_incoming-Swift.h>
      #else
      #import "flutter_callkit_incoming-Swift.h"
      #endif
    
      Data * data = [[Data alloc]initWithId:@"44d915e1-5ff4-4bed-bf13-c423048ec97a" nameCaller:@"Hien Nguyen" handle:@"0123456789" type:1];
      [data setNameCaller:@"Johnny"];
      [data setExtra:@{ @"userId" : @"HelloXXXX", @"key2" : @"value2"}];
      //... set more data
      [SwiftFlutterCallkitIncomingPlugin.sharedInstance showCallkitIncoming:data fromPushKit:YES];
    

      //send custom event from native
      SwiftFlutterCallkitIncomingPlugin.sharedInstance?.sendEventCustom("customEvent", body: ["customKey": "customValue"])
    
    
  1. Properties

    PropDescriptionDefault
    idUUID identifier for each call. UUID should be unique for every call and when the call is ended, the same UUID for that call to be used. suggest using uuidRequired
    nameCallerCaller's name.None
    appNameApp's name. using for display inside Callkit(iOS).App Name, Deprecated for iOS > 14, default using App name
    avatarAvatar's URL used for display for Android. /android/src/main/res/drawable-xxxhdpi/ic_default_avatar.pngNone
    handlePhone number/Email/Any.None
    type0 - Audio Call, 1 - Video Call0
    durationIncoming call/Outgoing call display time (second). If the time is over, the call will be missed.30000
    textAcceptText Accept used in AndroidAccept
    textDeclineText Decline used in AndroidDecline
    textMissedCallText Missed Call used in Android (show in miss call notification)Missed Call
    textCallbackText Call back used in Android (show in miss call notification)Call back
    extraAny data added to the event when received.{}
    headersAny data for custom header avatar/background image.{}
    androidAndroid data needed to customize UI.Below
    iosiOS data needed.Below

  • Android

    PropDescriptionDefault
    isCustomNotificationUsing custom notifications.false
    isShowLogoShow logo app inside full screen. /android/src/main/res/drawable-xxxhdpi/ic_logo.pngfalse
    isShowMissedCallNotificationShow missed call notification when timeouttrue
    isShowCallbackShow callback action from miss call notification.true
    ringtonePathFile name ringtone. put file into /android/app/src/main/res/raw/ringtone_default.pm3system_ringtone_default
    using ringtone default of the phone
    backgroundColorIncoming call screen background color.#0955fa
    backgroundUrlUsing image background for Incoming call screen.None
    actionColorColor used in button/text on notification.#4CAF50

  • iOS

    PropDescriptionDefault
    iconNameApp's Icon. using for display inside Callkit(iOS)CallKitLogo
    using from Images.xcassets/CallKitLogo
    handleTypeType handle call generic, number, emailgeneric
    supportsVideotrue
    maximumCallGroups2
    maximumCallsPerCallGroup1
    audioSessionModeNone, gameChat, measurement, moviePlayback, spokenAudio, videoChat, videoRecording, voiceChat, voicePrompt
    audioSessionActivetrue
    audioSessionPreferredSampleRate44100.0
    audioSessionPreferredIOBufferDuration0.005
    supportsDTMFtrue
    supportsHoldingtrue
    supportsGroupingtrue
    supportsUngroupingtrue
    ringtonePathAdd file to root project xcode /ios/Runner/Ringtone.caf and Copy Bundle Resources(Build Phases)Ringtone.caf
    system_ringtone_default
    using ringtone default of the phone
  1. Source code

     please checkout repo github
     https://github.com/hiennguyen92/flutter_callkit_incoming
    

  1. Pushkit - Received VoIP and Wake app from Terminated State (only for IOS)

  1. Todo

💡 Demo #

  1. Demo Illustration:
  2. Image
iOS(Lockscreen) iOS(full screen) iOS(Alert)
Android(Lockscreen) - Audio Android(Alert) - Audio Android(Lockscreen) - Video
Android(Alert) - Video isCustomNotification: false
60
likes
130
pub points
92%
popularity

Publisher

verified publisher iconhiennv.com

Flutter Callkit Incoming to show callkit screen in your Flutter app.

Repository (GitHub)
View/report issues

Documentation

API reference

License

Icon for licenses.MIT (LICENSE)

Dependencies

flutter

More

Packages that depend on flutter_callkit_incoming