Error reading contacts in Xamarin Forms using Xamarin.Mobile

221 Views Asked by At

I am getting the below error while looping through the contacts in Xamarin.Forms android project

"Expression of type 'System.Collections.Generic.IEnumerable1[Xamarin.Contacts.Contact]' cannot be used for return type 'System.Linq.IQueryable1[Xamarin.Contacts.Contact]'"

Interestingly I found the same error in bugzilla, but no resolution is mentioned.

Could someone please help me in fixing the error

https://bugzilla.xamarin.com/show_bug.cgi?id=35244

Below is the method:

    public async Task<IEnumerable<MobileUserContact>> All()
    {

        if (_contacts != null) return _contacts;

        var contacts = new List<MobileUserContact>();

        try
        {
            if (!await _book.RequestPermission())
            {
                Console.WriteLine("Permission denied");
                return;
            }

            foreach (Contact contact in _book.OrderBy(c => c.LastName))
            {
                Console.WriteLine("{0} {1}", contact.FirstName, contact.LastName);
                contacts.Add(new MobileUserContact(contact.FirstName, contact.LastName, ""));
            }

            return contacts;
        }
        catch (Exception ex)
        {

            throw;
        }
    }

it is using Xamarin.Mobile 0.7.1.0 version dll

I have enabled Read_Contacts permission

1

There are 1 best solutions below

0
On BEST ANSWER

If this is a Xamarin.Mobile package issue, maybe you can submit an issue here. Here I cannot fix this error but can only suggest two workarounds not using this Xamarin.Mobile package to get Contacts.

  1. You can try to use ContactsPlugin for Xamarin and Windows to get contacts.

And your MobileUserContact should be a class when you code like this var contacts = new List<MobileUserContact>();, but you use it like a method here: contacts.Add(new MobileUserContact(contact.FirstName, contact.LastName, ""));.

Anyway, I created a demo tried to reproduce your issue, the following code works fine by my side:

public List<MobileUserContact> contacts;
public async Task<IEnumerable<MobileUserContact>> All()
{
    contacts = new List<MobileUserContact>();
    try
    {
        if (!await CrossContacts.Current.RequestPermission())
        {
            return null;
        }

        foreach (var contact in CrossContacts.Current.Contacts.ToList())
        {
            contacts.Add(new MobileUserContact
            {
                FirstName = contact.FirstName,
                LastName = contact.LastName
            });
        }
        return contacts;
    }
    catch (Exception ex)
    {
        throw;
    }
}

MobileUserContact class is simple here:

public class MobileUserContact
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Besides the READ_CONTACTS permission, we also need to pay attention that this plugin only targets API 23+ and compile against API 23+ for Android platform.

The advantage uses this package is that all codes can be placed in PCL, but this package is Currently in Alpha and not fully supported at this time.

  1. Another method is to use DependencyService and use the native API of Android platform to get contacts.

The code in native Android project can be for example like this:

var cursor = Android.App.Application.Context.ContentResolver.Query(Phone.ContentUri, null, null, null, null);
contacts = new List<MobileUserContact>();
while (cursor.MoveToNext())
{
    contacts.Add(new MobileUserContact
    {
        FirstName = cursor.GetString(cursor.GetColumnIndex(Phone.InterfaceConsts.DisplayName)),
        Num = cursor.GetString(cursor.GetColumnIndex(Phone.Number))
    });
}