Bring the UWP app to the front of current window - c#

How can i use
await Windows.System.Launcher.LaunchUriAsync(new Uri("protocol://"));
to navigate to specific view of uwp application.
Is there any way to bring the app in front of the screen, if app was minimized or hidden behind other apps?
Thanks in advance

How can i use await Windows.System.Launcher.LaunchUriAsync(new Uri("protocol://")); to navigate to specific view of uwp application
For this, firstly you need to add the Protocol declaration in your Package.appxmanifest file . (Go to declarations tab and add Protocol from the available protocols). ( MSDN Doc )
Here i am using "app-protocol" as the protocol name.
Once this is done, you need to override the OnActivated() method in your App.xaml.cs. This method will be called when the app is launched using the protocol.
The arguments that we pass when calling the protocol can be retrieved here and based on that you can show your page or maybe pass that parameter to your page and let it handle the navigation .
For instance, if our Uri is app-protocol:login?param1=true, when you receive the ProtocolActivatedEventArgs eventArgs in the onActivated() method you will have access to the whole Uri.
You can use eventArgs.Uri to access all the Uri properties.
In any case your code should look something like this :
C#
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.Protocol)
{
ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
// Get the root frame
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
//URI : app-protocol:login?param1=true
//Logic for showing different pages/views based on parameters passed
if (eventArgs.Uri.PathAndQuery != string.Empty)//PathAndQuery:login?param1=true
{
var absolutePath = eventArgs.Uri.AbsolutePath;//AbsolutePath:login
if (absolutePath.Equals("login"))
{
rootFrame.Navigate(typeof(LoginPage));
}
else
{
rootFrame.Navigate(typeof(MainPage));
}
}
else
{
rootFrame.Navigate(typeof(MainPage));
}
}
// Ensure the current window is active
Window.Current.Activate();
}
Is there any way to bring the app in front of the screen, if app was minimized or hidden behind other apps?
We are calling Window.Current.Activate(); to ensure this.

To bring any UWP window to the front use this snippet (works if window with given viewId was already created and is either minimized or behind other windows:
private async Task TryActivateViewAsync(viewId)
{
if (Window.Current.Dispatcher != null)
{
await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
if (await ApplicationViewSwitcher.TryShowAsStandaloneAsync(viewId))
{
await ApplicationViewSwitcher.SwitchAsync(viewId);
}
});
}
}
Just as a reminder, viewId is an Identifier of a window which you can get when you create that window using:
var coreView = CoreApplication.CreateNewView(); // creates new view
await coreView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_someViewId = ApplicationView.GetForCurrentView().Id; // gets that view's id
}

Related

Xamarin.Forms UWP - Launch app on login

I'm trying to launch my app when the user logs in to Windows. I have the appropriate Extension (StartupTask) set in Package.appxmanifest, and I can get the app to launch when I log in to Windows, as expected. However, the app crashes after showing the Splash screen for about a second or two.
In my App.xaml.cs file, I have overridden the OnLaunched (called when the user launches the app) and OnActivated (called when the system launches the app after Windows login). Both call the same function to initialize my app; however, the app crashes only when the app is initialized from the OnActivated function. When initialized from OnLaunched, it works as expected. Here is the relevant code, from App.xaml.cs:
// Called when the user launches the app
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// Calling InitializeApp here, the app launches without problem
InitializeApp(e);
}
// Called when the system launches the app after Windows login
protected override void OnActivated(IActivatedEventArgs e)
{
base.OnActivated(e);
// Calling InitializeApp here will cause the app to crash
InitializeApp((LaunchActivatedEventArgs)e);
}
// initialize the app
async void InitializeApp(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
var assembliesToInclude = new List<Assembly>()
{
typeof(CachedImage).GetTypeInfo().Assembly,
typeof(CachedImageRenderer).GetTypeInfo().Assembly
};
Xamarin.Forms.Forms.Init(e, assembliesToInclude);
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
if (session == null)
{
// prevent the app from stopping when minimized
session = new ExtendedExecutionSession();
session.Reason = ExtendedExecutionReason.Unspecified;
session.Revoked += (s, a) => { };
var result = await session.RequestExtensionAsync();
if (result == ExtendedExecutionResult.Denied)
System.Diagnostics.Debug.WriteLine("EXTENDED EXECUTION DENIED");
}
}
The problem is that you are trying to cast the IActivatedEventArgs to LaunchActivatedEventArgs, but when startup activation happens, the type is actually StartupTaskActivatedEventArgs.
Luckily, you actually need the e parameter only for Xamarin.Forms.Forms.Init which actually accepts IActivatedEventArgs, so you can just change the parameter of InitializeApp to be IActivatedEventArgs and remove the cast to LaunchActivatedEventArgs in OnActivated.

Opening new UWP app using app-protocol from Startup application

I can start an application using app-protocol feature in windows 10 and universal windows application.
To do that first i declare a protocol in Package.appxmanifest file in application B then from my main application which call application A, run this code to run application B :
var success = await Launcher.LaunchUriAsync(new Uri("MyApplicationProtocolName:"));
But i face a problem, when main application is startup, i cannot lunch application B, how can i do that ?
The problem is that declaring the protocol itself is not enough for the application to respond to it. You also need to implement the protocol activation in app B:
public partial class App
{
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.Protocol)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
Window.Current.Activate();
}
}
}
The initialization you need to perform in OnActivated will probably be similar to OnLaunched in case the app is not yet launched. In case the app is already running, you don't need to do anything special, it will just come to the foreground. In case it is not running, you have to create the main Frame, initialize the Window.Current.Content and then do Window.Current.Activate() to activate the app.
Take a close look at the example code from Microsoft on this subject.
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/AssociationLaunching
See also:
https://learn.microsoft.com/en-us/windows/uwp/launch-resume/launch-app-with-uri

UWP OnShareTargetActivated Windows.System.Launcher.LaunchUriAsync does not work after first run

I would like to open my app after another app choose my app as the target for sharing a web link.
So first I use OnShareTargetActivated to read the weblink and then use LaunchUriAsync to launch my app through a custom scheme I created for it.
protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
ShareOperation shareOperation = args.ShareOperation;
try
{
if (shareOperation.Data.Contains(StandardDataFormats.WebLink))
{
var URL = await shareOperation.Data.GetWebLinkAsync();
var mAloudURI = #"myApp:?URL=" + URL;
// Launch the URI
await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
var success = await Windows.System.Launcher.LaunchUriAsync(new Uri(mAloudURI));
});
shareOperation.ReportCompleted();
}
}
catch (Exception exc)
{
var i = 0;
}
}
After that, I use OnActivated to read the link and open my MainPage on the passed link.
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.Protocol)
{
ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
var url = eventArgs.Uri.PathAndQuery.Substring("?URL=".Length);
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame != null)
{
rootFrame.Navigate(typeof(MainPage), url);
}
}
}
When I'm debugging I get the expected behavior when I F10 (step through) the line calling LaunchUriAsync, then OnActivated gets executed and MainPage gets displayed with the URL I wanted...
However if I try to share again, the secondary popup window for my app gets displayed for a while and then it disappears. Non of my break points get hit...
Is this the correct approach?
This looks to me like a very logical way of opening other apps with the content you are sharing to them...

Specify startup monitor for UWP app

In a UWP desktop app , is there a way to force the application to open on a specific monitor. (in my case I have a laptop and extra screen connected to the laptop, so I want the specify the startup screen in code)
I used the following code in winforms:
Screen[] screens = Screen.AllScreens;
if (Screen.AllScreens.Length == 1)
{
Application.Run(new frmMain());
}
else
{
//select largest monitor and set new monitor
Rectangle bounds = screens[LargestScreen].Bounds;
frm.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);
frm.StartPosition = FormStartPosition.Manual;
Application.Run(frm);
}
Any idea how to implement the above in a UWP app?
You should be able to create multiple views for the app and use ProjectionManager class with method StartProjectingAsync to show the secondary view on another screen. You may do this in OnLaunched method then once the app launch the secondary view will show on the screen you want.
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
///Get all the screens.
String projectorSelectorQuery = ProjectionManager.GetDeviceSelector();
var outputDevices = await DeviceInformation.FindAllAsync(projectorSelectorQuery);
//if(outputDevices.Count==1)
//{
//}
int thisViewId;
int newViewId = 0;
///Choose one screen for display .
DeviceInformation showDevice = outputDevices[1];
thisViewId = ApplicationView.GetForCurrentView().Id;
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
}
Window.Current.Activate();
}
///Create a new view
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame frame = new Frame();
frame.Navigate(typeof(MainPage), null);
Window.Current.Content = frame;
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
await ProjectionManager.StartProjectingAsync(newViewId, thisViewId, showDevice);
}
But it seems like the first view cannot be directly show on other screens since the StartProjectingAsync method requires a new view id. The first view that’s created when your app starts is called the main view. You don’t create this view; it’s created by the app. The main view's thread serves as the manager for the app, and all app activation events are delivered on this thread. And the main view cannot be closed, so the main first view will still leave on the first screen.
Details please reference the Projection official sample.

C#/XAML App Lifecycle - Jump login page after Terminating app

In my Windows Store App i've followed the Microsoft guidelines to resume the app after it is terminated(http://goo.gl/oZ7BG).
It all works but after the app is terminated i'd like to jump the login page(that is the first page in the app) and go directly to the Menu page of the app. It's absolutely like the Dropbox app. I know i have to work to the App.xaml.cs and this method:
protected async override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
bool appTerminated = false;
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
marketingHP.Common.SuspensionManager.RegisterFrame(rootFrame, "appFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
await marketingHP.Common.SuspensionManager.RestoreAsync();
appTerminated = true;
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
if (appTerminated)
rootFrame.Navigate(typeof(HomePage), args.Arguments);
else if (!rootFrame.Navigate(typeof(LoginPage), args.Arguments))
{
throw new Exception("Failed to create initial page");
}
}
// Ensure the current window is active
Window.Current.Activate();
}
How can i understand that the app is terminated before?
Note that i've added the bool appTerminated but it works only for suspending...
Read up further on windows 8 app lifecycle here:
http://msdn.microsoft.com/en-us/library/windows/apps/hh464925.aspx
Particularly, notice the section regarding the PreviousExecutionState property and the table included there outlining the different terminated states. It seems like what you would want to do is check the value of PreviousExecutionState, and if that value reflects the condition in which you want to skip the login page (e.g. the user has already logged in), then you should navigate to your homepage, similar to what you've tried to do above.
If you are closing the app manually and windows is not terminating it due to resource constraints, or it was closed unexpectedly, then appTerminated won't be set to true.
Instead of:
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
Include a check to see if the app was terminated by the user:
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated ||
args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser)
This will catch both when windows terminates the app due to resource constraints and when a user terminates the app manually. Then, on startup from termination, appTerminated should be set to true, and the app should navigate directly to HomePage.
edit:
In answer to your comment, what you could do is inside the App.xaml file, provide logic that changes the arguments passed in the Navigate call. You could do something like this:
string navArgs = "FromApp";
if (appTerminated)
{
navArgs = "FromTerminated";
}
Then, just pass this to HomePage when you call Navigate:
if (appTerminated)
{
rootFrame.Navigate(typeof(HomePage), navArgs);
}
Now, in your HomePage code behind file, define the OnNavigatedTo method. This takes a NavigatedEventArgs that you can then cast as some object (in this case as a String) and then check to see what was passed:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string navArgs = e.Parameter as String;
switch (navArgs)
{
case "FromApp":
//Do something here
break;
case "FromTerminated":
//Do something different here
break;
default:
break;
}
}
Hope this helps!

Categories

Resources