{"id":4585,"url":"https://github.com/joshuapinter/react-native-unified-contacts","last_synced_at":"2025-04-06T13:11:00.930Z","repository":{"id":57341125,"uuid":"54616323","full_name":"joshuapinter/react-native-unified-contacts","owner":"joshuapinter","description":"Your best friend when working with the latest and greatest Contacts Framework in iOS 9+ in React Native.","archived":false,"fork":false,"pushed_at":"2022-11-27T20:32:10.000Z","size":18129,"stargazers_count":158,"open_issues_count":23,"forks_count":57,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-30T08:09:37.327Z","etag":null,"topics":["android","apple","contacts","phone-number","privacy-settings","react","react-native","unified","xcode"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joshuapinter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-24T05:13:01.000Z","updated_at":"2024-08-12T19:22:02.000Z","dependencies_parsed_at":"2023-01-24T06:45:08.802Z","dependency_job_id":null,"html_url":"https://github.com/joshuapinter/react-native-unified-contacts","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuapinter%2Freact-native-unified-contacts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuapinter%2Freact-native-unified-contacts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuapinter%2Freact-native-unified-contacts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuapinter%2Freact-native-unified-contacts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshuapinter","download_url":"https://codeload.github.com/joshuapinter/react-native-unified-contacts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247485287,"owners_count":20946398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","apple","contacts","phone-number","privacy-settings","react","react-native","unified","xcode"],"created_at":"2024-01-05T20:17:17.114Z","updated_at":"2025-04-06T13:11:00.908Z","avatar_url":"https://github.com/joshuapinter.png","language":"Java","funding_links":[],"categories":["Components","\u003ca name=\"OS-\u0026-System-\u0026-File-Manager:-Native-Modules\"\u003eOS, System \u0026 File Manager: Native Modules\u003c/a\u003e"],"sub_categories":["System"],"readme":"\u003cimg src=\"readme_assets/react-native-unified-contacts-logo.png\" width=\"667\" alt=\"React Native Unified Contacts Logo\"\u003e\n\n\u003c!-- # React Native Unified Contacts --\u003e\n[![npm version](https://badge.fury.io/js/react-native-unified-contacts.svg)](https://badge.fury.io/js/react-native-unified-contacts)\n\n**Your best friend when working with the latest and greatest [Contacts Framework][apple-contacts-framework] in iOS 9+ and combining that with Android 6 (SDK 23)+ support**\n\n# Platform Compatibility\n\n**Requires iOS 9+ and Swift 4 for iOS or Android M (6.0 / SDK 23)+ for Anrdoid**\n\n|                                                                                     | iOS | Android | Notes |\n|-------------------------------------------------------------------------------------|:---:|:-------:|:------|\n| [`getContact`](#get-a-single-contact)                                               | ✅  | 🚫      |       |\n| [`getContacts`](#get-all-contacts)                                                  | ✅  | ✅      |       |\n| [`searchContacts`](#search-all-contacts)                                            | ✅  | ✅      |       |\n| [`selectContact`](#select-a-single-contact)                                         | 🚫  | ✅      | Opens up native Contacts app and allows User to select a single Contact. |\n| [`openContact`](#open-a-single-contact)                                             | 🚫  | ✅      | Opens up a native card for a single Contact, allowing the User to contact them. |\n| [`addContact`](#add-a-single-contact)                                               | ✅  | 🚫      |       |\n| [`updateContact`](#update-a-single-contact)                                         | ✅  | 🚫      |       |\n| [`deleteContact`](#delete-a-single-contact)                                         | ✅  | 🚫      |       |\n| [`getGroup`](#get-a-single-group)                                                   | ✅  | 🚫      |       |\n| [`getGroups`](#get-all-groups)                                                      | ✅  | 🚫      |       |\n| [`contactsInGroup`](#get-contacts-in-group)                                         | ✅  | 🚫      |       |\n| [`addGroup`](#add-a-group)                                                          | ✅  | 🚫      |       |\n| [`updateGroup`](#update-a-group)                                                    | ✅  | 🚫      |       |\n| [`deleteGroup`](#delete-a-group)                                                    | ✅  | 🚫      |       |\n| [`addContactsToGroup`](#add-contacts-to-a-group)                                    | ✅  | 🚫      |       |\n| [`removeContactsFromGroup`](#remove-contacts-from-a-group)                          | ✅  | 🚫      |       |\n| [`userCanAccessContacts`](#can-the-user-access-contacts)                            | ✅  | ✅      |       |\n| [`requestAccessToContacts`](#request-access-to-contacts)                            | ✅  | ✅      |       |\n| [`alreadyRequestedAccessToContacts`](#check-if-already-requsted-access-to-contacts) | ✅  | ✅️      | Android lets you request permission after denying, but not if \"Don't ask again\" is checked.      |\n| [`openPrivacySettings`](#open-the-users-privacy-settings)                           | ✅  | ✅      |       |\n\nApple recently did a complete overhaul of their Contacts Framework that does a number of things, including:\n\n  1. Making it simpler to use the framework.\n\n  2. Use the same framework across all their platforms, including iOS, tvOS, watchOS and even OS X.\n\n  3. Get unified Contact details not only from a User's local Contact entry, but also from the user's social accounts, like Facebook and Twitter. This allows you to get a Facebook profile picture for a Contact you have in your contact database.\n\n\n# Installation\n\n  1. Install the npm package:\n   ```bash\n   npm install --save react-native-unified-contacts\n   ```\n   _This will install the latest react-native-unified-contacts package and add it to your package.json file._\n\n## Automatic Installation\n\n  2. Link the project:\n  ```bash\n  react-native link react-native-unified-contacts\n  ```\n\n## Manual Installation\n   _Manual installation is only required if automatic linking fails._\n\n### iOS\n\n  2. Navigate to `\u003cyour-project-directory\u003e/node_modules/react-native-unified-contacts/` and drag the `RNUnifiedContacts` directory into your project directory in Xcode.\n\n  3. Ensure that `Copy items if needed` is **not** checked\n\n  4. Select `Create groups` and ensure your project is selected for a target.\n\n  ![Select files](readme_assets/drag_and_drop_library_to_sidebar.gif)\n\n### Android\n\n  2. In `android/settings.gradle`:\n\n  ```gradle\n  ...\n  include ':react-native-unified-contacts'\n  project(':react-native-unified-contacts').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-unified-contacts/android')\n  ```\n\n  3. In `android/app/build.gradle`:\n\n  ```gradle\n  ...\n  dependencies {\n      ...\n      implementation project(':react-native-unified-contacts')\n  }\n  ```\n\n  4. Also in `android/app/build.gradle`:\n  _Set minSdkVersion to 23 (Android 6.0 or i.e. Android M)_\n\n  ```gradle\n  ...\n\n  android {\n    ...\n    defaultConfig {\n      ...\n      minSdkVersion 23\n      ...\n  ```\n\n  5. In `android/app/source/main/AndroidManifest.xml`:\n  ```xml\n  ...\n    \u003cuses-sdk\n      ...\n      android:minSdkVersion=\"23\"\n      ...\n    /\u003e\n    ...\n  ```\n\n  6. In in android/app/src/main/java/[your-app]/MainActivity.java:\n\n  ```java\n  import com.joshuapinter.RNUnifiedContacts.RNUnifiedContactsPackage; // \u003c------ Add this line\n\n  public class MainApplication extends Application implements ReactApplication {\n    ...\n    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {\n      @Override\n      public boolean getUseDeveloperSupport() {\n        return BuildConfig.DEBUG;\n      }\n      ...\n      @Override\n      protected List\u003cReactPackage\u003e getPackages() {\n        return Arrays.\u003cReactPackage\u003easList(\n          new MainReactPackage(),\n          ...\n          new RNUnifiedContactsPackage(),  // \u003c------ Add this line\n          ...\n        );\n      }\n      ...\n    }\n  ```\n\n# Post-Install Setup\n\n## Permissions iOS\n\n  For iOS 10+, you need to add a `NSContactsUsageDescription` key to your `Info.plist`, also called `Privacy - Contacts Usage Description` if entered through XCode's interface. This provides a reason why your app needs to access private information:\n\n    \u003ckey\u003eNSContactsUsageDescription\u003c/key\u003e\n    \u003cstring\u003entwrk accesses Contacts in order to quickly add Relationships and allow them to reach out via ntwrk through email, text, phone, etc.\u003c/string\u003e\n\n## Permissions Android\n\n  Add permissions to your `android/app/src/main/AndroidManifest.xml` file. Below are exampes. You may only need READ_CONTACTS. Only ask for the permissions your app needs.\n\n  ```xml\n  ...\n    \u003cuses-permission android:name=\"android.permission.READ_PROFILE\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.READ_CONTACTS\" /\u003e\n    \u003cuses-permission android:name=\"android.permission.WRITE_CONTACTS\" /\u003e\n  ...\n  ```\n\n\n# Usage\n\n## Import Contacts Library\n\n```js\nimport Contacts from 'react-native-unified-contacts';\n```\n\n## Getting Contacts\n\n### Get a single contact\n\n```js\nlet contactIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nContacts.getContact( contactIdentifier, (error, contact) =\u003e  {\n  if (error) {\n    console.error(error);\n  }\n  else {\n    console.log(contact);\n  }\n});\n```\n\n### Get All Contacts\n\n```js\nContacts.getContacts( (error, contacts) =\u003e  {\n  if (error) {\n    console.error(error);\n  }\n  else {\n    console.log(contacts);\n  }\n});\n```\n\n### Search All Contacts\n\n```js\nContacts.searchContacts( 'Don Draper', (error, contacts) =\u003e  {\n  if (error) {\n    console.error(error);\n  }\n  else {\n    console.log(contacts);\n  }\n});\n```\n_This will search the given (first), family (last) and nick names of all of the contacts for the provided string. Future versions will allow you to search other fields as well, like phone or email._\n\n\n### Select a Single Contact\n\n\u003cimg src=\"readme_assets/select_contact.gif\" alt=\"Select Contact GIF\" align=\"right\"\u003e\n\nThis will launch the stock Contacts app and allow you to select a particular Contact, returning the Contact card to your app.\n**Android Only**\n\n```js\nContacts.selectContact( (error, contact) =\u003e  {\n  if (error) {\n    console.error(error);\n  }\n  else {\n    console.log(contact);\n  }\n});\n```\n\n\u003cbr clear=\"right\"/\u003e\n\n### Open a Single Contact\n\nThis will launch the stock Contact card of a single Contact and allows you to contact them through text, phone, email, etc.\n**Android Only**\n\n```js\nContacts.openContact( contactIdentifier );\n```\n\n\n## Adding Contacts\n\n### Add a single contact\n\n```js\nlet contactData = {\n  'givenName':        'John',\n  'familyName':       'Appleseed',\n  'organizationName': 'Apple Inc',\n  'phoneNumbers': [\n    {'label': 'Home', 'stringValue': '555-522-8243'},\n    {'label': 'Work', 'stringValue': '(408) 555-5270'},\n  ],\n  'emailAddresses': [\n    {'label': 'Work', 'value': 'john.appleseed@apple.com'},\n    {'label': 'Home', 'value': 'john@gmail.com'},\n  ],\n  'postalAddresses': [\n    {\n      'label': 'Work',\n      'street': '123 Fake Street',\n      'city':  'Boston',\n      'state':  'MA',\n      'postalCode':  '90210',\n      'country':  'United States',\n    },\n    {\n      'label': 'Home',\n      'street': '123 North Street',\n      'city':  'Halifax',\n      'state':  'NS',\n      'postalCode':  'M5M 4T4',\n      'country':  'Canada',\n    },\n  ],\n}\n\nContacts.addContact( contactData, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  }\n  else {\n    console.log(success);\n  }\n});\n```\n\n## Updating Contacts\n\n### Update a single contact\n\n```js\nlet contactIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nlet contactData = {\n  'givenName':        'John',\n  'familyName':       'Appleseed',\n  'organizationName': 'Apple Inc',\n  'phoneNumbers': [\n    {'label': 'Home', 'stringValue': '555-522-8243'},\n    {'label': 'Work', 'stringValue': '(408) 555-5270'},\n  ],\n  'emailAddresses': [\n    {'label': 'Work', 'value': 'john.appleseed@apple.com'},\n    {'label': 'Home', 'value': 'john@gmail.com'},\n  ],\n  'postalAddresses': [\n    {\n      'label': 'Work',\n      'street': '123 Fake Street',\n      'city':  'Boston',\n      'state':  'MA',\n      'postalCode':  '90210',\n      'country':  'United States',\n    },\n    {\n      'label': 'Home',\n      'street': '123 North Street',\n      'city':  'Halifax',\n      'state':  'NS',\n      'postalCode':  'M5M 4T4',\n      'country':  'Canada',\n    },\n  ],\n}\n\nContacts.updateContact(contactIdentifier, contactData, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  }\n  else {\n    console.log(success);\n  }\n});\n```\n\n_NOTE: If your `contactData` includes the keys `phoneNumbers`, `emailAddresses`, or `postalAddresses` the associated value will completely replace any Phone Numbers, Email Addresses or Postal Addresses for that Contact, respectively. In other words, if you have a contact with two Phone Numbers and you'd like to add a third, you need to pass in ALL THREE Phone Numbers, not just the new one. Same goes for Email Addresses and Postal Addresses._\n\n\n## Deleting Contacts\n\n### Delete a single contact\n\n```js\nlet contactIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nContacts.deleteContact( contactIdentifier, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  }\n  else {\n    console.log(success);\n  }\n}\n```\n\n## Getting Groups\n\n### Get a single group\n\n```js\nlet groupIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nContacts.getGroup( groupIdentifier, (error, group) =\u003e  {\n  if (error) {\n    console.error(error);\n  } else {\n    console.log(group);\n  }\n});\n```\n\n### Get all Groups\n\n```js\nContacts.getGroups( (error, groups) =\u003e  {\n  if (error) {\n    console.error(error);\n  }\n  else {\n    console.log(groups);\n  }\n});\n```\n\n### Get contacts in group\n\n```js\nlet groupIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nContacts.contactsInGroup(groupIdentifier, (error, contacts) =\u003e  {\n  if (error) {\n    console.error(error);\n  } else {\n    console.log(contacts);\n  }\n});\n```\n\n## Add a group\n\n```js\nlet groupData = {\n  'name': 'Friends'\n}\n\nContacts.addGroup(groupData, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  }\n  else {\n    console.log(success);\n  }\n});\n```\n\n## Update a group\n\n```js\nlet groupIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nlet groupData = {\n  'name': 'Friends'\n}\n\nContacts.updateGroup(groupIdentifier, groupData, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  }\n  else {\n    console.log(success);\n  }\n});\n```\n\n## Delete a group\n\n```js\nlet groupIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nContacts.deleteGroup(groupIdentifier, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  }\n  else {\n    console.log(success);\n  }\n});\n```\n\n## Add contacts to a group\n\n```js\nlet groupIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nlet contactIdentifiers = [\n  '4E5R6TGH-2EWQ-SAD2-SADS-2344EWFSDCSA',\n  '8GFK43JK-2E3F-U6HF-UYTB-23R4TGTHYRDF',\n  '5FTGYUHG-DSFD-4T5H-43TR-0IOJUVBHJNVG'\n]\n\nContacts.addContactsToGroup(groupIdentifier, contactIdentifiers, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  } else {\n    console.log(success);\n  }\n});\n```\n\n## Remove contacts from a group\n\n```js\nlet groupIdentifier = 'A7806266-6574-4731-82E1-C54946F63E1C';\n\nlet contactIdentifiers = [\n  '4E5R6TGH-2EWQ-SAD2-SADS-2344EWFSDCSA',\n  '8GFK43JK-2E3F-U6HF-UYTB-23R4TGTHYRDF',\n  '5FTGYUHG-DSFD-4T5H-43TR-0IOJUVBHJNVG'\n]\n\nContacts.removeContactsFromGroup(groupIdentifier, contactIdentifiers, (error, success) =\u003e {\n  if (error) {\n    console.log(error);\n  } else {\n    console.log(success);\n  }\n});\n```\n\n## Accessing the User's Contacts\n\n### Can The User Access Contacts?\n\n```js\nContacts.userCanAccessContacts( (userCanAccessContacts) =\u003e {\n  if (userCanAccessContacts) {\n    console.log(\"User has access to Contacts!\");\n  }\n  else {\n    console.log(\"User DOES NOT have access to Contacts!\");\n  }\n});\n```\n_This will not **request** access. For that, use the [`requestAccessToContacts`](#request-access-to-contacts)._\n\n\n### Request Access To Contacts\n\n```js\nContacts.requestAccessToContacts( (userCanAccessContacts) =\u003e {\n  if (userCanAccessContacts) {\n    console.log(\"User has access to Contacts!\");\n  }\n  else {\n    console.log(\"User DOES NOT have access to Contacts!\");\n  }\n});\n```\nThis will do everything you'd expect. Here's the workflow:\n\n1. Does the user already have access to Contacts?\n\n   1. Yes. Return `true`.\n\n   2. No.\n\n     1. If the User has not been asked before (first time asking), prompt user for access:\n\n        1. Yes. Return `true`.\n\n        2. No. Return `false`.\n\n     2. If user has already denied access to Contacts, return `false`.\n\n        _The user will have to go to their privacy settings and allow access manually. We provide a [`openPrivacySettings`](#open-privacy-settings) method that allows you to bring up the privacy page easily for the user. See below._\n\n\n### Check if Already Requsted Access To Contacts\n\n```js\nContacts.alreadyRequestedAccessToContacts( (hasRequested) =\u003e {\n  if (hasRequested) {\n    console.log(\"You have already requested access to contacts\");\n  }\n  else {\n    console.log(\"You have not yet asked for access to contacts\");\n  }\n});\n```\nSince you cannot ask again after the user refuses, this allows you to change the UI\n\n\n### Open the User's Privacy Settings\n\n```js\nContacts.openPrivacySettings()\n```\n\nIn the event that the User has denied access to their Contacts, you will need to have them manually change their setting in the privacy page. This method will open up the right page automatically for them and improves the experience for the user.\n\nHere's an example of how you might alert the user that they need to update their privacy settings:\n\n```js\n// Alert the User that we can't access their Contact.\n// Provide a link that will open up their Privacy Settings for ntwrk.\n//\nfunction alertUserToAllowAccessToContacts() {\n  Alert.alert(\n    \"Can't Access Your Contacts\",\n    \"Click on Open Settings and allow ntwrk to access your Contacts.\\n\" +\n    \"\\n\" +\n    \"Then come back!\",\n    [\n      {text: 'Open Settings', onPress: () =\u003e Contacts.openPrivacySettings() },\n      {text: \"Later\"}\n    ]\n  )\n}\n```\n\nThis will produce an alert similar to this:\n\n![Privacy Settings Alert](readme_assets/privacy_settings_alert.png)\n\n\n## Contact Object\n\nThe returned Contact object(s) will look something like this:\n\n```js\n{\n  \"contactRelations\": [\n    {\n      \"label\": \"Mother\",\n      \"identifier\": \"2D103009-45E2-4CA5-A2D5-50642EE7430C\",\n      \"name\": \"Mother Name\",\n      \"localizedLabel\": \"mother\"\n    }\n  ],\n  \"middleName\": \"Middle Name\",\n  \"phoneticGivenName\": \"Phonetic Given Name\",\n  \"phoneticMiddleName\": \"Phonetic Middle Name\",\n  \"nickname\": \"Nickname\",\n  \"phoneticFamilyName\": \"Phonetic Family Name\",\n  \"previousFamilyName\": \"Previous Family Name\",\n  \"familyName\": \"Family Name\",\n  \"phoneNumbers\": [\n    {\n      \"label\": \"Home\",\n      \"identifier\": \"73A0E4B6-86F6-4FAF-A7C3-D55705CA1DFF\",\n      \"stringValue\": \"1 (234) 567-8901\",\n      \"countryCode\": \"us\",\n      \"digits\": \"12345678901\",\n      \"localizedLabel\": \"home\"\n    }\n  ],\n  \"identifier\": \"D296E8E2-982F-4C39-9845-B75808B9CF96:ABPerson\",\n  \"givenName\": \"Given Name\",\n  \"dates\": [\n    {\n      \"label\": \"Anniversary\",\n      \"identifier\": \"FB73491F-E505-4864-8B68-F5F17C5AC4D7\",\n      \"year\": 2016,\n      \"month\": 1,\n      \"day\": 30,\n      \"localizedLabel\": \"anniversary\"\n    }\n  ],\n  \"fullName\": \"Full Name\",\n  \"nonGregorianBirthday\": {\n    \"year\": 33,\n    \"month\": 1,\n    \"day\": 3\n  },\n  \"departmentName\": \"Department Name\",\n  \"socialProfiles\": [\n    {\n      \"label\": \"twitter\",\n      \"localizedLabel\": \"twitter\",\n      \"service\": \"Twitter\",\n      \"localizedService\": \"Twitter\",\n      \"urlString\": \"http://twitter.com/12345\",\n      \"userIdentifier\": \"\",\n      \"username\": \"12345\",\n      \"identifier\": \"53698CFA-0125-48FE-84D7-E8372CD99ECD\"\n    }\n  ],\n  \"emailAddresses\": [\n    {\n      \"label\": \"Home\",\n      \"identifier\": \"8AE516A9-A531-4BBA-B890-BFA59E47A4C7\",\n      \"value\": \"person@example.com\",\n      \"localizedLabel\": \"home\"\n    }\n  ],\n  \"instantMessageAddresses\": [\n    {\n      \"label\": \"Skype\",\n      \"identifier\": \"82200A8E-4F19-4F5A-A7AF-FA9F8C43B01A\",\n      \"service\": \"Skype\",\n      \"localizedService\": \"Skype\",\n      \"username\": \"12345\",\n      \"localizedLabel\": \"Skype\"\n    }\n  ],\n  \"note\": \"Note\",\n  \"postalAddresses\": [\n    {\n      \"label\": \"Home\",\n      \"city\": \"City\",\n      \"state\": \"CA\",\n      \"localizedLabel\": \"home\",\n      \"postalCode\": \"98765\",\n      \"country\": \"United States\",\n      \"isoCountryCode\": \"\",\n      \"stringValue\": \"123 St\\nCity CA 98765\\nUnited States\",\n      \"street\": \"123 St\",\n      \"identifier\": \"7A472311-AB4F-46F4-B046-B60143DBC858\"\n    }\n  ],\n  \"urlAddresses\": [\n    {\n      \"label\": \"HomePage\",\n      \"identifier\": \"13F46F96-E5EE-4B6F-A8A6-EBC3C459E314\",\n      \"value\": \"www.example.com\",\n      \"localizedLabel\": \"homepage\"\n    }\n  ],\n  \"organizationName\": \"Organization Name\",\n  \"birthday\": {\n    \"month\": 1,\n    \"day\": 30\n  },\n  \"nameSuffix\": \"Name Suffix\",\n  \"imageDataAvailable\": false,\n  \"contactType\": \"person\",\n  \"namePrefix\": \"Name Prefix\",\n  \"jobTitle\": \"Job Title\"\n}\n```\n\n_NOTE: The birthday key will not be included if the Contact's birthday is not set. Also, it's possible for a Contact's\n  birthday to not include the `year`. In this case, `year` will be `null`._\n\n### Thumbnail Image\n\nThumbnail Image Data is stored in a base64 format and can easily be used with the `Image` component of React Native as follows:\n\n```js\n// contact is a single Contact record retrieved from something like Contacts.getContacts().\nvar base64ImageUri = 'data:image/png;base64,' + contact.thumbnailImageData;\n\n\u003cImage source={{uri: base64ImageUri}}/\u003e\n```\n\n# Troubleshooting\n\n## ExampleApp\n\n![ExampleApp iOS](readme_assets/example_app_ios.gif)\n![ExampleApp Android](readme_assets/example_app_android.gif)\n\nAs a quick example and a way to prove that it's working as expected with a fresh React Native app, there's an ExampleApp contained in the repository.\n\nOne of the best things to do is to make sure that this is working, see how it works and then take what you need to make it work in your own application.\n\nTo quickly run the ExampleApp:\n\n1. `git clone git@github.com:joshuapinter/react-native-unified-contacts.git`\n\n1. `cd react-native-unified-contacts/ExampleApp`\n\n1. `npm install`\n\n1. `open ios/ExampleApp.xcodeproject`\n\n1. Select your favourite device and click run.\n\n\n## Other Issues\n\nIf you run into trouble, take a look at the following thread:\n\nhttps://github.com/joshuapinter/react-native-unified-contacts/issues/15\n\nYou should also have the latest version of XCode (9.2+) and Swift (4+).\n\nIf that doesn't help you, please [create an Issue](https://github.com/joshuapinter/react-native-unified-contacts/issues/new) and we'll figure it out together.\n\n# Many Thanks To\n\n* My friend **[Smixx][smixx]** for working through adding a Swift library to a React Native project over his lunch hour.\n* **[Ismail Pelaseyed (homanp)][homanp]** for adding a couple of [huge PRs][homanp-prs] for Creating, Updating and Deleting Contacts.\n* **[Chris Edwards (chrise86)][chrise86]** for adding a tonne of [big PRs][chrise86-prs] for Adding, Updating and Deleting Groups.\n* **[Paul Wright (paintedbicycle)][paintedbicycle]** for acting like a PM with the Android Support, committing a number of critical updates and getting Android back on track. Thank you! 🙏\n\n# TODO\n\n- [X] Add Create/Update/Delete methods for Contacts. **_(Thanks [homanp][homanp]!)_**\n- [X] Add Basic Android support.\n- [ ] Add Full Android support.\n\n\n# License\n\nThe MIT License (MIT)\n\nCopyright 2016 - 2018 by [Joshua Pinter][joshuapinter]\n\n\n[apple-contacts-framework]: https://developer.apple.com/library/ios/documentation/Contacts/Reference/Contacts_Framework/index.html\n[react-native-contacts]:    https://github.com/rt2zz/react-native-contacts\n[react-native-addressbook]: https://github.com/rt2zz/react-native-addressbook\n[smixx]:                    https://twitter.com/smixx\n[joshuapinter]:             https://twitter.com/joshuapinter\n[homanp]:                   https://twitter.com/pelaseyed\n[homanp-prs]:               https://github.com/joshuapinter/react-native-unified-contacts/pulls?utf8=%E2%9C%93\u0026q=is%3Apr+author%3Ahomanp+\n[chrise86]:                 https://github.com/chrise86\n[chrise86-prs]:             https://github.com/joshuapinter/react-native-unified-contacts/pulls?utf8=%E2%9C%93\u0026q=is%3Apr%20author%3Achrise86\n[paintedbicycle]:           https://github.com/paintedbicycle\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuapinter%2Freact-native-unified-contacts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshuapinter%2Freact-native-unified-contacts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuapinter%2Freact-native-unified-contacts/lists"}