Содержание
Для выполнения различных операций в Android наше приложение .NET MAUI должно взаимодействовать с другими приложениями. Например, для выбора контакта и набора телефонного номера наше приложение должно вначале открыть приложение «Контакты», чтобы пользователь выбрал необходимый контакт, а затем — открыть приложение «Телефон» с набранным номером контакта. В этой части мы рассмотрим как мы можем взаимодействовать с другими приложениями в Android на примере приложения .NET MAUI «Выбор контакта и набор телефонного номера».
Выбор контакта в Android. Интерфейс IContacts
Интерфейс IContacts
содержит методы для работы с контактами:
Метод | Описание |
public Task<IEnumerable<Contact>> GetAllAsync(CancellationToken cancellationToken = default); |
Возвращает список всех контактов на устройстве |
public Task<Contact?> PickContactAsync(); |
Открывает приложение Android по умолчанию для выбора контакта с устройства |
Реализация интерфейса по умолчанию содержится в свойстве Default
класса Contacts
. Воспользуемся этими методами в приложении .NET MAUI. Создадим новый проект с названием MauiPhone.
Определение необходимых разрешений
Для того, чтобы наше приложение могло считывать данные о контактах, необходимо запросить разрешение android.permission.READ_CONTACTS
одним из известных нам способов. Например, добавим в MauiApplication.cs атрибут сборки:
using Android.App; using Android.Runtime; [assembly: UsesPermission(Android.Manifest.Permission.ReadContacts)] namespace MauiPhone; [Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { } protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); }
Вывод списка контактов
Создадим в проекте новую папку ViewModels и добавим в неё класс ContactsViewModel
со следующим содержимым:
using System.Collections.ObjectModel; using System.Windows.Input; namespace MauiPhone.ViewModels { public class ContactsViewModel { public ObservableCollection<Contact> ContactList { get; set; } = []; public ICommand ReadContacts { get; set; } public ContactsViewModel() { ReadContacts = new Command(async () => { if (await CheckPermissionStatus() == PermissionStatus.Granted) { foreach (var contact in await Microsoft.Maui.ApplicationModel.Communication.Contacts.Default.GetAllAsync()) { ContactList.Add(contact); } } }); } public async Task<PermissionStatus> CheckPermissionStatus() { var currentStatus = await Permissions.CheckStatusAsync<Permissions.ContactsRead>(); if (currentStatus != PermissionStatus.Granted) { currentStatus = await Permissions.RequestAsync<Permissions.ContactsRead>(); } return currentStatus; } } }
Здесь мы определили свойство ContactList
, которое будет содержать список всех контактов
public ObservableCollection<Contact> ContactList { get; set; } = [];
а также команду ReadContacts
для получения списка контактов:
public ICommand ReadContacts { get; set; } ... ReadContacts = new Command(async () => { if (await CheckPermissionStatus() == PermissionStatus.Granted) { foreach (var contact in await Microsoft.Maui.ApplicationModel.Communication.Contacts.Default.GetAllAsync()) { ContactList.Add(contact); } } });
Здесь мы вначале проверяем статус разрешения на чтение контактов, используя метод CheckPermissionStatus()
:
public async Task<PermissionStatus> CheckPermissionStatus() { var currentStatus = await Permissions.CheckStatusAsync<Permissions.ContactsRead>(); if (currentStatus != PermissionStatus.Granted) { currentStatus = await Permissions.RequestAsync<Permissions.ContactsRead>(); } return currentStatus; }
и затем, если разрешение было получено, считываем список всех контактов на устройстве. Используем нашу модель представления на главной странице приложения. Вначале изменим код MainPage.xaml.cs, передав в качестве контекста модель представления:
using MauiPhone.ViewModels; namespace MauiPhone { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new ContactsViewModel(); } } }
Теперь изменим XAML-код страницы MainPage.xaml следующим образом:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MauiPhone.ViewModels" xmlns:model="clr-namespace:Microsoft.Maui.ApplicationModel.Communication;assembly=Microsoft.Maui.Essentials" x:Class="MauiPhone.MainPage" x:DataType="local:ContactsViewModel"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Button Text="Посмотреть контакты" Command="{Binding ReadContacts}" /> <Picker ItemsSource="{Binding ContactList, Mode=TwoWay}" ItemDisplayBinding="{Binding DisplayName}" /> </VerticalStackLayout> </ScrollView> </ContentPage>
Клик по кнопке запускает команду на получение всего списка контактов, которые после загрузки отобразятся в выпадающем списке Picker
. При этом, в списке мы будем отображать свойство DisplayName
контакта. Запустим приложение и посмотрим на результат:
При этом при первой попытке загрузки списка контактов, приложение попросит разрешение на доступ к контактам. С первой частью работы с контактами мы справились — научились загружать и показывать список контактов. Теперь необходимо научиться выбирать контакт и показывать по нему информацию
Выбор контакта из списка и отображение свойств контакта
Каждый элемент списка ContactList
нашей модели представления содержит объект типа Contact
. Класс Contact
предоставляет нам следующую информацию по контакту:
Свойство | Тип | Описание |
Id |
string |
Идентификатор контакта |
GivenName |
string |
Имя контакта |
MiddleName |
string |
Отчество контакта |
FamilyName |
string |
Фамилия контакта |
DisplayName |
string |
Отображаемое имя (Ф.И.О.) |
NamePrefix |
string |
Префикс имени контакта |
NameSuffix |
string |
Суффикс имени контакта |
Phones |
List<ContactPhone> |
Список телефонных номеров |
Emails |
List<ContactEmail> |
Список адресов Email |
Допишем модель представления следующим образом:
public class ContactsViewModel: INotifyPropertyChanged { public ObservableCollection<Contact> ContactList { get; set; } = []; private Contact selectedContact; public Contact SelectedContact { get => selectedContact; set { if (value != selectedContact) { selectedContact = value; OnPropertyChanged(); } } } private ContactPhone selectedPhone; public ContactPhone SelectedPhone { get => selectedPhone; set { if (value != selectedPhone) { selectedPhone = value; OnPropertyChanged(); } } } private ContactEmail selectedEmail; public ContactEmail SelectedEmail { get => selectedEmail; set { if (value != selectedEmail) { selectedEmail = value; OnPropertyChanged(); } } } public ICommand ReadContacts { get; set; } public ContactsViewModel() { ReadContacts = new Command(async () => { if (await CheckPermissionStatus() == PermissionStatus.Granted) { foreach (var contact in await Microsoft.Maui.ApplicationModel.Communication.Contacts.Default.GetAllAsync()) { ContactList.Add(contact); } if (ContactList.Count > 0) { SelectedContact = ContactList[0]; OnPropertyChanged(nameof(SelectedContact)); } } }); } public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged([CallerMemberName] string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } public async Task<PermissionStatus> CheckPermissionStatus() { var currentStatus = await Permissions.CheckStatusAsync<Permissions.ContactsRead>(); if (currentStatus != PermissionStatus.Granted) { currentStatus = await Permissions.RequestAsync<Permissions.ContactsRead>(); } return currentStatus; } }
Здесь мы добавили три новых свойства:
Выбранный контакт
private Contact selectedContact; public Contact SelectedContact { get => selectedContact; set { if (value != selectedContact) { selectedContact = value; OnPropertyChanged(); } } }
Выбранный у контакта номер телефона
private ContactPhone selectedPhone; public ContactPhone SelectedPhone { get => selectedPhone; set { if (value != selectedPhone) { selectedPhone = value; OnPropertyChanged(); } } }
Выбранный у контакта адрес Email
private ContactEmail selectedEmail; public ContactEmail SelectedEmail { get => selectedEmail; set { if (value != selectedEmail) { selectedEmail = value; OnPropertyChanged(); } } }
Для того, чтобы мы могли отслеживать изменения этих свойств, мы реализовали интерфейс INotifyPropertyChanged
.
public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged([CallerMemberName] string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); }
Теперь используем эти свойства для привязки. Изменим XAML-код страницы следующим образом:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MauiPhone.ViewModels" xmlns:model="clr-namespace:Microsoft.Maui.ApplicationModel.Communication;assembly=Microsoft.Maui.Essentials" x:Class="MauiPhone.MainPage" x:DataType="local:ContactsViewModel"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Button Text="Посмотреть контакты" Command="{Binding ReadContacts}" /> <Picker ItemsSource="{Binding ContactList, Mode=TwoWay}" ItemDisplayBinding="{Binding DisplayName}" SelectedItem="{Binding SelectedContact, Mode=TwoWay}"/> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Label Text="Отображаемое имя" Grid.Row="0" Grid.Column="0"/> <Label Text="Имя" Grid.Row="1" Grid.Column="0"/> <Label Text="Отчество" Grid.Row="2" Grid.Column="0"/> <Label Text="Фамилия" Grid.Row="3" Grid.Column="0"/> <Label Text="Список телефонов" Grid.Row="4" Grid.Column="0" VerticalOptions="Center"/> <Label Text="Список Email" Grid.Row="5" Grid.Column="0" VerticalOptions="Center"/> <Label Text="{Binding SelectedContact.DisplayName, Mode=TwoWay}" Grid.Row="0" Grid.Column="1" /> <Label Text="{Binding SelectedContact.GivenName, Mode=TwoWay}" Grid.Row="1" Grid.Column="1"/> <Label Text="{Binding SelectedContact.MiddleName, Mode=TwoWay}" Grid.Row="2" Grid.Column="1"/> <Label Text="{Binding SelectedContact.FamilyName, Mode=TwoWay}" Grid.Row="3" Grid.Column="1"/> <Picker ItemsSource="{Binding SelectedContact.Phones, Mode=TwoWay}" SelectedItem="{Binding SelectedPhone}" Grid.Row="4" Grid.Column="1"/> <Picker ItemsSource="{Binding SelectedContact.Emails, Mode=TwoWay}" SelectedItem="{Binding SelectedEmail}" Grid.Row="5" Grid.Column="1"/> </Grid> </VerticalStackLayout> </ScrollView> </ContentPage>
Здесь мы привязываем визуальные компоненты Label
и Picker
к свойствам контакта. Теперь при выборе контакта в первом списке мы должны увидеть основные свойства выбранного контакта.
Запустим приложение, загрузим список контактов и выберем какой-нибудь контакт в списке:

Если у контакта есть список телефонов или адресов электронной почты, то они отобразятся в соответствующих списках.
Выбор контакта методом PickContactAsync()
Если вам не требуется загружать весь список контактов в своё приложение, а достаточно просто открыть адресную книгу и выбрать в ней конкретный контакт, то можно воспользоваться методом PickContactAsync()
. Добавим в модель представления ещё одну команду:
public ICommand PickContact { get; set; } public ContactsViewModel() { PickContact = new Command(async () => { var contact = await Microsoft.Maui.ApplicationModel.Communication.Contacts.Default.PickContactAsync(); if (contact != null) { SelectedContact = contact; } }); ... }
Здесь мы вызываем метод PickContactAsync()
и, если результатом будет не null
, то выбранный контакт будет присвоен свойству SelectedContact
, что приведен к отображению свойств контакта в приложении.
Добавим на страницу MainPage
новую кнопку и сделаем необходимую привязку к команде:
<Button Text="Выбрать контакт из адресной книги" Command="{Binding PickContact}" />
Запустим приложение и проверим результат. При нажатии на кнопку «Выбрать контакт из адресной книги» операционная система предложит выбор приложения для контактов (если на устройстве таких приложений несколько):
После выбора, откроется соответствующее приложение с контактами. Если контакт будет выбран, то в приложении вы увидите его свойства также, как и на рисунке выше.
Итого
Для выбора контактов в Android используется интерфейс IContacts
, реализация по умолчанию которого содержится в свойстве Default
статического класса Contacts. При этом мы можем как загрузить весь список контактов в приложение, так и выбрать конкретный контакт, воспользовавшись методом PickContactAsync()