Aktywacja aplikacji systemowych
Interfejs programistyczny uniwersalnej platformy Windows 10 implementuje mechanizm komunikacji pomiędzy zainstalowanymi aplikacjami. Dzięki temu odpowiednio skonfigurowane aplikacje mogą aktywować się wzajemnie i wymieniać pomiędzy sobą dane. Możliwość ta zostanie zaprezentowana na przykładzie aktywacji systemowych funkcji do odczytywania kontaktów i wysyłania wiadomości tekstowych.
Mechanizm aktywacji aplikacji (opisany dokładnie w rozdziale 9) można wykorzystać do aktywowania funkcji i modułów systemowych w celu wykorzystania zaimplementowanych w nich funkcjonalności. Umożliwia to zatem rozszerzanie możliwości własnych aplikacji. W szczególności za pomocą aktywacji systemowych elementów można odczytać kontakty zapisane w pamięci urządzenia, wysłać wiadomość elektroniczną lub nawet wiadomość tekstową SMS. Funkcjonalności te zostaną zaimplementowane w ramach kolejnego przykładu. Jego realizacja obejmuje następujące etapy:
- Utwórz nowy projekt aplikacji pod nazwą WiadomosciTekstowe.
- Do deklaracji głównego widoku wykorzystaj polecenia z listingu 9.10.
- W pliku MainPage.xaml.cs wstaw polecenia z listingu 9.11.
- Przejdź do edycji manifestu aplikacji, a następnie na zakładce Capabilities zaznacz opcję Chat Message Access.
Listing 9.10. Deklaracja głównego widoku aplikacji WiadomosciTekstowe
<Page
x:Class="WiadomosciTekstowe.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WiadomosciTekstowe"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Thickness x:Key="DefaultMargin">10</Thickness>
<Style TargetType="Button">
<Setter Property="Margin"
Value="{StaticResource DefaultMargin}"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin"
Value="{StaticResource DefaultMargin}" />
</Style>
<Style TargetType="RichEditBox">
<Setter Property="Margin"
Value="{StaticResource DefaultMargin}" />
<Setter Property="VerticalContentAlignment"
Value="Top"/>
</Style>
<Style TargetType="ComboBox">
<Setter Property="Margin"
Value="{StaticResource DefaultMargin}" />
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
</Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="ButtonPickContact"
Content="Wybierz kontakt..."
Click="ButtonPickContact_Click" />
<TextBlock x:Name="TextBlockContactDisplayName"
Grid.Column="1" />
<TextBlock x:Name="TextBlockPhoneNumber"
Grid.Row="1"
Text="Wybierz numer: " />
<ComboBox x:Name="ComboBoxPhoneNumbers"
Grid.Row="1"
Grid.Column="2" />
<TextBlock Grid.Row="2"
Grid.ColumnSpan="2"
Text="Treść wiadomości:" />
<RichEditBox x:Name="RichEditBoxMessage"
Grid.Row="3"
Grid.ColumnSpan="2" />
<Button x:Name="ButtonComposeSms"
Content="Wyślij..."
Grid.Row="4"
Click="ButtonComposeSms_Click" />
</Grid>
</Page>
Listing 9.11. Pobieranie numerów telefonów dla wybranego kontaktu oraz wysyłanie wiadomości SMS
using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Chat;
using Windows.ApplicationModel.Contacts;
using Windows.UI.Popups;
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace WiadomosciTekstowe
{
public sealed partial class MainPage : Page
{
private ContactPicker contactPicker;
public MainPage()
{
InitializeComponent();
ConfigureContactPicker();
}
private void ConfigureContactPicker()
{
contactPicker = new ContactPicker();
contactPicker.SelectionMode = ContactSelectionMode.Fields;
contactPicker.DesiredFieldsWithContactFieldType.Add(ContactFieldType.PhoneNumber);
}
private async void ButtonPickContact_Click(object sender, RoutedEventArgs e)
{
Contact contact = await contactPicker.PickContactAsync();
if (contact != null)
{
TextBlockContactDisplayName.Text = contact.DisplayName;
ComboBoxPhoneNumbers.ItemsSource = contact.Phones;
ComboBoxPhoneNumbers.DisplayMemberPath = "Number";
}
}
private async Task<bool> IsSmsTransportAvailable()
{
bool isSmsTransportAvailable = false;
var transports = await ChatMessageManager.GetTransportsAsync();
if (transports.Count > 0)
{
isSmsTransportAvailable = true;
}
return isSmsTransportAvailable;
}
private async void ButtonComposeSms_Click(object sender, RoutedEventArgs e)
{
if (!await IsSmsTransportAvailable())
{
DisplayError("Funkcja nie jest dostępna");
}
else
{
await ComposeSmsMessage();
ClearForm();
}
}
private async void DisplayError(string message)
{
MessageDialog messageDialog = new MessageDialog(message);
await messageDialog.ShowAsync();
}
private async Task ComposeSmsMessage()
{
string phoneNumber = GetSelectedPhoneNumber();
if (string.IsNullOrEmpty(phoneNumber))
{
DisplayError("Podaj numer telefonu");
return;
}
string smsBody = GetSmsBody();
if (string.IsNullOrEmpty(smsBody))
{
DisplayError("Podaj treść wiadomości"); ;
return;
}
var chatMessage = new ChatMessage();
chatMessage.Recipients.Add(phoneNumber);
chatMessage.Body = smsBody;
await ChatMessageManager.ShowComposeSmsMessageAsync(chatMessage);
}
private string GetSelectedPhoneNumber()
{
string result = string.Empty;
ContactPhone contactPhone = ComboBoxPhoneNumbers.SelectedItem as ContactPhone;
if (contactPhone != null)
{
result = contactPhone.Number;
}
return result;
}
private string GetSmsBody()
{
string result = string.Empty;
RichEditBoxMessage.Document.GetText(TextGetOptions.None, out result);
return result;
}
private void ClearForm()
{
ComboBoxPhoneNumbers.ItemsSource = null;
RichEditBoxMessage.Document.SetText(TextSetOptions.None, string.Empty);
TextBlockContactDisplayName.Text = string.Empty;
}
}
}
Przykładowe działanie aplikacji WiadomosciTekstowe ilustruje rysunek 9.6. Aplikacja ta prezentuje wykorzystanie dwóch wbudowanych aplikacji (funkcji) systemowych w celu pobrania informacji o danych kontaktowych zapisanych w pamięci urządzenia oraz do wysłania wiadomości tekstowej SMS (short message service).
Rysunek 9.6. Przykład aktywacji wbudowanych aplikacji Windows 10
Pobieranie informacji o kontakcie realizuje się za pomocą klasy ContactPicker. Po utworzeniu instancji tej klasy należy ją odpowiednio skonfigurować. Należy bowiem ustalić tryb wyboru informacji o kontakcie (pole SelectionMode) oraz rodzaj pól, które mają zostać odczytane. W przykładzie listingu 9.11, metoda ConfigureContactPicker konfiguruje instancję klasy ContactPicker w taki sposób, aby możliwe było odczytywanie numerów telefonów. Do tego celu kolekcja DesiredFieldsWithContactFieldType jest uzupełniana o pole wartość PhoneNumber zapisaną w typie wyliczeniowym ContactFieldType. Ten ostatni jest zdefiniowany w przestrzeni nazw Windows.ApplicationModel.Contacts i udostępnia następujące wartości: Email, PhoneNumber, Location, InstantMessage, Custom, ConnectedServiceAccount, ImportantDate, Address, SignificantOther, Notes, Website oraz JobInfo. Wszystkie pola odpowiadające wartościom typu wyliczeniowego ContactFieldType można zatem odczytać za pomocą odpowiednio skonfigurowanej klasy ContactPicker.
Po uzyskaniu listy numerów telefonów skojarzonych z danym kontaktem jest ona wykorzystywana jako źródło danych dla kontrolki ComboBox. Umożliwia ona wybór docelowego telefonu, pod który zostanie wysłana wiadomość SMS. Aplikacja WiadomosciTekstowe nie wysyła wiadomości SMS bezpośrednio. Do tego celu wykorzystuje odpowiednią funkcję systemową, do której dostęp jest możliwy za pomocą asynchronicznej funkcji ShowComposeSmsMessageAsync klasy ChatMesageManager. Metoda ShowComposeSmsMessageAsync uaktywnia systemową funkcję umożliwiającą utworzenie i wysłanie wiadomości tekstowej. Dodatkowo metoda ShowComposeSmsMessageAsync umożliwia wskazanie adresatów wiadomości oraz jej treści. Realizuje się to za pomocą klasy ChatMessage. W szczególności ta klasa udostępnia pola Recipients oraz Body. Pierwsze reprezentuje listą odbiorców, a drugie pozwala skonfigurować treść wiadomości.
Metoda ShowComposeSmsMessageAsync działa prawidłowo wyłącznie na urządzeniach, wyposażonych w funkcję wysyłania wiadomości SMS, czyli telefonach i wybranych tabletach. Podczas próby wywołania funkcji ShowComposeSmsMessageAsync w trybie desktop zostanie zgłoszony wyjątek. Aby tego uniknąć wykorzystano metodę IsSmsTransportAvailable w celu sprawdzenia, czy urządzenie umożliwia wysyłanie wiadomości SMS. Definicja metody IsSmsTransportAvailable nie jest skomplikowana i ogranicza się do sprawdzenia liczby dostępnych obiektów typu ChatMessageTransport. Realizuje się to za pomocą funkcji GetTransportsAsync klasy ChatMessageManager.
W podobny sposób można również wysyłać wiadomości elektroniczne. Do tego celu służy metoda ShowComposeNewEmailAsync klasy EmailManager, zadeklarowanej w przestrzeni nazw Windows.ApplicationModel.Email. Z kolei abstrakcyjną reprezentacją wiadomości elektronicznych jest klasa EmailMessage. Zachęcam czytelnika do samodzielnego uzupełnienia aplikacji WiadomosciTekstowe o możliwość wysyłania wiadomości email.
Dawid Borycki