Skip to main content
When a call arrives, showCallkitIncoming presents the native call UI. On iOS this uses Apple’s CallKit framework — the same full-screen lock-screen experience built into the Phone app. On Android a custom full-screen notification is used because there is no system CallKit equivalent.
iOS CallKit only works on a real device. The simulator does not support the CallKit framework.

Show the incoming call screen

1

Generate a UUID for the call

Every call must have a unique UUID. Use the uuid package to generate one and keep it for the lifetime of the call.
import 'package:uuid/uuid.dart';

final _uuid = const Uuid();
String _currentUuid = _uuid.v4();
2

Build CallKitParams and call showCallkitIncoming

Pass a fully configured CallKitParams object. The example below enables all customisation options on both platforms.
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';

CallKitParams callKitParams = CallKitParams(
  id: _currentUuid,            // must be a UUID
  nameCaller: 'Hien Nguyen',
  appName: 'Callkit',
  avatar: 'https://i.pravatar.cc/100',
  handle: '0123456789',
  type: 0,                     // 0 = audio, 1 = video
  textAccept: 'Accept',
  textDecline: 'Decline',
  missedCallNotification: NotificationParams(
    showNotification: true,
    isShowCallback: true,
    subtitle: 'Missed call',
    callbackText: 'Call back',
  ),
  callingNotification: const NotificationParams(
    showNotification: true,
    isShowCallback: true,
    subtitle: 'Calling...',
    callbackText: 'Hang Up',
  ),
  duration: 30000,             // milliseconds before call times out
  extra: <String, dynamic>{'userId': '1a2b3c4d'},
  headers: <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
  android: const AndroidParams(
    isCustomNotification: true,
    isShowLogo: false,
    logoUrl: 'https://i.pravatar.cc/100',
    ringtonePath: 'system_ringtone_default',
    backgroundColor: '#0955fa',
    backgroundUrl: 'https://i.pravatar.cc/500',
    actionColor: '#4CAF50',
    textColor: '#ffffff',
    incomingCallNotificationChannelName: 'Incoming Call',
    missedCallNotificationChannelName: 'Missed Call',
    isShowCallID: false,
  ),
  ios: IOSParams(
    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(callKitParams);

Key parameters

ParameterTypeDescription
idStringRequired. Must be a UUID. Use the same UUID for all subsequent operations on this call (end, mute, hold, etc.).
nameCallerStringCaller name displayed on the incoming call screen.
handleStringPhone number, email address, or any identifier for the caller.
typeint0 for audio call, 1 for video call. Defaults to 0.
durationintMilliseconds to display the incoming call UI. When the timer expires the call is marked as missed. Defaults to 30000.
avatarStringURL of the caller’s avatar image (Android only).
extraMapArbitrary data passed through to every call event on this call.

Hide the call notification (Android)

After the user accepts or declines a call on Android, dismiss the incoming call notification by calling hideCallkitIncoming.
CallKitParams params = CallKitParams(
  id: _currentUuid,
);
await FlutterCallkitIncoming.hideCallkitIncoming(params);
This method is Android-only. On iOS CallKit manages its own UI lifecycle.

Mark the call as connected

Call setCallConnected once your WebRTC or P2P session is fully established. On iOS this resets the call timer in the Phone app history; on Android it fires a callback event.
await FlutterCallkitIncoming.setCallConnected(_currentUuid);
Call setCallConnected after accepting the call and after the WebRTC/P2P connection is established — not immediately on accept.

Get active calls

Use activeCalls to check for ongoing calls, for example when the app is launched from a terminated state.
var calls = await FlutterCallkitIncoming.activeCalls();
// Returns: [{"id": "8BAA2B26-47AD-42C1-9197-1D75F662DF78", ...}]
On iOS activeCalls returns the active calls from CallKit (id only). On Android it returns only the last call.

Firebase background message handler

If you are triggering showCallkitIncoming from a Firebase Cloud Messaging background handler, annotate the handler with @pragma('vm:entry-point') so the Dart VM does not tree-shake it.
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  final uuid = const Uuid().v4();
  await FlutterCallkitIncoming.showCallkitIncoming(CallKitParams(
    id: uuid,
    nameCaller: message.data['nameCaller'] ?? '',
    handle: message.data['handle'] ?? '',
    type: int.tryParse(message.data['type'] ?? '0') ?? 0,
  ));
}

Call events

Listen to accept, decline, timeout, and other lifecycle events.

Notifications

Configure missed call and calling notifications.

Build docs developers (and LLMs) love