Содержание
Набор телефонного номера на устройстве Android в .NET MAUI тесно связан с работой с контактами, которую мы изучали в предыдущей части. Поэтому логично будет продолжить работу над нашим приложением, тем более, что там мы уже научились выбирать контакт и получать список его телефонных номеров.
Приложение для выбора контакта (из предыдущей части)
Для начала повторим код приложения, которое было разработано в предыдущей части. Структура проекта выглядит следующим образом:
Для получения разрешения на чтение контактов мы добавили атрибут сборки:
[assembly: UsesPermission(Android.Manifest.Permission.ReadContacts)]
Код модели представления ContactsViewModel
:
using System.Collections.ObjectModel; using System.Windows.Input; using System.ComponentModel; using System.Runtime.CompilerServices; namespace MauiPhone.ViewModels { 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 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; } }); 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; } } }
Код C# страницы MainPage:
using MauiPhone.ViewModels; namespace MauiPhone { public partial class MainPage : ContentPage { public MainPage() { BindingContext = new ContactsViewModel(); InitializeComponent(); } } }
И, наконец, код XAML станицы MainPage:
<?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}" /> <Button Text="Выбрать контакт из адрекной книги" Command="{Binding PickContact}" /> <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>
Наше приложение загружает список контактов с устройства Android, а также позволяет выбрать контакт, используя одно из приложений для работы с контактами, установленное на устройстве. Теперь мы доработаем наше приложение таким образом, чтобы мы могли набирать в телефоне выбранный номер контакта.
Интерфейс IPhoneDialer
Для набора телефонного номера в .NET MAUI используется интерфейс IPhoneDialer
. Этот интерфейс довольно простой и предоставляет нам всего одно свойство:
public bool IsSupported { get; }
определяющее доступен ли набор номера на устройстве. И один метод:
public void Open(string number);
собственно, и открывающий приложение телефона с набранным номером, который указывается в параметре метода.
Как и в большинстве случаев, реализация по умолчанию этого интерфейса доступна через свойство Default
одноименного класса PhoneDialer
. Допишем наше приложение, чтобы мы могли набирать телефонный номер для выбранного контакта.
Набор телефонного номера
Изменение манифеста приложения
Для того, чтобы наше приложение могло взаимодействовать с другими приложениями на устройстве, а именно с приложением для совершения телефонных звонков, нам необходимо добавить в манифест приложения требования к видимости пакета. Для этого откройте файл Platforms/Android/AndroidManifest.xml, используя текстовый редактор — кликните правой кнопкой мыши по файлу и выберите в меню пункт «Открыть с помощью…»и в открывшемся окне выберите, например, вот такой редактор:
Откроется обычный текстовый редактор XAML-файла:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
здесь уже содержатся разрешения приложения, добавленные .NET MAUI по умолчанию. Измените файл следующим образом:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <queries> <intent> <action android:name="android.intent.action.DIAL" /> <data android:scheme="tel"/> </intent> </queries> </manifest>
Теперь наше приложение сможет совершать звонки, используя приложения для набора номера абонента.
Команда набора телефонного номера
Теперь перейдем к модели представления ContactsViewModel
и добавим в неё ещё одну команду:
public class ContactsViewModel: INotifyPropertyChanged { ... public ICommand CallCommand { get; set; } public ContactsViewModel() { CallCommand = new Command(() => { if (PhoneDialer.Default.IsSupported) { if (SelectedPhone != null) PhoneDialer.Default.Open(SelectedPhone.PhoneNumber); } }); ... } ... }
здесь мы проверяем поддерживается ли набор номера на устройстве и выбран ли какой-либо номер в приложении и, если оба условия возвращают true
, то открываем приложение для набора номера с уже набранным номером телефона.
Добавим новую кнопку на страницу MainPage:
<?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 CallCommand}" /> </VerticalStackLayout> </ScrollView> </ContentPage>
Теперь можно запустить приложение и проверить его работу. Приложение сразу после запуска:
Теперь, если загрузите контакты или выберите контакт из телефонной книги, а затем выберите телефонный номер в списке телефонов. Например,
Нажмите «Набрать номер». Откроется приложение «Телефон» с уже набранным номером:
Итого
Набор телефонного номера в .NET MAUI осуществляется с использованием интерфейса IPhoneDialer
. Реализация по умолчанию для этого интерфейса содержится в свойстве Default статического класса PhoneDialer
. Приложение .NET MAUI, использующее набор телефонного номера должно определять в манифесте приложения специальный XML-узел <query>
для того, чтобы взаимодействовать с другими приложениями для телефонных звонков на устройстве.