---
uid: Uno.Features.ProtocolActivation
---
# Custom protocol activation
## Registering custom scheme
### iOS & macOS
Declare your custom URL scheme in `info.plist` in the platform head:
```xml
CFBundleURLTypes
CFBundleURLName
My Useful Scheme
CFBundleURLSchemes
my-scheme
```
### Android
Register your protocol on the `MainActivity` with the `[IntentFilter]` attribute:
```csharp
[IntentFilter(
new [] {
Android.Content.Intent.ActionView
},
Categories = new[] {
Android.Content.Intent.CategoryDefault,
Android.Content.Intent.CategoryBrowsable
},
DataScheme = "my-scheme")]
```
If your target framework is Android 12, you must also add `Exported = true` to the `[Activity]` attribute.
`CategoryDefault` is required (must be included for all implicit intents) and `CategoryBrowsable` is optional (allows opening the custom URI from the browser).
### WASM
WASM implementation uses the [`Navigator.registerProtocolHandler` API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/registerProtocolHandler).
This has several limitations when using a custom scheme:
- The custom scheme's name must begin with `web+`
- The custom scheme's name must include at least 1 letter after the `web+` prefix
- The custom scheme must have only lowercase ASCII letters in its name.
You can also use one of the following supported schemes instead:
- `bitcoin`
- `ftp`
- `ftps`
- `geo`
- `im`
- `irc`
- `ircs`
- `magnet`
- `mailto`
- `matrix`
- `mms`
- `news`
- `nntp`
- `openpgp4fpr`
- `sftp`
- `sip`
- `sms`
- `smsto`
- `ssh`
- `tel`
- `urn`
- `webcal`
- `wtai`
- `xmpp`
To register the custom theme, call the WASM-specific `Uno.Helpers.ProtocolActivation` API when appropriate to let the user confirm URI handler association:
```csharp
#if __WASM__
Uno.Helpers.ProtocolActivation.RegisterCustomScheme(
"web+myscheme",
new System.Uri("http://localhost:55838/"),
"Can we handle web+myscheme links?");
#endif
```
The first argument is the scheme name, the second is the base URL of your application (it must match the current domain to be registered successfully), and the third is a text prompt, which will be displayed to the user to ask for permission (this does not work on all browsers e.g. edge).
When a link with the custom scheme gets executed, the browser will navigate to the URL with an additional `unoprotocolactivation` query string key, which will contain the custom URI. Uno internally recognizes this query string key and executes `OnActivated` appropriately.
### WinUI
Works according to Windows docs. For more information, see [Handle URI activation | Microsoft Docs](https://learn.microsoft.com/windows/uwp/launch-resume/handle-uri-activation).
## Handling protocol activation
Custom URI activation can be handled by overriding the `OnActivated` method in `App.cs` or `App.xaml.cs`:
```csharp
protected override void OnActivated(IActivatedEventArgs e)
{
// Note: Ensure the root frame is created
if (e.Kind == ActivationKind.Protocol)
{
var protocolActivatedEventArgs = (ProtocolActivatedEventArgs)e;
var uri = protocolActivatedEventArgs.Uri;
// do something
}
}
```
Note that in line with WinUI, if the application is not running, the `OnLaunched` method is not called and only `OnActivated` is executed instead. You must perform a similar initialization of the root app frame and activate the current `Window` at the end. If the application is running, this initialization can be skipped.
A full application lifecycle handling with shared logic between `OnLaunched` and `OnActivated` could look as follows:
```csharp
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
var rootFrame = GetOrCreateRootFrame(e);
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
Window.Current.Activate();
}
}
protected override void OnActivated(IActivatedEventArgs args)
{
var rootFrame = GetOrCreateRootFrame(args);
if (args.Kind == ActivationKind.Protocol)
{
var protocolActivatedEventArgs = (ProtocolActivatedEventArgs)args;
var uri = protocolActivatedEventArgs.Uri;
rootFrame.Navigate(typeof(DetailPage), uri.AbsoluteUri);
Window.Current.Activate();
}
}
private Frame GetOrCreateRootFrame(IActivatedEventArgs eventArgs)
{
var rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (eventArgs.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Load state from previously suspended application
}
Window.Current.Content = rootFrame;
}
return rootFrame;
}
```