Contact Store | Getting Started
A cross-platform library for accessing device contacts on Android and iOS. Provides full CRUD operations, a fluent async query builder, Shiny’s AccessState permission model, and dependency injection integration. Built on Shiny.Core, so it runs in any Shiny host — with or without .NET MAUI.
| GitHub | |
| Downloads |
Features
Section titled “Features”- Full CRUD — create, read, update, and delete device contacts
- Fluent async queries —
Query()returns aContactQuerybuilder (Where/Search/OrderBy/Skip/Take→ToListAsync(ct)) with native translation on both platforms - Shiny permissions —
GetCurrentAccess()andRequestAccess()using Shiny.Core’sAccessStatemodel - No MAUI required — built on
Shiny.Core, so it works in any Shiny host - AOT compatible — trimmer and AOT safe
- Dependency injection — register with a single
AddContactStore()call
Platforms
Section titled “Platforms”| Platform | Minimum Version |
|---|---|
| Android | API 24 |
| iOS | 15.0 |
- MyApp/
1<?xml version="1.0" encoding="utf-8"?>2<manifest xmlns:android="http://schemas.android.com/apk/res/android">3 <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">4 </application>5 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>6 <uses-permission android:name="android.permission.BATTERY_STATS" />7 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />8 <uses-permission android:name="android.permission.INTERNET" />9 <uses-permission android:name="android.permission.READ_CONTACTS" />10 <uses-permission android:name="android.permission.WRITE_CONTACTS" />11</manifest>Quick Example
Section titled “Quick Example”// Request access (triggers OS prompt if needed)var access = await contactStore.RequestAccess();if (access != AccessState.Available) return;
// Get all contactsvar contacts = await contactStore.GetAll();
// Query with the fluent buildervar results = await contactStore.Query() .Where(ContactField.GivenName, "John") .OrderBy(ContactSortField.FamilyName) .ToListAsync();
// Create a contactvar contact = new Contact { GivenName = "John", FamilyName = "Doe" };contact.Phones.Add(new ContactPhone("555-1234", PhoneType.Mobile));string id = await contactStore.Create(contact);
// Updatecontact.GivenName = "Jane";await contactStore.Update(contact);
// Deleteawait contactStore.Delete(id);Photos vs Thumbnails
Section titled “Photos vs Thumbnails”Bulk reads — GetAll() and Query() — populate only the lightweight Thumbnail. The full-resolution Photo is null on these results: decoding every contact’s full image into memory at once spikes memory and can get the app OOM/jetsam-killed on a real device with many photo contacts. Fetch a single contact with GetById(id) to get the full Photo (it also includes the Thumbnail).
Bind list rows to Thumbnail, and load Photo on a per-contact detail screen.
AI Coding Assistant
Section titled “AI Coding Assistant”Step 1 — Add the marketplace:
claude plugin marketplace add shinyorg/skillsStep 2 — Install the plugin:
claude plugin install shiny-maui@shinyStep 1 — Add the marketplace:
copilot plugin marketplace add https://github.com/shinyorg/skillsStep 2 — Install the plugin:
copilot plugin install shiny-maui@shinyNext Steps
Section titled “Next Steps”- Permissions — Shiny
AccessStatepermission handling - Querying — the fluent query builder and what translates natively
- Release Notes — Version history


