Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

Commit

Permalink
[Contacts][Android] Changes to display of contacts list on ContactPic…
Browse files Browse the repository at this point in the history
…ker (#1600)

* Fixes #1559 (contacts picker are presented in a list without showing any individual numbers)
* Update the MSBuild.Sdk.Extras

Co-authored-by: Matthew Leibowitz <mattleibow@live.com>
  • Loading branch information
dimonovdd and mattleibow committed Dec 25, 2020
1 parent d901c07 commit 5b00532
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 65 deletions.
2 changes: 1 addition & 1 deletion DeviceTests/DeviceTests.Shared/DeviceTests.Shared.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
<Project Sdk="MSBuild.Sdk.Extras/3.0.22">
<PropertyGroup>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">Xamarin.iOS10;MonoAndroid90;uap10.0.16299</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">Xamarin.iOS10;MonoAndroid90;</TargetFrameworks>
Expand Down
124 changes: 61 additions & 63 deletions Xamarin.Essentials/Contacts/Contacts.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,31 @@
using Android.Content;
using Android.Database;
using Android.Provider;
using CommonDataKinds = Android.Provider.ContactsContract.CommonDataKinds;
using StructuredName = Android.Provider.ContactsContract.CommonDataKinds.StructuredName;

namespace Xamarin.Essentials
{
public static partial class Contacts
{
const string idCol = ContactsContract.Contacts.InterfaceConsts.Id;
const string displayNameCol = ContactsContract.Contacts.InterfaceConsts.DisplayName;
const string mimetypeCol = ContactsContract.Data.InterfaceConsts.Mimetype;

const string contactIdCol = CommonDataKinds.Phone.InterfaceConsts.ContactId;

static async Task<Contact> PlatformPickContactAsync()
{
var intent = new Intent(Intent.ActionPick);
intent.SetType(ContactsContract.CommonDataKinds.Phone.ContentType);

var intent = new Intent(Intent.ActionPick, ContactsContract.Contacts.ContentUri);
var result = await IntermediateActivity.StartAsync(intent, Platform.requestCodePickContact).ConfigureAwait(false);
if (result?.Data == null)
return null;

if (result?.Data != null)
return GetContact(result.Data);
using var cursor = Platform.ContentResolver.Query(result?.Data, null, null, null, null);
if (cursor?.MoveToFirst() != true)
return null;

return null;
return GetContact(cursor);
}

static Task<IEnumerable<Contact>> PlatformGetAllAsync(CancellationToken cancellationToken)
Expand All @@ -30,106 +39,95 @@ static Task<IEnumerable<Contact>> PlatformGetAllAsync(CancellationToken cancella

IEnumerable<Contact> GetEnumerable()
{
if (cursor?.MoveToFirst() ?? false)
if (cursor?.MoveToFirst() == true)
{
do
{
var contact = GetContact(cursor, ContactsContract.Contacts.InterfaceConsts.Id);
var contact = GetContact(cursor);
if (contact != null)
yield return contact;
}
while (cursor.MoveToNext());
}

cursor.Close();
cursor?.Close();
}
}

internal static Contact GetContact(global::Android.Net.Uri contactUri)
static Contact GetContact(ICursor cursor)
{
if (contactUri == null)
return default;

using var cursor = Platform.ContentResolver.Query(contactUri, null, null, null, null);
var id = GetString(cursor, idCol);
var displayName = GetString(cursor, displayNameCol);
var phones = GetNumbers(id)?.Select(p => new ContactPhone(p));
var emails = GetEmails(id)?.Select(e => new ContactEmail(e));
var (prefix, given, middle, family, suffix) = GetName(id);

if (cursor.MoveToFirst())
{
return GetContact(
cursor,
ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId);
}

return default;
return new Contact(id, prefix, given, middle, family, suffix, phones, emails, displayName);
}

static Contact GetContact(ICursor cursor, string idKey)
static IEnumerable<string> GetNumbers(string id)
{
var displayName = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.DisplayName));
var idQ = new string[1] { cursor.GetString(cursor.GetColumnIndex(idKey)) };
var phones = GetNumbers(idQ)?.Select(
item => new ContactPhone(item.data));
var emails = GetEmails(idQ)?.Select(
item => new ContactEmail(item.data));
var name = GetName(idQ[0]);

return new Contact(idQ[0], name.Prefix, name.Given, name.Middle, name.Family, name.Suffix, phones, emails, displayName);
}
var uri = CommonDataKinds.Phone.ContentUri
.BuildUpon()
.AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1")
.Build();

static IEnumerable<(string data, string type)> GetNumbers(string[] idQ)
{
var uri = ContactsContract.CommonDataKinds.Phone.ContentUri.BuildUpon().AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1").Build();
var cursor = Platform.ContentResolver.Query(uri, null, $"{ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId}=?", idQ, null);
var cursor = Platform.ContentResolver.Query(uri, null, $"{contactIdCol}=?", new[] { id }, null);

return ReadCursorItems(cursor, ContactsContract.CommonDataKinds.Phone.Number, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type);
return ReadCursorItems(cursor, CommonDataKinds.Phone.Number);
}

static IEnumerable<(string data, string type)> GetEmails(string[] idQ)
static IEnumerable<string> GetEmails(string id)
{
var uri = ContactsContract.CommonDataKinds.Email.ContentUri.BuildUpon().AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1").Build();
var cursor = Platform.ContentResolver.Query(uri, null, $"{ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId}=?", idQ, null);
var uri = CommonDataKinds.Email.ContentUri
.BuildUpon()
.AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1")
.Build();

var cursor = Platform.ContentResolver.Query(uri, null, $"{contactIdCol}=?", new[] { id }, null);

return ReadCursorItems(cursor, ContactsContract.CommonDataKinds.Email.Address, ContactsContract.CommonDataKinds.Email.InterfaceConsts.Type);
return ReadCursorItems(cursor, CommonDataKinds.Email.Address);
}

static IEnumerable<(string data, string type)> ReadCursorItems(ICursor cursor, string dataKey, string typeKey)
static IEnumerable<string> ReadCursorItems(ICursor cursor, string dataKey)
{
if (cursor?.MoveToFirst() ?? false)
if (cursor?.MoveToFirst() == true)
{
do
{
var data = cursor.GetString(cursor.GetColumnIndex(dataKey));
var type = cursor.GetString(cursor.GetColumnIndex(typeKey));

var data = GetString(cursor, dataKey);
if (data != null)
yield return (data, type);
yield return data;
}
while (cursor.MoveToNext());
}
cursor?.Close();
}

static (string Prefix, string Given, string Middle, string Family, string Suffix) GetName(string idQ)
static (string Prefix, string Given, string Middle, string Family, string Suffix) GetName(string id)
{
var whereNameParams = new string[] { ContactsContract.CommonDataKinds.StructuredName.ContentItemType };
var whereName = $"{ContactsContract.Data.InterfaceConsts.Mimetype} = ? AND {ContactsContract.CommonDataKinds.StructuredName.InterfaceConsts.ContactId} = {idQ}";
var selection = $"{mimetypeCol}=? AND {contactIdCol}=?";
var selectionArgs = new string[] { StructuredName.ContentItemType, id };

using var cursor = Platform.ContentResolver.Query(
ContactsContract.Data.ContentUri,
null,
whereName,
whereNameParams,
selection,
selectionArgs,
null);

if (cursor?.MoveToFirst() ?? false)
{
return (
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.Prefix)),
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GivenName)),
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MiddleName)),
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FamilyName)),
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.Suffix)));
}
if (cursor?.MoveToFirst() != true)
return (null, null, null, null, null);

return (null, null, null, null, null);
return (
GetString(cursor, StructuredName.Prefix),
GetString(cursor, StructuredName.GivenName),
GetString(cursor, StructuredName.MiddleName),
GetString(cursor, StructuredName.FamilyName),
GetString(cursor, StructuredName.Suffix));
}

static string GetString(ICursor cursor, string column) =>
cursor.GetString(cursor.GetColumnIndex(column));
}
}
2 changes: 1 addition & 1 deletion Xamarin.Essentials/Xamarin.Essentials.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
<Project Sdk="MSBuild.Sdk.Extras/3.0.22">
<PropertyGroup>
<TargetFrameworks>netstandard1.0;netstandard2.0;Xamarin.iOS10;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid80;MonoAndroid81;MonoAndroid90;MonoAndroid10.0;tizen40;Xamarin.Mac20;</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);uap10.0.16299;</TargetFrameworks>
Expand Down

0 comments on commit 5b00532

Please sign in to comment.