dartpub.dev
plugins / contacts_kit
co

contacts_kit

v0.1.0 MIT

Contacts for DartNative, the flutter_contacts way.

The complete flutter_contacts API on DartNative: read, create, update and delete contacts with every field, permissions, groups and accounts, the native picker, viewer, editor and creator, change listeners, vCard import and export, plus the Android-only SIM, blocked-number and ringtone APIs. Same Dart surface as flutter_contacts 2.6.0, running on the Contacts framework and ContactsContract over FFI with no platform channels.

by edkluivert/contacts_kit · updated 1 week ago
Install
Free
pubspec.yaml
dependencies:
  contacts_kit:
    hosted: https://dartpub.dev
    version: ^0.1.0
Weekly installs
0
Active apps
2
Rating
0.0 · 0
Open issues
0

contacts_kit

flutter_contacts for DartNative: the same FlutterContacts API, models and vCard support, with the Flutter platform channels replaced by an FFI channel into the same Swift and Kotlin handlers.

import 'package:contacts_kit/contacts_kit.dart';

final status = await FlutterContacts.permissions.request(PermissionType.read);
final contacts = await FlutterContacts.getAll(
  properties: {ContactProperty.name, ContactProperty.phone},
);
final picked = await FlutterContacts.native.showPicker(
  properties: {ContactProperty.phone, ContactProperty.email},
);

The API is flutter_contacts 2.6.0's, unchanged: see its documentation for every call. PlatformException is this package's own class with the same fields.

Setup

dependencies:
  contacts_kit: ^0.1.0

Run dn pub get; it adds ContactsKitFFIBindings.loadSymbols() to the app's plugin registrant.

  • iOS: NSContactsUsageDescription in ios/Runner/Info.plist.
  • Android: READ_CONTACTS and/or WRITE_CONTACTS in the app manifest. The picker itself needs neither; reading the picked contact's fields does.

How the port works

Layer What changed
Dart lib/api, lib/models, lib/src/vcard are the originals. Their one Flutter import now points at lib/src/channel/services.dart, a MethodChannel / EventChannel / PlatformException with the same shapes over FfiChannel (JSON strings, one dispatcher pointer, tokens).
iOS ios/Classes are the original Swift handlers minus import Flutter. FlutterShim.swift defines FlutterMethodCall, FlutterResult, FlutterError, FlutterMethodNotImplemented, FlutterEventSink, FlutterStreamHandler. ContactsKit.swift holds the @_cdecl entry points, the dispatcher slot and the "domain.method" router.
Android android/.../co/quis/flutter_contacts are the original Kotlin handlers. com.kluivert.contactskit.shim holds MethodCall, MethodChannel.Result, EventChannel, PluginRegistry and ActivityPluginBinding copies (the engine's own classes exist at runtime and must not be shadowed). ContactsKitBridge.kt routes calls, ContactsKitProxyActivity owns the picker/editor/creator results and the permission dialog, because the DartNative embedding has no activity-result hooks. The five call sites that started an activity for a result now go through the proxy.

Replies travel as JSON, so a contact photo is a base64 string on the wire, exactly as flutter_contacts already encodes it.

Deviations from flutter_contacts

  • ViewControllerUtils.rootViewController() returns the top-most presented controller, so the picker opens above a DartNative sheet.
  • On Android the four activity-for-result calls and the permission request go through ContactsKitProxyActivity; the ported handlers no longer require a host activity.

Verified

  • Both platforms: permissions.request, getAll, create → get → delete, vCard export/import (the example's autorun).
  • iOS: native.showPicker from inside a DartNative sheet, result filled into a field (Kept).
  • Android: native.showPicker round trip through the proxy activity.

Not verified yet

The viewer, editor and creator, the change listeners, groups, accounts, SIM, blocked numbers and ringtones are ported as-is and untested.

Example

example/ is a dn create app. dn run --dart-define=CONTACTS_KIT_AUTORUN=true runs permission → getAll → create/get/delete → vCard at startup and mirrors the results into the dn run log as [example] lines.