Lanciatore
Questo articolo descrive come usare l'interfaccia utente dell'app multipiattaforma .NET (.NET MAUI). ILauncher Questa interfaccia consente a un'applicazione di aprire un URI dal sistema. Questo modo di aprire un'applicazione viene spesso usato quando si esegue il deep linking negli schemi URI personalizzati di un'altra applicazione.
L'implementazione predefinita dell'interfaccia ILauncher
è disponibile tramite la proprietà Launcher.Default. Sia l'interfaccia ILauncher
che la classe Launcher
sono contenute nello spazio dei nomi Microsoft.Maui.ApplicationModel
.
Importante
Per aprire il browser verso un sito web, utilizzare invece l'API browser.
Inizia subito
Per accedere alla funzionalità di avvio, è necessaria la configurazione specifica della piattaforma seguente.
Se vuoi usare collegamenti diretti per aprire altre app Android, devi definire un filtro finalità nell'app. A tale scopo, aggiungere il codice XML seguente al file 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>
Gli elementi <data>
sono gli schemi URI preregistrati con l'app. Non è possibile usare schemi non definiti nel filtro finalità.
Per rendere l'app esplorabile da altre app dichiarare un elemento <data>
con l'attributo android:scheme
:
<data android:scheme="appName"/>
Aprire un'altra app
Per usare la funzionalità Launcher, chiamare il metodo ILauncher.OpenAsync e passare un String o Uri che rappresenta l'app da aprire. Facoltativamente, il metodo ILauncher.CanOpenAsync(Uri) può essere usato per verificare se lo schema URI può essere gestito da un'app nel dispositivo. Il codice seguente illustra come verificare se uno schema URI è supportato o meno e quindi apre l'URI:
bool supportsUri = await Launcher.Default.CanOpenAsync("lyft://");
if (supportsUri)
await Launcher.Default.OpenAsync("lyft://ridetype?id=lyft_line");
L'esempio di codice precedente può essere semplificato usando il TryOpenAsync(Uri), che controlla se lo schema URI può essere aperto, prima di aprirlo:
bool launcherOpened = await Launcher.Default.TryOpenAsync("lyft://ridetype?id=lyft_line");
if (launcherOpened)
{
// Do something fun
}
Aprire un'altra app tramite un file
L'utilità di avvio può essere usata anche per aprire un'app con un file selezionato. .NET MAUI rileva automaticamente il tipo di file (MIME) e apre l'app predefinita per quel tipo di file. Se più app sono registrate con il tipo di file, viene visualizzato un popover di selezione dell'app all'utente.
L'esempio di codice seguente scrive testo in un file e apre il file di testo con l'utilità di avvio:
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)));
Controllare i percorsi dei file
Importante
Questa sezione si applica solo ad Android.
In alcuni scenari su Android, ad esempio quando un file si trova in un'archiviazione privata, può essere copiato nella cache dell'app, che viene quindi condivisa tramite FileProvider
su Android. Tuttavia, questo può esporre involontariamente l'intera cache e i dati dell'applicazione a un utente malintenzionato. Ciò può essere impedito aggiungendo alla tua app un file di override dei percorsi del provider di file e assicurandoti che i file vengano copiati nel percorso specificato in questo file prima della condivisione.
Per aggiungere un file di sostituzione dei percorsi del provider di file all'app, inserire un file chiamato microsoft_maui_essentials_fileprovider_file_paths.xml nella cartella Platforms\Android\Resources\xml dell'app. Pertanto, il nome file relativo completo al progetto deve essere Platforms\Android\Resources\xml\microsoft_maui_essentials_fileprovider_file_paths.xml. Aggiungere quindi XML al file per i percorsi necessari:
<?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>
Per altre informazioni sui percorsi del provider di file, vedere FileProvider su developer.android.com.
Prima di condividere un file, assicurati che sia prima salvato nella cartella sharing-root, in una delle posizioni indicate nel file di override.
// 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),
});
È possibile verificare che il file sia condiviso correttamente se l'URI condiviso esclude la directory radice di condivisione. Ad esempio, se si condivide il file <CacheDirectory>/sharing-root/mydata.txt e l'URI condiviso è content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/sharing-root/mydata.txt
il provider di file non usa il percorso corretto. Se l'URI condiviso è content://com.companyname.overwritefileproviderpaths.fileProvider/internal_cache/mydata.txt
, il provider di file usa il percorso corretto.
Avvertimento
Quando si condivide un file, se si riceve un Java.Lang.IllegalArgumentException
, con un messaggio simile a "Impossibile trovare la radice configurata che contiene /data/data/com.companyname.overwritefileproviderpaths/cache/some-non-sharing-path/mydata.txt", è molto probabile condividere un file al di fuori della radice di condivisione.
Impostare la posizione del lanciatore
Importante
Questa sezione si applica solo a iPadOS.
Quando si richiede una condivisione o si apre un'utilità di avvio in iPadOS, è possibile presentarla in un popover. Specifica dove verrà visualizzato il popover e dove punterà direttamente una freccia. Questo luogo è spesso il comando che ha avviato l'azione. È possibile specificare il percorso usando la proprietà 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
});
Tutti gli elementi descritti di seguito funzionano allo stesso modo per Share e Launcher.
Ecco un metodo di estensione che consente di calcolare i limiti di una visualizzazione:
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);
}
}
Questa operazione può quindi essere usata quando si chiama 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
}
}
È possibile passare l'elemento chiamante quando viene attivato il Command
:
<Button Text="Share"
Command="{Binding ShareWithFriendsCommand}"
CommandParameter="{Binding Source={RelativeSource Self}}"/>
Per un esempio della classe ViewHelpers
, vedere l'esempio MAUI di .NET ospitato in GitHub.
Differenze tra le piattaforme
Questa sezione descrive le differenze specifiche della piattaforma con l'API di avvio.
Il Task che viene restituito da CanOpenAsync si completa immediatamente.