File: Launcher\Launcher.shared.cs
Web Access
Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials)
#nullable enable
using System;
using System.Threading.Tasks;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Storage;
 
namespace Microsoft.Maui.ApplicationModel
{
	/// <summary>
	/// The Launcher API enables an application to open a URI by the system.
	/// This is often used when deep linking into another application's custom URI schemes.
	/// </summary>
	/// <remarks>
	/// <para>If you are looking to open the browser to a website then you should refer to the <see cref="IBrowser"/> API.</para>
	/// <para>On iOS 9+, you will have to specify the <c>LSApplicationQueriesSchemes</c> key in the <c>info.plist</c> file with URI schemes you want to query from your app.</para>
	/// </remarks>
	public interface ILauncher
	{
		/// <summary>
		/// Queries if the device supports opening the given URI scheme.
		/// </summary>
		/// <param name="uri">URI scheme to query.</param>
		/// <returns><see langword="true"/> if opening is supported, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		Task<bool> CanOpenAsync(Uri uri);
 
		/// <summary>
		/// Opens the app specified by the URI scheme.
		/// </summary>
		/// <param name="uri">URI to open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		Task<bool> OpenAsync(Uri uri);
 
		/// <summary>
		/// Requests to open a file in an application based on content type.
		/// </summary>
		/// <param name="request">Request that contains information on the file to open.</param>
		/// <returns><see langword="true"/> if the file was opened, otherwise <see langword="false"/>.</returns>
		Task<bool> OpenAsync(OpenFileRequest request);
 
		/// <summary>
		/// First checks if the provided URI is supported, then opens the app specified by the URI.
		/// </summary>
		/// <param name="uri">URI to try and open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		Task<bool> TryOpenAsync(Uri uri);
	}
 
	/// <summary>
	/// The Launcher API enables an application to open a URI by the system.
	/// This is often used when deep linking into another application's custom URI schemes.
	/// </summary>
	/// <remarks>
	/// <para>If you are looking to open the browser to a website then you should refer to the <see cref="IBrowser"/> API.</para>
	/// <para>On iOS 9+, you will have to specify the <c>LSApplicationQueriesSchemes</c> key in the <c>info.plist</c> file with URI schemes you want to query from your app.</para>
	/// </remarks>
	public static partial class Launcher
	{
		/// <summary>
		/// Queries if the device supports opening the given URI scheme.
		/// </summary>
		/// <param name="uri">URI scheme to query.</param>
		/// <returns><see langword="true"/> if opening is supported, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> CanOpenAsync(string uri)
			=> Current.CanOpenAsync(uri);
 
		/// <summary>
		/// Queries if the device supports opening the given URI scheme.
		/// </summary>
		/// <param name="uri">URI scheme to query.</param>
		/// <returns><see langword="true"/> if opening is supported, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> CanOpenAsync(Uri uri)
			=> Current.CanOpenAsync(uri);
 
		/// <summary>
		/// Opens the app specified by the URI scheme.
		/// </summary>
		/// <param name="uri">URI to open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> OpenAsync(string uri)
			=> Current.OpenAsync(uri);
 
		/// <summary>
		/// Opens the app specified by the URI scheme.
		/// </summary>
		/// <param name="uri">URI to open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> OpenAsync(Uri uri)
			=> Current.OpenAsync(uri);
 
		/// <summary>
		/// Requests to open a file in an application based on content type.
		/// </summary>
		/// <param name="request">Request that contains information on the file to open.</param>
		/// <returns><see langword="true"/> if the file was opened, otherwise <see langword="false"/>.</returns>
		public static Task<bool> OpenAsync(OpenFileRequest request)
			=> Current.OpenAsync(request);
 
		/// <summary>
		/// First checks if the provided URI is supported, then opens the app specified by the URI.
		/// </summary>
		/// <param name="uri">URI to try and open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> TryOpenAsync(string uri)
			=> Current.TryOpenAsync(uri);
 
		/// <summary>
		/// First checks if the provided URI is supported, then opens the app specified by the URI.
		/// </summary>
		/// <param name="uri">URI to try and open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> TryOpenAsync(Uri uri)
			=> Current.TryOpenAsync(uri);
 
		static ILauncher Current => ApplicationModel.Launcher.Default;
 
		static ILauncher? defaultImplementation;
 
		/// <summary>
		/// Provides the default implementation for static usage of this API.
		/// </summary>
		public static ILauncher Default =>
			defaultImplementation ??= new LauncherImplementation();
 
		internal static void SetDefault(ILauncher? implementation) =>
			defaultImplementation = implementation;
	}
 
	partial class LauncherImplementation : ILauncher
	{
		public Task<bool> CanOpenAsync(Uri uri)
		{
			if (uri == null)
				throw new ArgumentNullException(nameof(uri));
 
			return PlatformCanOpenAsync(uri);
		}
 
		public Task<bool> OpenAsync(Uri uri)
		{
			if (uri == null)
				throw new ArgumentNullException(nameof(uri));
 
			return PlatformOpenAsync(uri);
		}
 
		public Task<bool> OpenAsync(OpenFileRequest request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));
			if (request.File == null)
				throw new ArgumentNullException(nameof(request.File));
 
			return PlatformOpenAsync(request);
		}
 
		public Task<bool> TryOpenAsync(Uri uri)
		{
			if (uri == null)
				throw new ArgumentNullException(nameof(uri));
 
			return PlatformTryOpenAsync(uri);
		}
	}
 
	/// <summary>
	/// Static class with extension methods for the <see cref="ILauncher"/> APIs.
	/// </summary>
	public static class LauncherExtensions
	{
		/// <summary>
		/// Queries if the device supports opening the given URI scheme.
		/// </summary>
		/// <param name="launcher">The object this method is invoked on.</param>
		/// <param name="uri">URI scheme to query.</param>
		/// <returns><see langword="true"/> if opening is supported, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> CanOpenAsync(this ILauncher launcher, string uri) =>
			launcher.CanOpenAsync(new Uri(uri));
 
		/// <summary>
		/// Opens the app specified by the URI scheme.
		/// </summary>
		/// <param name="launcher">The object this method is invoked on.</param>
		/// <param name="uri">URI to open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> OpenAsync(this ILauncher launcher, string uri) =>
			launcher.OpenAsync(new Uri(uri));
 
		/// <summary>
		/// First checks if the provided URI is supported, then opens the app specified by the URI.
		/// </summary>
		/// <param name="launcher">The object this method is invoked on.</param>
		/// <param name="uri">URI to try and open.</param>
		/// <returns><see langword="true"/> if the URI was opened, otherwise <see langword="false"/>.</returns>
		/// <exception cref="UriFormatException">Thrown when <paramref name="uri"/> is malformed.</exception>
		public static Task<bool> TryOpenAsync(this ILauncher launcher, string uri) =>
			launcher.TryOpenAsync(new Uri(uri));
	}
 
	/// <summary>
	/// Represents a request for opening a file in another application.
	/// </summary>
	public class OpenFileRequest
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenFileRequest"/> class.
		/// </summary>
		public OpenFileRequest()
		{
		}
 
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenFileRequest"/> class with the given title and existing file.
		/// </summary>
		/// <param name="title">Title to display on open dialog.</param>
		/// <param name="file">File to open.</param>
		/// <remarks>The title might not always be displayed on every platform.</remarks>
		public OpenFileRequest(string title, ReadOnlyFile file)
		{
			Title = title;
			File = file;
		}
 
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenFileRequest"/> class with the given title and existing file.
		/// </summary>
		/// <param name="title">Title to display on the open dialog.</param>
		/// <param name="file">File to open.</param>
		/// <remarks>The title might not always be displayed on every platform.</remarks>
		public OpenFileRequest(string title, FileBase file)
		{
			Title = title;
			File = new ReadOnlyFile(file);
		}
 
		/// <summary>
		/// Gets or sets the title to display on the open dialog.
		/// </summary>
		/// <remarks>The title might not always be displayed on every platform.</remarks>
		public string? Title { get; set; }
 
		/// <summary>
		/// Gets or sets the file to open through this request.
		/// </summary>
		public ReadOnlyFile? File { get; set; }
 
		/// <summary>
		/// Gets or sets the source rectangle to display the Share UI from.
		/// </summary>
		/// <remarks>This only has effect on iPadOS.</remarks>
		public Rect PresentationSourceBounds { get; set; } = Rect.Zero;
	}
}