I am developing an WP8 app that uses a webbrowser control that shows statefull server content. On WP8 you can switch between apps manually. E.g. if you want to copy&paste some information from one app into a browser input field. If you switch that way, the current app instance stays alive. That means the web session and the current page of the browser control will stay available.
Now I want another app to send some data directly into the app with the browser control - without restarting it...
From what I know, there are three ways to handle inter app communication:
register a file type that will open the app by launching that file from local storage
register an app protocol and use Launcher.LaunchUriAsync() to submit parameters in a query string
use a shared storage file
Detailed information can be found here.
I think the last approach is not usefull, because after you have started the second app, there is now way to activate the calling app or is there any usefull way to reactivate the webbrowser app?
I tried the second approach, but I am running in an issue, because it starts a new instance by design. That means InitializePhoneApplication is called. There is the entry point for the custom UriMapper that reads the incoming parameters. So the old app instance is killed and all session data, cookies and input fields are gone. With WP webbrowser control you are not able to store the cookie and page state, so a fast app resume is not possible also.
private void InitializePhoneApplication()
{
if (this.phoneApplicationInitialized)
{
return;
}
RootFrame = new TransitionFrame();
RootFrame.Navigated += this.CompleteInitializePhoneApplication;
RootFrame.UriMapper = new AssociationUriMapper();
//...
this.phoneApplicationInitialized = true;
}
Is there any other way or a possibility to use the shown approaches to send data between apps without restarting them using LanchUri()?
That means, to send some data back to a running instance without reinitializing the whole app, so that the page state and session state are still available on the target app.
Best regards
Holger
FastAppResume is the solution. I haven't used it and thought it also reinitiates the app. But it doesnt. This example shows how to reuse the existing instance.
Regards
Holger
Related
When creating a .NET Core Web app C# and debugging you can opt to Launch the browser when Running the app. The console launches and then the url launches in your preferred browser. Once you close the browser tab opened by the debug session, the app process it stop and is no longer running on the machine.
When I published the app, the page does not launch automatically so I am starting a new Process to do so. I've added an event handler to the process before starting it but the since the app didn't launch the process it doesn't receive any notification when the tab has been closed.
What is the proper way to go about launching your .NET Core web app and/or handle communicating between the two?
I even tried adding a Close button but JS won't allow me to close the window as I haven't opened it.
I'm creating my Process as follows:
var p = Process.Start("cmd", "/C start http://localhost:5000");
I've tried
p.WaitForExit();
p.EventHandler += newHandler;
and I also tried using ProcessStartInfo but the only thing that is working right now is if I set a Timer and then kill the process when the timer is activated but this doesn't seem too clean.
Any advice is appreciated!
I wanted to follow-up with the process I feel is the most graceful way that I am happy with.
A few pieces of info that may be helpful in creating your own process. It was a goal of mine to use .net core to self host a client side web app which communicates with a server hosted web api.
I am using Razor views and .net core 3.1
I am using Startup and utilizing applicationLifeTime to handle OnStartup where I start the process as I described in my original post.
At this point the web app opens and if the user decides to close the browser the process doesn't know and continues to run in the background.
In order to prevent it from continuing to run and allow the user to initiate it closing, I made a few the following additions.
First, I added a timer that uses a configurable length of time via appsettings. When starting the process that opens the browser I call and set the timer that will perform an "AutoShutdown" if the process is still running after the configurable length of time that I defaulted to 1hr. I am using Enviroment.Exit(0) in the event that handles closing the running process.
My View is using a Model that contains a property who's value will be set from the page via a hidden field.
I added a Close button to the View that is displayed to the user at startup. When the user clicks close, I use jquery to set a hidden field in the view and then I use jquery to submit the form.
When the Model is received, the value set by the client's request to close is true and you can handle the close without display errors if you use a Timer and Start it almost immediately after redirecting the View to a view with a message to the client. Whether they leave it open or close it, the process will have closed. Example of how I did it below.
Finally, in Main.cs I put a check in to check if there is an existing process running and close it before starting a new one. I added this because the client may not always close the browser and/or they may attempt to start it before the "AutoShutdown" timer has kicked in.
This is more "hacky" then I would like but I couldn't find anything else that didn't throw and show Bad Request when trying to use Envirnoment.Exit(0) when the client is still has the view open and I was unsuccessful at being able to allow console input so that I could send close to the console.
This is how I am handling the close request from the client in my Controller
if (ui.HandleCloseApp)
{
var app = Process.GetProcessesByName("NameOfYourWebApp");
if (app.Length >= 1)
{
foreach (var p in app)
{
if (p.ProcessName == "NameOfYourWebApp")
{
p.Close();
p.Dispose();
}
}
}
var t = new System.Timers.Timer(10);
t.Elapsed += OnClose;
t.Start();
return View("Close");
}
I hope this helps someone else in creating their own "graceful" process that shouldn't be :)
I'm still open if anyone has input to share. Thx!
I've built a WPF app in C# which needs to know the user's location, and currently requires that it be entered manually. I'm using the Desktop Bridge to make it be able to run as a UWP app. When it's running as a UWP app, I want to take advantage of the Windows 10 location API if it is enabled. I'm using the following code to request for location access when the program starts:
public static async void RequestAccess()
{
var accessStatus = await Windows.Devices.Geolocation.Geolocator.RequestAccessAsync();
switch (accessStatus)
{
case Windows.Devices.Geolocation.GeolocationAccessStatus.Allowed:
UwpDesktop.hasLocationAccess = true;
break;
case Windows.Devices.Geolocation.GeolocationAccessStatus.Denied:
UwpDesktop.hasLocationAccess = false;
break;
case Windows.Devices.Geolocation.GeolocationAccessStatus.Unspecified:
MessageBox.Show("Failed to access Windows 10 location API", "Error");
UwpDesktop.hasLocationAccess = false;
break;
}
}
However I get the following error when I run my app if the location permission is not enabled for it:
System.Exception: 'Element not found. (Exception from HRESULT: 0x80070490)'
The cause of this error as far as I can tell is that the RequestAccessAsync function needs to be run in the main UWP UI thread. The reason it only happens when the location permission is not enabled is because Windows tries to launch a UWP dialog requesting that the user grant location access, but fails to do so in a Desktop Bridge app.
I'm aware of two solutions to this problem. One would be to launch the Location section of the Settings app and show a messagebox to users asking them to grant location access there, which could work but I would really prefer to use the official API. The other option is to create a new UWP code project and write this code there, and then run it from the WPF app.
Microsoft has some documentation that is supposed to explain how to do the second option, but their examples are complicated and I don't know how to apply them to what I'm trying to do. I don't want to create a XAML UI or a background service, all I need is a way to safely call RequestAccessAsync and return a value based on the outcome. I'm wondering if I really need to create a UWP project to make this behave the way I want, or what the simplest way would be to go about it.
I'm planing to start a UWP application that monitor a sensor data for 365 days and save all data to database(Sqlite).
I still worry about UWP capability. Please advice me Which should I use (UWP/WPF) ? I want to use better UI, than, I want to use UWP if possible...
UWP-Suspending is my worry.
With this post, Some people said a way to prevent a UWP application from suspending..
var extendedExecutionSession = new ExtendedExecutionSession();
extendedExecutionSession.Reason = ExtendedExecutionReason.Unspecified;
var extendedExecutionResult = await extendedExecutionSession.RequestExtensionAsync();
if (extendedExecutionResult != ExtendedExecutionResult.Allowed)
{
//extended execution session revoked
extendedExecutionSession.Dispose();
extendedExecutionSession = null;
}
Question
If I wrote this code in UWP app, Can I use a UWP application like Desktop WPF application ? I want to run my UWP application for 365 days without stopping
.. even if user do "minimized" on desktop... Please advice it...
Yes, you can do that with ExtendedExecution. One thing to note is when you run on battery (e.g. laptop, tablet) you will get suspended after some time - however you can prevent that as well by going into the Battery settings page and set your app as "Always Allowed".
Details are documented here: https://learn.microsoft.com/en-us/windows/uwp/launch-resume/run-minimized-with-extended-execution
I try to solve problem with the Windows Phone Launcher.
I have application and I would like to call another application using the uri and pass it some data. And I would like to know if the second application started. If the application was not started I would like to do some fallback.
Example:
bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri("secondApp://data/123", UriKind.RelativeOrAbsolute));
if (!result)
{
// Opps. The second application is not installed.
ShowToast("Oops. The applications is not installed.");
UseInternalTinyFunctionalityInstead();
}
But the result is always true. Even though the second application is not installed. And additionally the windows message box is displayed "Search for app in the Store? You need to install an app for this task. Would you like to search for one in the Store? yes, no".
Is it possible to check if the second application was started/ is installed?
Is it possible NOT to display this dialog?
Thank you.
Myth Rush
In wp7 app I simply call web browser task. But when I press back button, it closes the task but also wp7 app. So, How do I go back to app ? (with back button or something else it doesn't matter.)
WebBrowserTask task = new WebBrowserTask();
task.Uri = new Uri("myUri", UriKind.RelativeOrAbsolute);
task.Show();
If you launch a WebBrowserTask from your app, the user will return to your app by default after closing the browser with the back button.
It is possible that your code raises an exception when it is reactivated and then it crashes.
To test this, simply run it with F5 and you will see if you get an exception.
Okay, when I asked the question, I had no clue about things in Windows phone 7.
So if you navigate to a new page or start new task(like web browser), then you click the back button, it goes back to the page which called the method(navigate or new task). There's no problem with it.
However, if an exception raises when navigating back, or going back to the app from task, the program crashes with Debugger.Stop() in App.xaml.cs.
I was using PhoneApplicationService.Current.State to store datas because I was passing these datas from page to page. But this way the app stores the datas only for the thread you are using.
Well, I had the problem because when I started a web browser task , the app deleted the datas I stored with PhoneApplicationService.Current.State. When I come back from the task, I was using the this code
string str = PhoneApplicationService.Current.State["some_key"];
But datas were already deleted, so it was trying to get the values, but couldn't achieve this, so it raised an exception.
This problem doesn't appear when navigating page to page, but when starting tasks.
So my suggestion is if you want to store datas, you could use IsolatedStorageSettings.ApplicationSettings. You can find a reference here.
It 's a good approach, because not only you store the datas for the moment, you can use the datas when you open the app after closing.