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

Commit 5b00532

Browse files
[Contacts][Android] Changes to display of contacts list on ContactPicker (#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 <[email protected]>
1 parent d901c07 commit 5b00532

File tree

3 files changed

+63
-65
lines changed

3 files changed

+63
-65
lines changed

DeviceTests/DeviceTests.Shared/DeviceTests.Shared.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
1+
<Project Sdk="MSBuild.Sdk.Extras/3.0.22">
22
<PropertyGroup>
33
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">Xamarin.iOS10;MonoAndroid90;uap10.0.16299</TargetFrameworks>
44
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">Xamarin.iOS10;MonoAndroid90;</TargetFrameworks>

Xamarin.Essentials/Contacts/Contacts.android.cs

Lines changed: 61 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,31 @@
55
using Android.Content;
66
using Android.Database;
77
using Android.Provider;
8+
using CommonDataKinds = Android.Provider.ContactsContract.CommonDataKinds;
9+
using StructuredName = Android.Provider.ContactsContract.CommonDataKinds.StructuredName;
810

911
namespace Xamarin.Essentials
1012
{
1113
public static partial class Contacts
1214
{
15+
const string idCol = ContactsContract.Contacts.InterfaceConsts.Id;
16+
const string displayNameCol = ContactsContract.Contacts.InterfaceConsts.DisplayName;
17+
const string mimetypeCol = ContactsContract.Data.InterfaceConsts.Mimetype;
18+
19+
const string contactIdCol = CommonDataKinds.Phone.InterfaceConsts.ContactId;
20+
1321
static async Task<Contact> PlatformPickContactAsync()
1422
{
15-
var intent = new Intent(Intent.ActionPick);
16-
intent.SetType(ContactsContract.CommonDataKinds.Phone.ContentType);
17-
23+
var intent = new Intent(Intent.ActionPick, ContactsContract.Contacts.ContentUri);
1824
var result = await IntermediateActivity.StartAsync(intent, Platform.requestCodePickContact).ConfigureAwait(false);
25+
if (result?.Data == null)
26+
return null;
1927

20-
if (result?.Data != null)
21-
return GetContact(result.Data);
28+
using var cursor = Platform.ContentResolver.Query(result?.Data, null, null, null, null);
29+
if (cursor?.MoveToFirst() != true)
30+
return null;
2231

23-
return null;
32+
return GetContact(cursor);
2433
}
2534

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

3140
IEnumerable<Contact> GetEnumerable()
3241
{
33-
if (cursor?.MoveToFirst() ?? false)
42+
if (cursor?.MoveToFirst() == true)
3443
{
3544
do
3645
{
37-
var contact = GetContact(cursor, ContactsContract.Contacts.InterfaceConsts.Id);
46+
var contact = GetContact(cursor);
3847
if (contact != null)
3948
yield return contact;
4049
}
4150
while (cursor.MoveToNext());
4251
}
4352

44-
cursor.Close();
53+
cursor?.Close();
4554
}
4655
}
4756

48-
internal static Contact GetContact(global::Android.Net.Uri contactUri)
57+
static Contact GetContact(ICursor cursor)
4958
{
50-
if (contactUri == null)
51-
return default;
52-
53-
using var cursor = Platform.ContentResolver.Query(contactUri, null, null, null, null);
59+
var id = GetString(cursor, idCol);
60+
var displayName = GetString(cursor, displayNameCol);
61+
var phones = GetNumbers(id)?.Select(p => new ContactPhone(p));
62+
var emails = GetEmails(id)?.Select(e => new ContactEmail(e));
63+
var (prefix, given, middle, family, suffix) = GetName(id);
5464

55-
if (cursor.MoveToFirst())
56-
{
57-
return GetContact(
58-
cursor,
59-
ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId);
60-
}
61-
62-
return default;
65+
return new Contact(id, prefix, given, middle, family, suffix, phones, emails, displayName);
6366
}
6467

65-
static Contact GetContact(ICursor cursor, string idKey)
68+
static IEnumerable<string> GetNumbers(string id)
6669
{
67-
var displayName = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.DisplayName));
68-
var idQ = new string[1] { cursor.GetString(cursor.GetColumnIndex(idKey)) };
69-
var phones = GetNumbers(idQ)?.Select(
70-
item => new ContactPhone(item.data));
71-
var emails = GetEmails(idQ)?.Select(
72-
item => new ContactEmail(item.data));
73-
var name = GetName(idQ[0]);
74-
75-
return new Contact(idQ[0], name.Prefix, name.Given, name.Middle, name.Family, name.Suffix, phones, emails, displayName);
76-
}
70+
var uri = CommonDataKinds.Phone.ContentUri
71+
.BuildUpon()
72+
.AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1")
73+
.Build();
7774

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

83-
return ReadCursorItems(cursor, ContactsContract.CommonDataKinds.Phone.Number, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type);
77+
return ReadCursorItems(cursor, CommonDataKinds.Phone.Number);
8478
}
8579

86-
static IEnumerable<(string data, string type)> GetEmails(string[] idQ)
80+
static IEnumerable<string> GetEmails(string id)
8781
{
88-
var uri = ContactsContract.CommonDataKinds.Email.ContentUri.BuildUpon().AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1").Build();
89-
var cursor = Platform.ContentResolver.Query(uri, null, $"{ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId}=?", idQ, null);
82+
var uri = CommonDataKinds.Email.ContentUri
83+
.BuildUpon()
84+
.AppendQueryParameter(ContactsContract.RemoveDuplicateEntries, "1")
85+
.Build();
86+
87+
var cursor = Platform.ContentResolver.Query(uri, null, $"{contactIdCol}=?", new[] { id }, null);
9088

91-
return ReadCursorItems(cursor, ContactsContract.CommonDataKinds.Email.Address, ContactsContract.CommonDataKinds.Email.InterfaceConsts.Type);
89+
return ReadCursorItems(cursor, CommonDataKinds.Email.Address);
9290
}
9391

94-
static IEnumerable<(string data, string type)> ReadCursorItems(ICursor cursor, string dataKey, string typeKey)
92+
static IEnumerable<string> ReadCursorItems(ICursor cursor, string dataKey)
9593
{
96-
if (cursor?.MoveToFirst() ?? false)
94+
if (cursor?.MoveToFirst() == true)
9795
{
9896
do
9997
{
100-
var data = cursor.GetString(cursor.GetColumnIndex(dataKey));
101-
var type = cursor.GetString(cursor.GetColumnIndex(typeKey));
102-
98+
var data = GetString(cursor, dataKey);
10399
if (data != null)
104-
yield return (data, type);
100+
yield return data;
105101
}
106102
while (cursor.MoveToNext());
107103
}
108104
cursor?.Close();
109105
}
110106

111-
static (string Prefix, string Given, string Middle, string Family, string Suffix) GetName(string idQ)
107+
static (string Prefix, string Given, string Middle, string Family, string Suffix) GetName(string id)
112108
{
113-
var whereNameParams = new string[] { ContactsContract.CommonDataKinds.StructuredName.ContentItemType };
114-
var whereName = $"{ContactsContract.Data.InterfaceConsts.Mimetype} = ? AND {ContactsContract.CommonDataKinds.StructuredName.InterfaceConsts.ContactId} = {idQ}";
109+
var selection = $"{mimetypeCol}=? AND {contactIdCol}=?";
110+
var selectionArgs = new string[] { StructuredName.ContentItemType, id };
111+
115112
using var cursor = Platform.ContentResolver.Query(
116113
ContactsContract.Data.ContentUri,
117114
null,
118-
whereName,
119-
whereNameParams,
115+
selection,
116+
selectionArgs,
120117
null);
121118

122-
if (cursor?.MoveToFirst() ?? false)
123-
{
124-
return (
125-
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.Prefix)),
126-
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GivenName)),
127-
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MiddleName)),
128-
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FamilyName)),
129-
cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.StructuredName.Suffix)));
130-
}
119+
if (cursor?.MoveToFirst() != true)
120+
return (null, null, null, null, null);
131121

132-
return (null, null, null, null, null);
122+
return (
123+
GetString(cursor, StructuredName.Prefix),
124+
GetString(cursor, StructuredName.GivenName),
125+
GetString(cursor, StructuredName.MiddleName),
126+
GetString(cursor, StructuredName.FamilyName),
127+
GetString(cursor, StructuredName.Suffix));
133128
}
129+
130+
static string GetString(ICursor cursor, string column) =>
131+
cursor.GetString(cursor.GetColumnIndex(column));
134132
}
135133
}

Xamarin.Essentials/Xamarin.Essentials.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
1+
<Project Sdk="MSBuild.Sdk.Extras/3.0.22">
22
<PropertyGroup>
33
<TargetFrameworks>netstandard1.0;netstandard2.0;Xamarin.iOS10;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid80;MonoAndroid81;MonoAndroid90;MonoAndroid10.0;tizen40;Xamarin.Mac20;</TargetFrameworks>
44
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);uap10.0.16299;</TargetFrameworks>

0 commit comments

Comments
 (0)