Usage
Address Book allows cross-platform contact access on mobile devices.
Essential Kit wraps the native iOS Contacts framework and Android Contacts Provider into a single Unity API. The first call to AddressBook.ReadContacts automatically handles permissions, so you can focus on delivering contact-driven gameplay loops.
Table of Contents
Permission Workflow
Call AddressBook.ReadContacts directly. Essential Kit requests permission automatically on the first call and returns an error when the player denies access.
using UnityEngine;
using VoxelBusters.CoreLibrary;
using VoxelBusters.EssentialKit;
public class ContactsLoader : MonoBehaviour
{
private void Start()
{
var options = new ReadContactsOptions.Builder()
.WithLimit(25) // Show a small preview list
.WithConstraints(ReadContactsConstraint.MustIncludeName)
.Build();
AddressBook.ReadContacts(options, OnContactsRead);
}
private void OnContactsRead(AddressBookReadContactsResult result, Error error)
{
if (error != null)
{
if (error.Code == (int)AddressBookErrorCode.PermissionDenied)
{
// Let players know why contacts matter, then
Utilities.OpenApplicationSettings();
}
return;
}
foreach (var contact in result.Contacts)
{
Debug.Log($"Contact: {contact.FirstName} {contact.LastName}");
}
}
}Show your own rationale screen before the first read call. Apps that explain the benefit of sharing contacts see higher opt-in rates and fewer support tickets.
Optional: Check Permission Status
Use AddressBook.GetContactsAccessStatus() only when you need to customize UI copy before launching the native prompt or to detect the Limited state on iOS 14+.
var status = AddressBook.GetContactsAccessStatus();
switch (status)
{
case AddressBookContactsAccessStatus.Authorized:
case AddressBookContactsAccessStatus.Limited:
// Show friends list immediately
break;
case AddressBookContactsAccessStatus.NotDetermined:
// Encourage user to continue so ReadContacts can request access
break;
case AddressBookContactsAccessStatus.Denied:
case AddressBookContactsAccessStatus.Restricted:
// Show recovery UI + OpenApplicationSettings button
break;
}Avoid blocking on GetContactsAccessStatus() before every read. The main operation already covers permission prompts and keeps platform behaviour consistent.
Reading Contacts
ReadContactsOptions lets you control page size and skip counts. Set Limit to a reasonable number (25–100) for scrolling lists and Offset to zero for the first batch.
int _nextOffset = 0;
void LoadInitialContacts()
{
var options = new ReadContactsOptions.Builder()
.WithLimit(50)
.WithOffset(_nextOffset)
.Build();
AddressBook.ReadContacts(options, OnContactsRead);
}
void OnContactsRead(AddressBookReadContactsResult result, Error error)
{
if (error != null)
{
Debug.LogError($"Contacts read failed: {error.Description}");
return;
}
Debug.Log($"Loaded {result.Contacts?.Length ?? 0} contacts.");
_nextOffset = result.NextOffset;
}Filtering and Constraints
Combine constraints to filter out incomplete entries (e.g., require both a name and phone number before showing an invite button).
var inviteOptions = new ReadContactsOptions.Builder()
.WithLimit(100)
.WithConstraints(ReadContactsConstraint.MustIncludeName | ReadContactsConstraint.MustIncludePhoneNumber)
.Build();ReadContactsConstraint.None
Return every contact (default)
ReadContactsConstraint.MustIncludeName
Skip entries with no first/last name
ReadContactsConstraint.MustIncludePhoneNumber
Only contacts with at least one phone number
ReadContactsConstraint.MustIncludeEmail
Only contacts with at least one email address
Combining all three constraints (Name + Phone + Email) often yields fewer contacts than expected. Start broad and tighten filters based on telemetry.
Paginated Reads (Advanced)
Use the NextOffset returned in each result to load more contacts as players scroll. Essential Kit returns -1 when you've reached the end.
int _nextOffset = 0;
bool _isLoading;
public void LoadMoreIfNeeded()
{
if (_isLoading || _nextOffset < 0)
return;
_isLoading = true;
var options = new ReadContactsOptions.Builder()
.WithLimit(25)
.WithOffset(_nextOffset)
.Build();
AddressBook.ReadContacts(options, (result, error) =>
{
_isLoading = false;
if (error == null)
{
Debug.Log($"Appended {result.Contacts?.Length ?? 0} contacts.");
_nextOffset = result.NextOffset; // -1 means done
}
});
}Contact Data Properties
FirstName, MiddleName, LastName
string
Empty when a contact only has a company name
CompanyName
string
Useful for B2B apps or support forms
PhoneNumbers
string[]
Iterate and display type labels in your own UI
EmailAddresses
string[]
Often empty on phone-focused contacts
LoadImage(callback)
EventCallback<TextureData>
Async load; returns placeholder texture when the contact lacks a photo
Loading Contact Images
LoadImage is async and safe to call on the main thread. Provide a default sprite while the callback resolves.
void ShowAvatar(IAddressBookContact contact, RawImage target)
{
target.texture = _placeholder;
contact.LoadImage((textureData, error) =>
{
if (error == null && textureData.Texture != null)
{
target.texture = textureData.Texture;
}
});
}Cache textures per contact ID in memory to avoid reloading images every time a scroll view recycles a cell.
Core APIs Reference
AddressBook.ReadContacts(options, callback)
Requests permission if needed, then returns contacts
AddressBookReadContactsResult via callback
ReadContactsOptions.Builder()
Configure pagination and constraints
Chain .WithLimit(), .WithOffset(), .WithConstraints()
AddressBook.GetContactsAccessStatus()
Optional: inspect current permission state
AddressBookContactsAccessStatus enum
IAddressBookContact.LoadImage(callback)
Load a contact's profile picture asynchronously
TextureData with texture or placeholder
Error Handling
AddressBookErrorCode.PermissionDenied
Player denied or restricted contacts access
Show rationale, direct to Utilities.OpenApplicationSettings()
AddressBookErrorCode.Unknown
Platform returned an unexpected failure
Retry, log for diagnostics, or fall back to manual friend codes
Related Guides
Demo scene:
Assets/Plugins/VoxelBusters/EssentialKit/Examples/Scenes/AddressBookDemo.unityPair with Sharing Services to pre-fill SMS or email invites using selected contacts
Ready to validate your flow? Head to the Testing guide next
Last updated
Was this helpful?