From 7012276fa24b66a40bb877aa0c7b99e7a0ffa2d6 Mon Sep 17 00:00:00 2001 From: Zhen Qiu Date: Thu, 4 Feb 2021 16:47:12 -0800 Subject: [PATCH 1/5] add contact info. --- .../ContactsServicePlugin.java | 770 ++++++++++++++---- lib/contacts_service.dart | 28 +- 2 files changed, 630 insertions(+), 168 deletions(-) diff --git a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java index f8645a63..d923d69b 100644 --- a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java +++ b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java @@ -1,5 +1,13 @@ package flutter.plugins.contactsservice.contactsservice; +import static android.app.Activity.RESULT_CANCELED; +import static android.provider.ContactsContract.CommonDataKinds; +import static android.provider.ContactsContract.CommonDataKinds.Email; +import static android.provider.ContactsContract.CommonDataKinds.Organization; +import static android.provider.ContactsContract.CommonDataKinds.Phone; +import static android.provider.ContactsContract.CommonDataKinds.StructuredName; +import static android.provider.ContactsContract.CommonDataKinds.StructuredPostal; + import android.annotation.TargetApi; import android.content.ContentProviderOperation; import android.content.ContentResolver; @@ -17,7 +25,16 @@ import android.provider.ContactsContract; import android.text.TextUtils; import android.util.Log; - +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.embedding.engine.plugins.activity.ActivityAware; +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugin.common.PluginRegistry.Registrar; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -27,30 +44,12 @@ import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.embedding.engine.plugins.activity.ActivityAware; -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.plugin.common.PluginRegistry.Registrar; - -import static android.app.Activity.RESULT_CANCELED; -import static android.provider.ContactsContract.CommonDataKinds; -import static android.provider.ContactsContract.CommonDataKinds.Email; -import static android.provider.ContactsContract.CommonDataKinds.Organization; -import static android.provider.ContactsContract.CommonDataKinds.Phone; -import static android.provider.ContactsContract.CommonDataKinds.StructuredName; -import static android.provider.ContactsContract.CommonDataKinds.StructuredPostal; - @TargetApi(Build.VERSION_CODES.ECLAIR) public class ContactsServicePlugin implements MethodCallHandler, FlutterPlugin, ActivityAware { @@ -102,10 +101,25 @@ public void onDetachedFromEngine(FlutterPluginBinding binding) { public void onMethodCall(MethodCall call, Result result) { switch(call.method){ case "getContacts": { - this.getContacts(call.method, (String)call.argument("query"), (boolean)call.argument("withThumbnails"), (boolean)call.argument("photoHighResolution"), (boolean)call.argument("orderByGivenName"), (boolean)call.argument("androidLocalizedLabels"), result); + this.getContacts( + call.method, + (String) call.argument("query"), + (boolean) call.argument("withThumbnails"), + (boolean) call.argument("photoHighResolution"), + (boolean) call.argument("orderByGivenName"), + (boolean) call.argument("androidLocalizedLabels"), + (List) call.argument("contactInfos"), + result); break; } case "getContactsForPhone": { - this.getContactsForPhone(call.method, (String)call.argument("phone"), (boolean)call.argument("withThumbnails"), (boolean)call.argument("photoHighResolution"), (boolean)call.argument("orderByGivenName"), (boolean)call.argument("androidLocalizedLabels"), result); + this.getContactsForPhone( + call.method, + (String) call.argument("phone"), + (boolean) call.argument("withThumbnails"), + (boolean) call.argument("photoHighResolution"), + (boolean) call.argument("orderByGivenName"), + (boolean) call.argument("androidLocalizedLabels"), + result); break; } case "getAvatar": { final Contact contact = Contact.fromMap((HashMap)call.argument("contact")); @@ -124,7 +138,8 @@ public void onMethodCall(MethodCall call, Result result) { if (this.deleteContact(contact)) { result.success(null); } else { - result.error(null, "Failed to delete the contact, make sure it has a valid identifier", null); + result.error( + null, "Failed to delete the contact, make sure it has a valid identifier", null); } break; } case "updateContact": { @@ -132,33 +147,34 @@ public void onMethodCall(MethodCall call, Result result) { if (this.updateContact(contact)) { result.success(null); } else { - result.error(null, "Failed to update the contact, make sure it has a valid identifier", null); + result.error( + null, "Failed to update the contact, make sure it has a valid identifier", null); } break; } case "openExistingContact" :{ final Contact contact = Contact.fromMap((HashMap)call.argument("contact")); - final boolean localizedLabels = call.argument("androidLocalizedLabels"); + final boolean localizedLabels = call.argument("androidLocalizedLabels"); if (delegate != null) { delegate.setResult(result); - delegate.setLocalizedLabels(localizedLabels); + delegate.setLocalizedLabels(localizedLabels); delegate.openExistingContact(contact); } else { result.success(FORM_COULD_NOT_BE_OPEN); } break; } case "openContactForm": { - final boolean localizedLabels = call.argument("androidLocalizedLabels"); + final boolean localizedLabels = call.argument("androidLocalizedLabels"); if (delegate != null) { delegate.setResult(result); - delegate.setLocalizedLabels(localizedLabels); + delegate.setLocalizedLabels(localizedLabels); delegate.openContactForm(); } else { result.success(FORM_COULD_NOT_BE_OPEN); } break; } case "openDeviceContactPicker": { - final boolean localizedLabels = call.argument("androidLocalizedLabels"); - openDeviceContactPicker(result, localizedLabels); + final boolean localizedLabels = call.argument("androidLocalizedLabels"); + openDeviceContactPicker(result, localizedLabels); break; } default: { result.notImplemented(); @@ -202,14 +218,151 @@ public void onMethodCall(MethodCall call, Result result) { StructuredPostal.COUNTRY, }; + private static final String[] ACCOUNT_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Profile.DISPLAY_NAME, + ContactsContract.Contacts.Data.MIMETYPE, + ContactsContract.RawContacts.ACCOUNT_TYPE, + ContactsContract.RawContacts.ACCOUNT_NAME, + }; + + private static final String[] NAME_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Contacts.Data.MIMETYPE, + StructuredName.DISPLAY_NAME, + StructuredName.GIVEN_NAME, + StructuredName.MIDDLE_NAME, + StructuredName.FAMILY_NAME, + StructuredName.PREFIX, + StructuredName.SUFFIX, + }; + + private static final String[] NOTE_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Contacts.Data.MIMETYPE, + CommonDataKinds.Note.NOTE, + }; + + private static final String[] PHONE_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Contacts.Data.MIMETYPE, + Phone.NUMBER, + Phone.TYPE, + Phone.LABEL, + }; + + private static final String[] EMAIL_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Contacts.Data.MIMETYPE, + Email.DATA, + Email.ADDRESS, + Email.TYPE, + Email.LABEL, + }; + + private static final String[] ORG_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Contacts.Data.MIMETYPE, + Organization.COMPANY, + Organization.TITLE, + }; + + private static final String[] LOCATION_PROJECTION = { + ContactsContract.Data.CONTACT_ID, + ContactsContract.Contacts.Data.MIMETYPE, + StructuredPostal.FORMATTED_ADDRESS, + StructuredPostal.TYPE, + StructuredPostal.LABEL, + StructuredPostal.STREET, + StructuredPostal.POBOX, + StructuredPostal.NEIGHBORHOOD, + StructuredPostal.CITY, + StructuredPostal.REGION, + StructuredPostal.POSTCODE, + StructuredPostal.COUNTRY, + }; @TargetApi(Build.VERSION_CODES.ECLAIR) - private void getContacts(String callMethod, String query, boolean withThumbnails, boolean photoHighResolution, boolean orderByGivenName, boolean localizedLabels, Result result) { - new GetContactsTask(callMethod, result, withThumbnails, photoHighResolution, orderByGivenName, localizedLabels).executeOnExecutor(executor, query, false); + private void getContacts( + String callMethod, + String query, + boolean withThumbnails, + boolean photoHighResolution, + boolean orderByGivenName, + boolean localizedLabels, + List contactInfos, + Result result) { + new GetContactsTask( + callMethod, + result, + withThumbnails, + photoHighResolution, + orderByGivenName, + localizedLabels, + contactInfos) + .executeOnExecutor(executor, query, false); + } + + private ArrayList getContacts( + String query, String rawContactId, boolean localizedLabels, List contactInfos) { + String selection = + "(" + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.Data.MIMETYPE + + "=? OR " + + ContactsContract.RawContacts.ACCOUNT_TYPE + + "=?" + + ")"; + ArrayList selectionArgs = + new ArrayList<>( + Arrays.asList( + CommonDataKinds.Note.CONTENT_ITEM_TYPE, + Email.CONTENT_ITEM_TYPE, + Phone.CONTENT_ITEM_TYPE, + StructuredName.CONTENT_ITEM_TYPE, + Organization.CONTENT_ITEM_TYPE, + StructuredPostal.CONTENT_ITEM_TYPE, + CommonDataKinds.Event.CONTENT_ITEM_TYPE, + ContactsContract.RawContacts.ACCOUNT_TYPE)); + if (query != null) { + selectionArgs = new ArrayList<>(); + selectionArgs.add(query + "%"); + selection = ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?"; + } + if (rawContactId != null) { + selectionArgs.add(rawContactId); + selection += " AND " + ContactsContract.Data.CONTACT_ID + " =?"; + } + return queryContacts(selection, selectionArgs, localizedLabels, contactInfos); } - private void getContactsForPhone(String callMethod, String phone, boolean withThumbnails, boolean photoHighResolution, boolean orderByGivenName, boolean localizedLabels, Result result) { - new GetContactsTask(callMethod, result, withThumbnails, photoHighResolution, orderByGivenName, localizedLabels).executeOnExecutor(executor, phone, true); + private void getContactsForPhone( + String callMethod, + String phone, + boolean withThumbnails, + boolean photoHighResolution, + boolean orderByGivenName, + boolean localizedLabels, + Result result) { + new GetContactsTask( + callMethod, + result, + withThumbnails, + photoHighResolution, + orderByGivenName, + localizedLabels, null) + .executeOnExecutor(executor, phone, true); } @Override @@ -283,7 +436,8 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent intent) Cursor cursor = contentResolver.query(contactUri, null, null, null, null); if (cursor.moveToFirst()) { String id = contactUri.getLastPathSegment(); - getContacts("openDeviceContactPicker", id, false, false, false, localizedLabels, this.result); + getContacts( + "openDeviceContactPicker", id, false, false, false, localizedLabels, null, this.result); } else { Log.e(LOG_TAG, "onActivityResult - cursor.moveToFirst() returns false"); finishWithResult(FORM_OPERATION_CANCELED); @@ -356,17 +510,17 @@ HashMap getContactByIdentifier(String identifier) { return null; } } - - private void openDeviceContactPicker(Result result, boolean localizedLabels) { + + private void openDeviceContactPicker(Result result, boolean localizedLabels) { if (delegate != null) { delegate.setResult(result); - delegate.setLocalizedLabels(localizedLabels); + delegate.setLocalizedLabels(localizedLabels); delegate.openContactPicker(); } else { result.success(FORM_COULD_NOT_BE_OPEN); } } - + private class ContactServiceDelegateOld extends BaseContactsServiceDelegate { private final PluginRegistry.Registrar registrar; @@ -426,23 +580,38 @@ private class GetContactsTask extends AsyncTask private boolean photoHighResolution; private boolean orderByGivenName; private boolean localizedLabels; - - public GetContactsTask(String callMethod, Result result, boolean withThumbnails, boolean photoHighResolution, boolean orderByGivenName, boolean localizedLabels) { + private List contactInfos; + + public GetContactsTask( + String callMethod, + Result result, + boolean withThumbnails, + boolean photoHighResolution, + boolean orderByGivenName, + boolean localizedLabels, + List contactInfos) { this.callMethod = callMethod; this.getContactResult = result; this.withThumbnails = withThumbnails; this.photoHighResolution = photoHighResolution; this.orderByGivenName = orderByGivenName; this.localizedLabels = localizedLabels; + this.contactInfos = contactInfos; } @TargetApi(Build.VERSION_CODES.ECLAIR) protected ArrayList doInBackground(Object... params) { ArrayList contacts; switch (callMethod) { - case "openDeviceContactPicker": contacts = getContactsFrom(getCursor(null, (String) params[0]), localizedLabels); break; - case "getContacts": contacts = getContactsFrom(getCursor((String) params[0], null), localizedLabels); break; - case "getContactsForPhone": contacts = getContactsFrom(getCursorForPhone(((String) params[0])), localizedLabels); break; + case "openDeviceContactPicker": + contacts = getContacts(null, (String) params[0], localizedLabels, contactInfos); + break; + case "getContacts": + contacts = getContacts((String) params[0], null, localizedLabels, contactInfos); + break; + case "getContactsForPhone": + contacts = getContactsFrom(getCursorForPhone(((String) params[0])), localizedLabels); + break; default: return null; } @@ -492,25 +661,280 @@ protected void onPostExecute(ArrayList result) { } } + private ArrayList queryContacts( + String selection, + ArrayList selectionArgs, + boolean localizedLabels, + List contactInfos) { + HashMap map = new LinkedHashMap<>(); + if (contactInfos == null || contactInfos.contains("ContactInfo.account")) { + Cursor accountInfoCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + ACCOUNT_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (accountInfoCursor != null && accountInfoCursor.moveToNext()) { + populateAccountInfo(map, accountInfoCursor); + } + if (accountInfoCursor != null) { + accountInfoCursor.close(); + } + } - private Cursor getCursor(String query, String rawContactId) { - String selection = "(" + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=? OR " - + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=? OR " - + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=? OR " - + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.RawContacts.ACCOUNT_TYPE + "=?" + ")"; - ArrayList selectionArgs = new ArrayList<>(Arrays.asList(CommonDataKinds.Note.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE, - Phone.CONTENT_ITEM_TYPE, StructuredName.CONTENT_ITEM_TYPE, Organization.CONTENT_ITEM_TYPE, - StructuredPostal.CONTENT_ITEM_TYPE, CommonDataKinds.Event.CONTENT_ITEM_TYPE, ContactsContract.RawContacts.ACCOUNT_TYPE)); - if (query != null) { - selectionArgs = new ArrayList<>(); - selectionArgs.add(query + "%"); - selection = ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?"; + if (contactInfos == null || contactInfos.contains("ContactInfo.name")) { + Cursor nameCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + NAME_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (nameCursor != null && nameCursor.moveToNext()) { + populateName(map, nameCursor); + } + if (nameCursor != null) { + nameCursor.close(); + } } - if (rawContactId != null) { - selectionArgs.add(rawContactId); - selection += " AND " + ContactsContract.Data.CONTACT_ID + " =?"; + + if (contactInfos == null || contactInfos.contains("ContactInfo.note")) { + Cursor noteCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + NOTE_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (noteCursor != null && noteCursor.moveToNext()) { + populateNote(map, noteCursor); + } + if (noteCursor != null) { + noteCursor.close(); + } + } + + if (contactInfos == null || contactInfos.contains("ContactInfo.phone")) { + Cursor phoneCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + PHONE_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (phoneCursor != null && phoneCursor.moveToNext()) { + populatePhone(map, phoneCursor, localizedLabels); + } + if (phoneCursor != null) { + phoneCursor.close(); + } + } + + if (contactInfos == null || contactInfos.contains("ContactInfo.email")) { + Cursor emailCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + EMAIL_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (emailCursor != null && emailCursor.moveToNext()) { + populateEmail(map, emailCursor, localizedLabels); + } + if (emailCursor != null) { + emailCursor.close(); + } + } + + if (contactInfos == null || contactInfos.contains("ContactInfo.org")) { + Cursor orgCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + ORG_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (orgCursor != null && orgCursor.moveToNext()) { + populateOrg(map, orgCursor); + } + if (orgCursor != null) { + orgCursor.close(); + } + } + + if (contactInfos == null || contactInfos.contains("ContactInfo.location")) { + Cursor locationCursor = + contentResolver.query( + ContactsContract.Data.CONTENT_URI, + LOCATION_PROJECTION, + selection, + selectionArgs.toArray(new String[selectionArgs.size()]), + null); + + while (locationCursor != null && locationCursor.moveToNext()) { + populateLocation(map, locationCursor, localizedLabels); + } + if (locationCursor != null) { + locationCursor.close(); + } + } + + return new ArrayList<>(map.values()); + } + + private static void populateAccountInfo(HashMap map, Cursor accountInfoCursor) { + int columnIndex = accountInfoCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = accountInfoCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + contact.displayName = + accountInfoCursor.getString( + accountInfoCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); + contact.androidAccountType = + accountInfoCursor.getString( + accountInfoCursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)); + contact.androidAccountName = + accountInfoCursor.getString( + accountInfoCursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_NAME)); + } + + private static void populateName(HashMap map, Cursor nameCursor) { + int columnIndex = nameCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = nameCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + String mimeType = + nameCursor.getString(nameCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); + if (mimeType.equals(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) { + contact.givenName = + nameCursor.getString(nameCursor.getColumnIndex(StructuredName.GIVEN_NAME)); + contact.middleName = + nameCursor.getString(nameCursor.getColumnIndex(StructuredName.MIDDLE_NAME)); + contact.familyName = + nameCursor.getString(nameCursor.getColumnIndex(StructuredName.FAMILY_NAME)); + contact.prefix = nameCursor.getString(nameCursor.getColumnIndex(StructuredName.PREFIX)); + contact.suffix = nameCursor.getString(nameCursor.getColumnIndex(StructuredName.SUFFIX)); + } + } + + private static void populateNote(HashMap map, Cursor noteCursor) { + int columnIndex = noteCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = noteCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + String mimeType = + noteCursor.getString(noteCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); + if (mimeType.equals(CommonDataKinds.Note.CONTENT_ITEM_TYPE)) { + contact.note = noteCursor.getString(noteCursor.getColumnIndex(CommonDataKinds.Note.NOTE)); + } + } + + private void populatePhone( + HashMap map, Cursor phoneCursor, boolean localizedLabels) { + int columnIndex = phoneCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = phoneCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + String mimeType = + phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); + if (mimeType.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) { + String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(Phone.NUMBER)); + if (!TextUtils.isEmpty(phoneNumber)) { + int type = phoneCursor.getInt(phoneCursor.getColumnIndex(Phone.TYPE)); + String label = Item.getPhoneLabel(resources, type, phoneCursor, localizedLabels); + contact.phones.add(new Item(label, phoneNumber, type)); + } + } + } + + private void populateEmail( + HashMap map, Cursor emailCursor, boolean localizedLabels) { + int columnIndex = emailCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = emailCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + String mimeType = + emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); + if (mimeType.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) { + String email = emailCursor.getString(emailCursor.getColumnIndex(Email.ADDRESS)); + int type = emailCursor.getInt(emailCursor.getColumnIndex(Email.TYPE)); + if (!TextUtils.isEmpty(email)) { + String label = Item.getEmailLabel(resources, type, emailCursor, localizedLabels); + contact.emails.add(new Item(label, email, type)); + } + } + } + + private static void populateOrg(HashMap map, Cursor orgCursor) { + int columnIndex = orgCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = orgCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + String mimeType = orgCursor.getString(orgCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); + if (mimeType.equals(CommonDataKinds.Organization.CONTENT_ITEM_TYPE)) { + contact.company = orgCursor.getString(orgCursor.getColumnIndex(Organization.COMPANY)); + contact.jobTitle = orgCursor.getString(orgCursor.getColumnIndex(Organization.TITLE)); + } + } + + private void populateLocation( + HashMap map, Cursor locationCursor, boolean localizedLabels) { + int columnIndex = locationCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); + String contactId = locationCursor.getString(columnIndex); + + if (!map.containsKey(contactId)) { + map.put(contactId, new Contact(contactId)); + } + Contact contact = map.get(contactId); + + String mimeType = + locationCursor.getString(locationCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); + if (mimeType.equals(CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)) { + int type = locationCursor.getInt(locationCursor.getColumnIndex(StructuredPostal.TYPE)); + String label = PostalAddress.getLabel(resources, type, locationCursor, localizedLabels); + String street = + locationCursor.getString(locationCursor.getColumnIndex(StructuredPostal.STREET)); + String city = locationCursor.getString(locationCursor.getColumnIndex(StructuredPostal.CITY)); + String postcode = + locationCursor.getString(locationCursor.getColumnIndex(StructuredPostal.POSTCODE)); + String region = + locationCursor.getString(locationCursor.getColumnIndex(StructuredPostal.REGION)); + String country = + locationCursor.getString(locationCursor.getColumnIndex(StructuredPostal.COUNTRY)); + contact.postalAddresses.add( + new PostalAddress(label, street, city, postcode, region, country, type)); } - return contentResolver.query(ContactsContract.Data.CONTENT_URI, PROJECTION, selection, selectionArgs.toArray(new String[selectionArgs.size()]), null); } private Cursor getCursorForPhone(String phone) { @@ -539,6 +963,7 @@ private Cursor getCursorForPhone(String phone) { /** * Builds the list of contacts from the cursor + * * @param cursor * @return the list of contacts */ @@ -555,87 +980,36 @@ private ArrayList getContactsFrom(Cursor cursor, boolean localizedLabel Contact contact = map.get(contactId); String mimeType = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); - contact.displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); - contact.androidAccountType = cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)); - contact.androidAccountName = cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_NAME)); - - //NAMES - if (mimeType.equals(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) { - contact.givenName = cursor.getString(cursor.getColumnIndex(StructuredName.GIVEN_NAME)); - contact.middleName = cursor.getString(cursor.getColumnIndex(StructuredName.MIDDLE_NAME)); - contact.familyName = cursor.getString(cursor.getColumnIndex(StructuredName.FAMILY_NAME)); - contact.prefix = cursor.getString(cursor.getColumnIndex(StructuredName.PREFIX)); - contact.suffix = cursor.getString(cursor.getColumnIndex(StructuredName.SUFFIX)); - } + + populateAccountInfo(map, cursor); + // NAMES + populateName(map, cursor); // NOTE - else if (mimeType.equals(CommonDataKinds.Note.CONTENT_ITEM_TYPE)) { - contact.note = cursor.getString(cursor.getColumnIndex(CommonDataKinds.Note.NOTE)); - } - //PHONES - else if (mimeType.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)){ - String phoneNumber = cursor.getString(cursor.getColumnIndex(Phone.NUMBER)); - if (!TextUtils.isEmpty(phoneNumber)){ - int type = cursor.getInt(cursor.getColumnIndex(Phone.TYPE)); - String label = Item.getPhoneLabel(resources, type, cursor, localizedLabels); - contact.phones.add(new Item(label, phoneNumber, type)); - } - } - //MAILS - else if (mimeType.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) { - String email = cursor.getString(cursor.getColumnIndex(Email.ADDRESS)); - int type = cursor.getInt(cursor.getColumnIndex(Email.TYPE)); - if (!TextUtils.isEmpty(email)) { - String label = Item.getEmailLabel(resources, type, cursor, localizedLabels); - contact.emails.add(new Item(label, email, type)); - } - } - //ORG - else if (mimeType.equals(CommonDataKinds.Organization.CONTENT_ITEM_TYPE)) { - contact.company = cursor.getString(cursor.getColumnIndex(Organization.COMPANY)); - contact.jobTitle = cursor.getString(cursor.getColumnIndex(Organization.TITLE)); - } - //ADDRESSES - else if (mimeType.equals(CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)) { - int type = cursor.getInt(cursor.getColumnIndex(StructuredPostal.TYPE)); - String label = PostalAddress.getLabel(resources, type, cursor, localizedLabels); - String street = cursor.getString(cursor.getColumnIndex(StructuredPostal.STREET)); - String city = cursor.getString(cursor.getColumnIndex(StructuredPostal.CITY)); - String postcode = cursor.getString(cursor.getColumnIndex(StructuredPostal.POSTCODE)); - String region = cursor.getString(cursor.getColumnIndex(StructuredPostal.REGION)); - String country = cursor.getString(cursor.getColumnIndex(StructuredPostal.COUNTRY)); - contact.postalAddresses.add(new PostalAddress(label, street, city, postcode, region, country, type)); - } + populateNote(map, cursor); + // PHONES + populatePhone(map, cursor, localizedLabels); + // MAILS + populateEmail(map, cursor, localizedLabels); + // ORG + populateOrg(map, cursor); + // ADDRESSES + populateLocation(map, cursor, localizedLabels); // BIRTHDAY - else if (mimeType.equals(CommonDataKinds.Event.CONTENT_ITEM_TYPE)) { + if (mimeType.equals(CommonDataKinds.Event.CONTENT_ITEM_TYPE)) { int eventType = cursor.getInt(cursor.getColumnIndex(CommonDataKinds.Event.TYPE)); if (eventType == CommonDataKinds.Event.TYPE_BIRTHDAY) { - contact.birthday = cursor.getString(cursor.getColumnIndex(CommonDataKinds.Event.START_DATE)); + contact.birthday = + cursor.getString(cursor.getColumnIndex(CommonDataKinds.Event.START_DATE)); } } } - if(cursor != null) - cursor.close(); + if (cursor != null) cursor.close(); return new ArrayList<>(map.values()); } - private void setAvatarDataForContactIfAvailable(Contact contact) { - Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Integer.parseInt(contact.identifier)); - Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); - Cursor avatarCursor = contentResolver.query(photoUri, - new String[] {ContactsContract.Contacts.Photo.PHOTO}, null, null, null); - if (avatarCursor != null && avatarCursor.moveToFirst()) { - byte[] avatar = avatarCursor.getBlob(0); - contact.avatar = avatar; - } - if (avatarCursor != null) { - avatarCursor.close(); - } - } - - private void getAvatar(final Contact contact, final boolean highRes, - final Result result) { + private void getAvatar(final Contact contact, final boolean highRes, final Result result) { new GetAvatarsTask(contact, highRes, contentResolver, result).executeOnExecutor(this.executor); } @@ -736,18 +1110,18 @@ private boolean addContact(Contact contact){ .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone.value); - if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM){ + if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) { op.withValue( ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.BaseTypes.TYPE_CUSTOM ); op.withValue(ContactsContract.CommonDataKinds.Phone.LABEL, phone.label); - } else - op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); + } else op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); ops.add(op.build()); } //Emails for (Item email : contact.emails) { - op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + op = + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(CommonDataKinds.Email.ADDRESS, email.value) @@ -756,9 +1130,12 @@ private boolean addContact(Contact contact){ } //Postal addresses for (PostalAddress address : contact.postalAddresses) { - op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + op = + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) + .withValue( + ContactsContract.Data.MIMETYPE, + CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) .withValue(CommonDataKinds.StructuredPostal.TYPE, address.type) .withValue(CommonDataKinds.StructuredPostal.LABEL, address.label) .withValue(CommonDataKinds.StructuredPostal.STREET, address.street) @@ -787,8 +1164,11 @@ private boolean addContact(Contact contact){ private boolean deleteContact(Contact contact){ ArrayList ops = new ArrayList<>(); - ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) - .withSelection(ContactsContract.RawContacts.CONTACT_ID + "=?", new String[]{String.valueOf(contact.identifier)}) + ops.add( + ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) + .withSelection( + ContactsContract.RawContacts.CONTACT_ID + "=?", + new String[] {String.valueOf(contact.identifier)}) .build()); try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); @@ -804,41 +1184,97 @@ private boolean updateContact(Contact contact) { ContentProviderOperation.Builder op; // Drop all details about contact except name - op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE}); + op = + ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE + }); ops.add(op.build()); - op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}); + op = + ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + }); ops.add(op.build()); - op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID +"=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}); + op = + ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE + }); ops.add(op.build()); - op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID +"=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}); + op = + ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE + }); ops.add(op.build()); - op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}); + op = + ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + }); ops.add(op.build()); - //Photo - op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}); + // Photo + op = + ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + }); ops.add(op.build()); // Update data (name) - op = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}) + op = + ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) + .withSelection( + ContactsContract.Data.CONTACT_ID + + "=? AND " + + ContactsContract.Data.MIMETYPE + + "=?", + new String[] { + String.valueOf(contact.identifier), + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + }) .withValue(StructuredName.GIVEN_NAME, contact.givenName) .withValue(StructuredName.MIDDLE_NAME, contact.middleName) .withValue(StructuredName.FAMILY_NAME, contact.familyName) @@ -876,17 +1312,17 @@ private boolean updateContact(Contact contact) { .withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.identifier) .withValue(Phone.NUMBER, phone.value); - if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM){ + if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) { op.withValue( ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.BaseTypes.TYPE_CUSTOM ); op.withValue(ContactsContract.CommonDataKinds.Phone.LABEL, phone.label); - } else - op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); + } else op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); ops.add(op.build()); } for (Item email : contact.emails) { - op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + op = + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.identifier) .withValue(CommonDataKinds.Email.ADDRESS, email.value) @@ -895,8 +1331,11 @@ private boolean updateContact(Contact contact) { } for (PostalAddress address : contact.postalAddresses) { - op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) - .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) + op = + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + .withValue( + ContactsContract.Data.MIMETYPE, + CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.identifier) .withValue(CommonDataKinds.StructuredPostal.TYPE, address.type) .withValue(CommonDataKinds.StructuredPostal.STREET, address.street) @@ -919,3 +1358,4 @@ private boolean updateContact(Contact contact) { } } + diff --git a/lib/contacts_service.dart b/lib/contacts_service.dart index 9b8523dc..be62e871 100644 --- a/lib/contacts_service.dart +++ b/lib/contacts_service.dart @@ -7,19 +7,40 @@ import 'package:quiver/core.dart'; export 'share.dart'; +enum ContactInfo { + account, + name, + note, + phone, + email, + org, + location, +} + class ContactsService { static const MethodChannel _channel = MethodChannel('github.com/clovisnicolas/flutter_contacts'); /// Fetches all contacts, or when specified, the contacts with a name /// matching [query] - static Future> getContacts( - {String? query, + static Future> getContacts({ + String? query, bool withThumbnails = true, bool photoHighResolution = true, bool orderByGivenName = true, bool iOSLocalizedLabels = true, - bool androidLocalizedLabels = true}) async { + bool androidLocalizedLabels = true, + List contactInfos = const [ + ContactInfo.account, + ContactInfo.name, + ContactInfo.note, + ContactInfo.phone, + ContactInfo.email, + ContactInfo.org, + ContactInfo.location + ]}) async { + List contactInfoStrings = contactInfos.map((info) => + info.toString()).toList(); Iterable contacts = await _channel.invokeMethod('getContacts', { 'query': query, @@ -28,6 +49,7 @@ class ContactsService { 'orderByGivenName': orderByGivenName, 'iOSLocalizedLabels': iOSLocalizedLabels, 'androidLocalizedLabels': androidLocalizedLabels, + 'contactInfos': contactInfoStrings, }); return contacts.map((m) => Contact.fromMap(m)); } From 7d220ad431c01d15c7f577e945f362853815fade Mon Sep 17 00:00:00 2001 From: Zhen Qiu Date: Thu, 4 Feb 2021 17:26:53 -0800 Subject: [PATCH 2/5] format. --- .../ContactsServicePlugin.java | 218 +++++++----------- 1 file changed, 83 insertions(+), 135 deletions(-) diff --git a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java index d923d69b..308d9e71 100644 --- a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java +++ b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java @@ -101,25 +101,25 @@ public void onDetachedFromEngine(FlutterPluginBinding binding) { public void onMethodCall(MethodCall call, Result result) { switch(call.method){ case "getContacts": { - this.getContacts( - call.method, - (String) call.argument("query"), - (boolean) call.argument("withThumbnails"), - (boolean) call.argument("photoHighResolution"), - (boolean) call.argument("orderByGivenName"), - (boolean) call.argument("androidLocalizedLabels"), - (List) call.argument("contactInfos"), - result); + this.getContacts( + call.method, + (String) call.argument("query"), + (boolean) call.argument("withThumbnails"), + (boolean) call.argument("photoHighResolution"), + (boolean) call.argument("orderByGivenName"), + (boolean) call.argument("androidLocalizedLabels"), + (List) call.argument("contactInfos"), + result); break; } case "getContactsForPhone": { - this.getContactsForPhone( - call.method, - (String) call.argument("phone"), - (boolean) call.argument("withThumbnails"), - (boolean) call.argument("photoHighResolution"), - (boolean) call.argument("orderByGivenName"), - (boolean) call.argument("androidLocalizedLabels"), - result); + this.getContactsForPhone( + call.method, + (String) call.argument("phone"), + (boolean) call.argument("withThumbnails"), + (boolean) call.argument("photoHighResolution"), + (boolean) call.argument("orderByGivenName"), + (boolean) call.argument("androidLocalizedLabels"), + result); break; } case "getAvatar": { final Contact contact = Contact.fromMap((HashMap)call.argument("contact")); @@ -138,8 +138,7 @@ public void onMethodCall(MethodCall call, Result result) { if (this.deleteContact(contact)) { result.success(null); } else { - result.error( - null, "Failed to delete the contact, make sure it has a valid identifier", null); + result.error(null, "Failed to delete the contact, make sure it has a valid identifier", null); } break; } case "updateContact": { @@ -147,8 +146,7 @@ public void onMethodCall(MethodCall call, Result result) { if (this.updateContact(contact)) { result.success(null); } else { - result.error( - null, "Failed to update the contact, make sure it has a valid identifier", null); + result.error(null, "Failed to update the contact, make sure it has a valid identifier", null); } break; } case "openExistingContact" :{ @@ -156,7 +154,7 @@ public void onMethodCall(MethodCall call, Result result) { final boolean localizedLabels = call.argument("androidLocalizedLabels"); if (delegate != null) { delegate.setResult(result); - delegate.setLocalizedLabels(localizedLabels); + delegate.setLocalizedLabels(localizedLabels); delegate.openExistingContact(contact); } else { result.success(FORM_COULD_NOT_BE_OPEN); @@ -166,15 +164,15 @@ public void onMethodCall(MethodCall call, Result result) { final boolean localizedLabels = call.argument("androidLocalizedLabels"); if (delegate != null) { delegate.setResult(result); - delegate.setLocalizedLabels(localizedLabels); + delegate.setLocalizedLabels(localizedLabels); delegate.openContactForm(); } else { result.success(FORM_COULD_NOT_BE_OPEN); } break; } case "openDeviceContactPicker": { - final boolean localizedLabels = call.argument("androidLocalizedLabels"); - openDeviceContactPicker(result, localizedLabels); + final boolean localizedLabels = call.argument("androidLocalizedLabels"); + openDeviceContactPicker(result, localizedLabels); break; } default: { result.notImplemented(); @@ -512,13 +510,13 @@ HashMap getContactByIdentifier(String identifier) { } private void openDeviceContactPicker(Result result, boolean localizedLabels) { - if (delegate != null) { - delegate.setResult(result); + if (delegate != null) { + delegate.setResult(result); delegate.setLocalizedLabels(localizedLabels); - delegate.openContactPicker(); - } else { - result.success(FORM_COULD_NOT_BE_OPEN); - } + delegate.openContactPicker(); + } else { + result.success(FORM_COULD_NOT_BE_OPEN); + } } private class ContactServiceDelegateOld extends BaseContactsServiceDelegate { @@ -998,18 +996,33 @@ private ArrayList getContactsFrom(Cursor cursor, boolean localizedLabel if (mimeType.equals(CommonDataKinds.Event.CONTENT_ITEM_TYPE)) { int eventType = cursor.getInt(cursor.getColumnIndex(CommonDataKinds.Event.TYPE)); if (eventType == CommonDataKinds.Event.TYPE_BIRTHDAY) { - contact.birthday = - cursor.getString(cursor.getColumnIndex(CommonDataKinds.Event.START_DATE)); + contact.birthday = cursor.getString(cursor.getColumnIndex(CommonDataKinds.Event.START_DATE)); } } } - if (cursor != null) cursor.close(); + if(cursor != null) + cursor.close(); return new ArrayList<>(map.values()); } - private void getAvatar(final Contact contact, final boolean highRes, final Result result) { + private void setAvatarDataForContactIfAvailable(Contact contact) { + Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Integer.parseInt(contact.identifier)); + Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); + Cursor avatarCursor = contentResolver.query(photoUri, + new String[] {ContactsContract.Contacts.Photo.PHOTO}, null, null, null); + if (avatarCursor != null && avatarCursor.moveToFirst()) { + byte[] avatar = avatarCursor.getBlob(0); + contact.avatar = avatar; + } + if (avatarCursor != null) { + avatarCursor.close(); + } + } + + private void getAvatar(final Contact contact, final boolean highRes, + final Result result) { new GetAvatarsTask(contact, highRes, contentResolver, result).executeOnExecutor(this.executor); } @@ -1110,18 +1123,18 @@ private boolean addContact(Contact contact){ .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone.value); - if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) { + if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM){ op.withValue( ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.BaseTypes.TYPE_CUSTOM ); op.withValue(ContactsContract.CommonDataKinds.Phone.LABEL, phone.label); - } else op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); + } else + op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); ops.add(op.build()); } //Emails for (Item email : contact.emails) { - op = - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(CommonDataKinds.Email.ADDRESS, email.value) @@ -1130,12 +1143,9 @@ private boolean addContact(Contact contact){ } //Postal addresses for (PostalAddress address : contact.postalAddresses) { - op = - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - .withValue( - ContactsContract.Data.MIMETYPE, - CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) + .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) .withValue(CommonDataKinds.StructuredPostal.TYPE, address.type) .withValue(CommonDataKinds.StructuredPostal.LABEL, address.label) .withValue(CommonDataKinds.StructuredPostal.STREET, address.street) @@ -1164,11 +1174,8 @@ private boolean addContact(Contact contact){ private boolean deleteContact(Contact contact){ ArrayList ops = new ArrayList<>(); - ops.add( - ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) - .withSelection( - ContactsContract.RawContacts.CONTACT_ID + "=?", - new String[] {String.valueOf(contact.identifier)}) + ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) + .withSelection(ContactsContract.RawContacts.CONTACT_ID + "=?", new String[] {String.valueOf(contact.identifier)}) .build()); try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); @@ -1184,97 +1191,41 @@ private boolean updateContact(Contact contact) { ContentProviderOperation.Builder op; // Drop all details about contact except name - op = - ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE - }); + op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE}); ops.add(op.build()); - op = - ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE - }); + op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{ String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}); ops.add(op.build()); - op = - ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE - }); + op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}); ops.add(op.build()); - op = - ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE - }); + op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}); ops.add(op.build()); - op = - ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE - }); + op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}); ops.add(op.build()); // Photo - op = - ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE - }); + op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}); ops.add(op.build()); // Update data (name) - op = - ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) - .withSelection( - ContactsContract.Data.CONTACT_ID - + "=? AND " - + ContactsContract.Data.MIMETYPE - + "=?", - new String[] { - String.valueOf(contact.identifier), - ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE - }) + op = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) + .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}) .withValue(StructuredName.GIVEN_NAME, contact.givenName) .withValue(StructuredName.MIDDLE_NAME, contact.middleName) .withValue(StructuredName.FAMILY_NAME, contact.familyName) @@ -1312,17 +1263,17 @@ private boolean updateContact(Contact contact) { .withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.identifier) .withValue(Phone.NUMBER, phone.value); - if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) { + if (phone.type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM){ op.withValue( ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.BaseTypes.TYPE_CUSTOM ); op.withValue(ContactsContract.CommonDataKinds.Phone.LABEL, phone.label); - } else op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); + } else + op.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phone.type); ops.add(op.build()); } for (Item email : contact.emails) { - op = - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.identifier) .withValue(CommonDataKinds.Email.ADDRESS, email.value) @@ -1331,11 +1282,8 @@ private boolean updateContact(Contact contact) { } for (PostalAddress address : contact.postalAddresses) { - op = - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) - .withValue( - ContactsContract.Data.MIMETYPE, - CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) + op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) + .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.identifier) .withValue(CommonDataKinds.StructuredPostal.TYPE, address.type) .withValue(CommonDataKinds.StructuredPostal.STREET, address.street) From ecf16a2abcdfd200763833ce22ce30fc70ef3e64 Mon Sep 17 00:00:00 2001 From: Zhen Qiu Date: Thu, 4 Feb 2021 17:32:33 -0800 Subject: [PATCH 3/5] format. --- .../ContactsServicePlugin.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java index 308d9e71..663922fe 100644 --- a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java +++ b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java @@ -138,7 +138,7 @@ public void onMethodCall(MethodCall call, Result result) { if (this.deleteContact(contact)) { result.success(null); } else { - result.error(null, "Failed to delete the contact, make sure it has a valid identifier", null); + result.error(null, "Failed to delete the contact, make sure it has a valid identifier", null); } break; } case "updateContact": { @@ -146,12 +146,12 @@ public void onMethodCall(MethodCall call, Result result) { if (this.updateContact(contact)) { result.success(null); } else { - result.error(null, "Failed to update the contact, make sure it has a valid identifier", null); + result.error(null, "Failed to update the contact, make sure it has a valid identifier", null); } break; } case "openExistingContact" :{ final Contact contact = Contact.fromMap((HashMap)call.argument("contact")); - final boolean localizedLabels = call.argument("androidLocalizedLabels"); + final boolean localizedLabels = call.argument("androidLocalizedLabels"); if (delegate != null) { delegate.setResult(result); delegate.setLocalizedLabels(localizedLabels); @@ -161,7 +161,7 @@ public void onMethodCall(MethodCall call, Result result) { } break; } case "openContactForm": { - final boolean localizedLabels = call.argument("androidLocalizedLabels"); + final boolean localizedLabels = call.argument("androidLocalizedLabels"); if (delegate != null) { delegate.setResult(result); delegate.setLocalizedLabels(localizedLabels); @@ -434,8 +434,7 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent intent) Cursor cursor = contentResolver.query(contactUri, null, null, null, null); if (cursor.moveToFirst()) { String id = contactUri.getLastPathSegment(); - getContacts( - "openDeviceContactPicker", id, false, false, false, localizedLabels, null, this.result); + getContacts("openDeviceContactPicker", id, false, false, false, localizedLabels, null, this.result); } else { Log.e(LOG_TAG, "onActivityResult - cursor.moveToFirst() returns false"); finishWithResult(FORM_OPERATION_CANCELED); @@ -1001,7 +1000,7 @@ private ArrayList getContactsFrom(Cursor cursor, boolean localizedLabel } } - if(cursor != null) + if(cursor != null) cursor.close(); return new ArrayList<>(map.values()); @@ -1175,7 +1174,7 @@ private boolean addContact(Contact contact){ private boolean deleteContact(Contact contact){ ArrayList ops = new ArrayList<>(); ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI) - .withSelection(ContactsContract.RawContacts.CONTACT_ID + "=?", new String[] {String.valueOf(contact.identifier)}) + .withSelection(ContactsContract.RawContacts.CONTACT_ID + "=?", new String[]{String.valueOf(contact.identifier)}) .build()); try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); @@ -1193,39 +1192,39 @@ private boolean updateContact(Contact contact) { // Drop all details about contact except name op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE}); + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE}); ops.add(op.build()); op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{ String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}); + new String[]{ String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}); ops.add(op.build()); op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}); + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}); ops.add(op.build()); op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}); + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}); ops.add(op.build()); op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}); + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}); ops.add(op.build()); // Photo op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}); + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}); ops.add(op.build()); // Update data (name) op = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}) + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}) .withValue(StructuredName.GIVEN_NAME, contact.givenName) .withValue(StructuredName.MIDDLE_NAME, contact.middleName) .withValue(StructuredName.FAMILY_NAME, contact.familyName) From 3d23da7b4eb3b7eb601f44b8a0738c03b58df337 Mon Sep 17 00:00:00 2001 From: Zhen Qiu Date: Thu, 4 Feb 2021 17:34:23 -0800 Subject: [PATCH 4/5] format. --- .../contactsservice/ContactsServicePlugin.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java index 663922fe..39ff612b 100644 --- a/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java +++ b/android/src/main/java/flutter/plugins/contactsservice/contactsservice/ContactsServicePlugin.java @@ -1197,16 +1197,16 @@ private boolean updateContact(Contact contact) { op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", - new String[]{ String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}); + new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}); ops.add(op.build()); op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + .withSelection(ContactsContract.Data.CONTACT_ID +"=? AND " + ContactsContract.Data.MIMETYPE + "=?", new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}); ops.add(op.build()); op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) - .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", + .withSelection(ContactsContract.Data.CONTACT_ID +"=? AND " + ContactsContract.Data.MIMETYPE + "=?", new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}); ops.add(op.build()); @@ -1215,7 +1215,7 @@ private boolean updateContact(Contact contact) { new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}); ops.add(op.build()); - // Photo + //Photo op = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", new String[]{String.valueOf(contact.identifier), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}); From cbaa276ede89e9930486c2c708b7f69ae43150e3 Mon Sep 17 00:00:00 2001 From: Zhen Qiu Date: Thu, 4 Feb 2021 17:36:36 -0800 Subject: [PATCH 5/5] format. --- lib/contacts_service.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/contacts_service.dart b/lib/contacts_service.dart index be62e871..cfd10f78 100644 --- a/lib/contacts_service.dart +++ b/lib/contacts_service.dart @@ -39,8 +39,8 @@ class ContactsService { ContactInfo.org, ContactInfo.location ]}) async { - List contactInfoStrings = contactInfos.map((info) => - info.toString()).toList(); + List contactInfoStrings = contactInfos.map((info) => + info.toString()).toList(); Iterable contacts = await _channel.invokeMethod('getContacts', { 'query': query,