Запускатор
В этой статье описывается, как использовать интерфейс многоплатформенного приложения .NET (.NET MAUI) ILauncher. Этот интерфейс позволяет приложению открывать универсальный код ресурса (URI) системой. Этот метод открытия приложения часто используется при глубокой интеграции с пользовательскими схемами URI другого приложения.
Реализация интерфейса ILauncher
по умолчанию доступна через свойство Launcher.Default. Интерфейс ILauncher
и класс Launcher
содержатся в пространстве имен Microsoft.Maui.ApplicationModel
.
Это важно
Чтобы открыть браузер на веб-сайте, используйте вместо этого API браузера.
Начало работы
Для доступа к функциям средства запуска требуется следующая настройка для конкретной платформы.
Если вы хотите использовать глубокие ссылки для открытия других приложений Android, необходимо определить фильтр намерений в приложении. Это можно сделать, добавив следующий XML-файл в файл Platform/Android/AndroidManifest.xml:
<activity android:name="appName" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="lyft"/>
<data android:scheme="fb"/>
</intent-filter>
</activity>
Элементы <data>
— это предварительно зарегистрированные в приложении схемы URI. Нельзя использовать схемы, которые не определены в фильтре намерений.
Чтобы сделать приложение доступным для просмотра другими приложениями, объявите элемент <data>
с атрибутом android:scheme
:
<data android:scheme="appName"/>
Открытие другого приложения
Чтобы использовать функцию Launcher, вызовите метод ILauncher.OpenAsync и передайте String или Uri, представляющее приложение для открытия. При необходимости метод ILauncher.CanOpenAsync(Uri) можно использовать для проверки того, может ли схема URI обрабатываться приложением на устройстве. В следующем коде показано, как проверить, поддерживается ли схема URI, а затем открывает URI:
bool supportsUri = await Launcher.Default.CanOpenAsync("lyft://");
if (supportsUri)
await Launcher.Default.OpenAsync("lyft://ridetype?id=lyft_line");
Предыдущий пример кода можно упростить с помощью TryOpenAsync(Uri), который проверяет, можно ли открыть схему URI перед открытием:
bool launcherOpened = await Launcher.Default.TryOpenAsync("lyft://ridetype?id=lyft_line");
if (launcherOpened)
{
// Do something fun
}
Открытие другого приложения с помощью файла
Средство запуска также можно использовать для открытия приложения с выбранным файлом. .NET MAUI автоматически обнаруживает тип файла (MIME) и открывает приложение по умолчанию для этого типа файла. Если в типе файла зарегистрировано несколько приложений, отображается всплывающее окно выбора приложения пользователю.
В следующем примере кода записывается текст в файл и открывается текстовый файл с помощью средства запуска:
string popoverTitle = "Read text file";
string name = "File.txt";
string file = System.IO.Path.Combine(FileSystem.CacheDirectory, name);
System.IO.File.WriteAllText(file, "Hello World");
await Launcher.Default.OpenAsync(new OpenFileRequest(popoverTitle, new ReadOnlyFile(file)));
Управление расположениями файлов
Это важно
Этот раздел относится только к Android.
В некоторых сценариях на Android, например, если файл находится в частном хранилище, его можно скопировать в кэш приложения, который затем можно передать через Android FileProvider
. Однако это может непреднамеренно привести к тому, что весь кэш и данные приложений станут доступны злоумышленнику. Это можно предотвратить, добавив в приложение файл переопределения путей файлов поставщика и убедившись, что файлы копируются в указанное в этом файле расположение перед их обменом.
Чтобы добавить файл с переопределенными путями для поставщика файлов в ваше приложение, добавьте файл с именем microsoft_maui_essentials_fileprovider_file_paths.xml в папку Platforms\Android\Resources\xml в вашем приложении. Таким образом, полное относительное имя файла проекта должно быть Platforms\Android\Resources\xml\microsoft_maui_essentials_fileprovider_file_paths.xml. Затем добавьте XML в файл для требуемых путей:
<?xml version="1.0" encoding="UTF-8" ?>
<paths>
<external-path name="external_files" path="sharing-root" />
<cache-path name="internal_cache" path="sharing-root" />
<external-cache-path name="external_cache" path="sharing-root" />
</paths>
Дополнительные сведения о путях поставщика файлов см. в разделе FileProvider на developer.android.com.
Перед тем как предоставить доступ к файлу, необходимо сначала записать его в корневую папку для общего доступа в одном из путей из файла переопределений.
// Write into the specific sub-directory
var dir = Path.Combine(FileSystem.CacheDirectory, "sharing-root");
Directory.CreateDirectory(dir);
var file = Path.Combine(dir, "mydata.txt");
await File.WriteAllTextAsync(file, $"My data: {count}");
// Share the file
await Launcher.OpenAsync(new OpenFileRequest
{
Title = "My data",
File = new ReadOnlyFile(file),
});
Можно проверить правильность общего доступа к файлу, если общий URI исключает корневой каталог общего доступа. Например, если вы предоставляете общий доступ к файлу <CacheDirectory>/sharing-root/mydata.txt, а общий URI content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/sharing-root/mydata.txt
, то поставщик файлов не использует правильный путь. Если предоставленный URI content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/mydata.txt
, это значит, что поставщик файлов использует правильный путь.
Предупреждение
Если при совместном использовании файла вы получаете Java.Lang.IllegalArgumentException
с сообщением "Не удалось найти настроенный корень, содержащий /data/data/com.companyname.overwritefileproviderpaths/cache/some-non-sharing-path/mydata.txt", вы, скорее всего, предоставляете общий доступ к файлу, который находится за пределами корневого корня общего доступа.
Установка расположения средства запуска
Это важно
Этот раздел относится только к iPadOS.
При запросе или открытии программы запуска на iPadOS, это можно представить во всплывающем окне. Это указывает, где появится всплывающее окно и наведите стрелку непосредственно на нее. Это расположение часто является элементом управления, запускающим действие. Расположение можно указать с помощью свойства PresentationSourceBounds:
await Share.RequestAsync(new ShareFileRequest
{
Title = Title,
File = new ShareFile(file),
PresentationSourceBounds = DeviceInfo.Platform == DevicePlatform.iOS && DeviceInfo.Idiom == DeviceIdiom.Tablet
? new Rect(0, 20, 0, 0)
: Rect.Zero
});
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(file),
PresentationSourceBounds = DeviceInfo.Platform == DevicePlatform.iOS && DeviceInfo.Idiom == DeviceIdiom.Tablet
? new Rect(0, 20, 0, 0)
: Rect.Zero
});
Все описанное здесь работает одинаково для Share и Launcher.
Ниже приведен метод расширения, который помогает вычислить границы представления:
public static class ViewHelpers
{
public static Rect GetAbsoluteBounds(this Microsoft.Maui.Controls.View element)
{
Element looper = element;
var absoluteX = element.X + element.Margin.Top;
var absoluteY = element.Y + element.Margin.Left;
// Add logic to handle titles, headers, or other non-view bars
while (looper.Parent != null)
{
looper = looper.Parent;
if (looper is Microsoft.Maui.Controls.View v)
{
absoluteX += v.X + v.Margin.Top;
absoluteY += v.Y + v.Margin.Left;
}
}
return new Rect(absoluteX, absoluteY, element.Width, element.Height);
}
}
Затем это можно использовать при вызове RequestAsync:
public Command<Microsoft.Maui.Controls.View> ShareCommand { get; } = new Command<Microsoft.Maui.Controls.View>(Share);
async void Share(Microsoft.Maui.Controls.View element)
{
try
{
await Share.Default.RequestAsync(new ShareTextRequest
{
PresentationSourceBounds = element.GetAbsoluteBounds(),
Title = "Title",
Text = "Text"
});
}
catch (Exception)
{
// Handle exception that share failed
}
}
При срабатывании Command
вы можете передать элемент вызова:
<Button Text="Share"
Command="{Binding ShareWithFriendsCommand}"
CommandParameter="{Binding Source={RelativeSource Self}}"/>
Пример класса ViewHelpers
см. в примере .NET MAUI, размещенном наGitHub.
Различия платформ
В этом разделе описываются различия в API запуска, зависящие от платформы.
Task, возвращенный из CanOpenAsync, завершается сразу.