Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo se describe cómo puedes utilizar la interfaz ILauncher de .NET Multi-platform App UI (.NET MAUI). Esta interfaz permite a una aplicación abrir un URI por el sistema. Esta forma de abrir una aplicación se suele usar cuando se vincula profundamente a esquemas de URI personalizados de otra aplicación.
La implementación predeterminada de la interfaz ILauncher
está disponible a través de la propiedad Launcher.Default. Tanto la interfaz ILauncher
como la clase Launcher
se encuentran en el espacio de nombres Microsoft.Maui.ApplicationModel
.
Importante
Para abrir el navegador en un sitio web, use la API Browser en su lugar.
Comenzar
Para acceder a la funcionalidad del iniciador, se requiere la siguiente configuración específica de la plataforma.
Si desea usar vínculos profundos para abrir otras aplicaciones android, debe definir un filtro de intención en la aplicación. Esto se puede lograr agregando el siguiente XML al archivo Platforms/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>
Los elementos <data>
son los esquemas de URI previamente registrados con la aplicación. No puede usar esquemas que no estén definidos en el filtro de intención.
Para que la aplicación se pueda examinar desde otras aplicaciones, declare un elemento <data>
con el atributo android:scheme
:
<data android:scheme="appName"/>
Abrir otra aplicación
Para usar la funcionalidad Launcher, llame al método ILauncher.OpenAsync y pase un String o Uri que represente la aplicación para abrirla. Opcionalmente, se puede usar el método ILauncher.CanOpenAsync(Uri) para comprobar si una aplicación en el dispositivo puede manejar el esquema de URI. En el código siguiente se muestra cómo comprobar si se admite o no un esquema de URI y, a continuación, se abre el URI:
bool supportsUri = await Launcher.Default.CanOpenAsync("lyft://");
if (supportsUri)
await Launcher.Default.OpenAsync("lyft://ridetype?id=lyft_line");
El ejemplo de código anterior se puede simplificar mediante el TryOpenAsync(Uri), que comprueba si se puede abrir el esquema de URI antes de abrirlo:
bool launcherOpened = await Launcher.Default.TryOpenAsync("lyft://ridetype?id=lyft_line");
if (launcherOpened)
{
// Do something fun
}
Abrir otra aplicación a través de un archivo
El iniciador también se puede usar para abrir una aplicación con un archivo seleccionado. .NET MAUI detecta automáticamente el tipo de archivo (MIME) y abre la aplicación predeterminada para ese tipo de archivo. Si se registra más de una aplicación con el tipo de archivo, se muestra una ventana emergente de selección de la aplicación al usuario.
En el ejemplo de código siguiente se escribe texto en un archivo y se abre el archivo de texto con el iniciador:
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)));
Controlar ubicaciones de archivos
Importante
Esta sección solo se aplica a Android.
En algunos escenarios de Android, como cuando un archivo está en almacenamiento privado, se puede copiar en la memoria caché de la aplicación, que luego se comparte a través de una FileProvider
de Android. Sin embargo, esto puede exponer involuntariamente toda la memoria caché y los datos de la aplicación a un atacante. Esto se puede evitar agregando un archivo de anulación de rutas de archivo del proveedor en tu aplicación y asegurándote de que los archivos se copian en la ubicación especificada en este archivo antes de compartir.
Para añadir un archivo de anulación de rutas de acceso de proveedor de archivos a tu aplicación, agrega un archivo llamado microsoft_maui_essentials_fileprovider_file_paths.xml a la carpeta Platforms\Android\Resources\xml de la aplicación. Por lo tanto, el nombre de archivo relativo completo al proyecto debe ser Plataformas\Android\Resources\xml\microsoft_maui_essentials_fileprovider_file_paths.xml. A continuación, agregue XML al archivo para las rutas de acceso necesarias:
<?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>
Para obtener más información sobre las rutas de acceso del proveedor de archivos, consulte FileProvider en developer.android.com.
Antes de compartir un archivo, debe asegurarse de que esté escrito primero en la carpeta raíz de uso compartido en una de las ubicaciones del archivo de anulación:
// 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),
});
Puede comprobar que el archivo se comparte correctamente si el URI compartido excluye el directorio raíz de uso compartido. Por ejemplo, si comparte el archivo <CacheDirectory>/sharing-root/mydata.txt y el URI compartido es content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/sharing-root/mydata.txt
el proveedor de archivos no usa la ruta de acceso correcta. Si el URI compartido es content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/mydata.txt
, el proveedor de archivos usa la ruta de acceso correcta.
Advertencia
Al compartir un archivo, si recibe un Java.Lang.IllegalArgumentException
, con un mensaje similar a "No se pudo encontrar la raíz configurada que contiene /data/data/com.companyname.overwritefileproviderpaths/cache/some-non-sharing-path/mydata.txt", probablemente comparta un archivo que esté fuera de la raíz de uso compartido.
Establecer la ubicación del iniciador
Importante
Esta sección solo se aplica a iPadOS.
Al solicitar un recurso compartido o abrir el iniciador en iPadOS, puede presentarlo en una ventana emergente. Esto especifica dónde aparecerá la ventana emergente y apuntará una flecha directamente. Esta ubicación suele ser el elemento de control que inició la acción. Puede especificar la ubicación mediante la propiedad 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
});
Todo lo descrito aquí funciona igualmente para Share y Launcher.
Este es un método de extensión que ayuda a calcular los límites de una vista:
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);
}
}
A continuación, se puede usar al llamar a 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
}
}
Puede pasar el elemento de llamada cuando se desencadene el Command
:
<Button Text="Share"
Command="{Binding ShareWithFriendsCommand}"
CommandParameter="{Binding Source={RelativeSource Self}}"/>
Para obtener un ejemplo de la clase ViewHelpers
, consulte el ejemplo de MAUI de .NET hospedado en GitHub.
Diferencias de plataforma
En esta sección se describen las diferencias específicas de la plataforma con la API del iniciador.
El Task devuelto de CanOpenAsync se completa inmediatamente.