Handling back button on launch from secondary tile - windows-phone-8.1

How do I make the hardware back button return to the system's Start page when my app is launched from a secondary tile (i.e. deep linking)?
I'm using XAML and C#, by the way.

You can just clear the back stack if app is launched from a secondary tile.
Next press on back button will take user back to Start screen.
EDIT:
To clear the back stack:
If you're in page code behind, do
Frame.BackStack.Clear();
else do
var frame = Window.Current.Content as Frame;
frame.BackStack.Clear();

So, finally answering my own question months later...
The situation
Whenever my app is launched using a secondary tile, I have to make sure that the back stack is cleared by calling rootFrame.BackStack.Clear() on App.xaml.cs. That's necessary because if there is a suspended instance of my app in memory, this navigation from the secondary tile is added to the top of whatever back stack that suspended instance had. This is a problem because it makes a press of the back button return to the previous page on the stack instead of the Start screen, which is the appropriate behavior for secondary tile launches.
The problem
If the user "cold launches" the app using a secondary tile, whenever s/he leaves it Windows will suspend that session of the app with a clear back stack. That means that new launches from the primary tile will restore that page that was called from the secondary tile, and pressing the back button will suspend the app again instead of going to the app's main page.
The solution
It's actually documented by Microsoft, but only textually (https://msdn.microsoft.com/en-us/library/windows/apps/xaml/dn639128.aspx):
Ensure proper Back button behavior when your app supports multiple launch points
Consider creating new instances of navigation journals for launch points such as primary and secondary tiles, file and URI Associations. Save the activation parameters each time the app is launched and compare when the app is being re-launched. If the app is being re-launched with different parameters, consider creating a new navigation history. Do this by creating a new Frame. This will allow the user to quickly navigate back to the launch point when the hardware Back key button is pressed. To maintain a small memory footprint, the Navigation history for launch points other than the Primary tile doesn’t need to be saved when the app is suspended.
In practice, for me, that meant writing the last received launch argument to a text file in my app's storage and reading it back on the beginning of the OnLaunched method in App.xaml.cs. Then I compare the read value to the current launch arguments. If they are different, I simply assign null to the rootFrame variable, so that a new "navigation journal" is created:
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
...
Frame rootFrame = Window.Current.Content as Frame;
var lastArgument = await ReadLastArgument();
if (!string.Equals(lastArgument,currentArgument))
rootFrame = null;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active.
if (rootFrame == null){
...
}
...
if (!String.IsNullOrEmpty(e.Arguments))
{
WriteLastArgument(e.Arguments);
//Navigate to the page...
...
rootFrame.BackStack.Clear();
}
private async Task<string> ReadLastArgument()
{
StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
try
{
StorageFile file = await folder.GetFileAsync("lastArgument.txt");
var argument = await Windows.Storage.FileIO.ReadTextAsync(file);
return argument;
}
catch (System.IO.FileNotFoundException)
{
return "";
}
}
private async void WriteLastArgument(string argument)
{
StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync("lastArgument.txt", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, argument);
}
}

Related

Detect if user Idle on windows universal app

I'm developing a class library for windows 10 universal apps (mobile and desktop device families only). I need to invoke an event if the user has been idle(no touch, mouse move, key press etc) for x number of seconds. This method can be used to solves this problem on android. But I couldn't find a solution on windows UWP.
Is there an API available in UWP to achieve this?
You can detect global input with various events on the app's CoreWindow:
Touch and mouse input with CoreWindow.PointerPressed, PointerMoved, and PointerReleased.
Keyboard input: KeyUp and KeyDown (the soft keys) and CharacterReceived (for characters generated via chords & text suggestions)
Use these to detect the user is active and idle out if it goes too long without any of these events.
I know this is really old question, but I think you can now get to same result with RegisterBackgroundTask
Just set:
new TimeTrigger(15, false) //For time trigger
Link
new SystemCondition(SystemConditionType.UserNotPresent)) //And so you want to know so user is not present
Link
Example usage in App.xaml.cs:
var builder = new BackgroundTaskBuilder();
builder.Name = "Is user Idle";
builder.SetTrigger(new TimeTrigger(2, false)); //two mins
builder.AddCondition(new SystemCondition(SystemConditionType.UserNotPresent));
// Do not set builder.TaskEntryPoint for in-process background tasks
// Here we register the task and work will start based on the time trigger.
BackgroundTaskRegistration task = builder.Register();
task.Completed += (sender, args) =>
{
//Handle user not present (Idle) here.
};

How to carry out save action on a page when the user presses the start key

I am working on a Windows Phone 8 app and want to save data from a page each time the user navigates away from the page. This works fine if the user presses the back key or navigates within the application, however if I press the start key nothing is saved. My code is shown below:
protected async override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
if (!toDelete)
{
List<NoteItem> ni = this.getNoteItems();
await SaveNotes(ni, this.Title.Text);
}
}
This calls the method to save the notes. I don't see any other events on a page to save this. Does anybody know where I am going wrong with this?
Thanks,
You can try handling this case in App.xaml.cs.
When the Start button is pressed, Application_Deactivated event is raised.
For example
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
//do the saving here
}
Although, I'm getting the OnNavigatingFrom event called when pressing Start button, too, so it may be the charm of using await in event handlers. Read this article by Andy Wigley, it's packed with useful info.

Run Chrome extension in the background

I'm currently creating my first Chrome extension, so far so good.
It's just a little test where I run multiple timers.
But obviously all my timers reset when I open and close the extension.
So to keep all my timers running, I would have to same them somehow when I close the extension and make them run in the background page.
When I open the extension again, those timers should be send back to the open page.
How would you handle this?
I already have an array of all my timers, what would be the best option for me>
A background page runs at all times when the extension is enabled. You cannot see it, but it can modify other aspects of the extension, like setting the browser action badge.
For example, the following would set the icon badge to the number of unread items in a hypothetical service:
function getUnreadItems(callback) {
$.ajax(..., function(data) {
process(data);
callback(data);
});
}
function updateBadge() {
getUnreadItems(function(data) {
chrome.browserAction.setBadgeText({text:data.unreadItems});
});
}
Then, you can make a request and schedule it so the data is retrieved and processed regularly, you can also stop the request at any time.
var pollInterval = 1000 * 60; // 1 minute
function startRequest() {
updateBadge();
window.setTimeout(startRequest, pollInterval);
}
function stopRequest() {
window.clearTimeout(timerId);
}
Now just load it...
onload='startRequest()'
Also, HTML5 offline storage is good for storing data and constantly update it...
var data = "blah";
localStorage.myTextData = data;

Execute exe-file from html-page?

I want to launch a local exe-file (without saving it to another location first) upon clicking on a link on a local html file.
It either needs to work in IE, Firefox, Chrome or Opera, I don't care. It's just for a presentation tomorrow.
It's simply not possible. If it was, it would be considered a security flaw and fixed. On Firefox within hours, on IE within some months.
UPDATE: You could try registering your custom protocol: http://openwinforms.com/run_exe_from_javascript.html
But I believe the browser will still prompt you whether you want to run the app.
I want to share my experience.
The accepted response says that it is not possible but it is quite possible indirectly.
If you want to execute an exe on a pc, it means that you have acces on this pc and you can install your exe on that machine.
In my case, I had to take a 3D scan from a 3D scanner via a web application. It seemed impossible at the beginning.
After lots of research, I found that we can send socket messages via javascript.
It means that if we had an application which listens a specific port, it can communicate with a website.
Let's explain how I did this.
In my web application, I created a javascript method like this :
function openCapron3DScanner(foot) {
$("#div-wait").show();
//Creates a web socket pointed to local and the port 21000
var ws = new WebSocket("ws://127.0.0.1:21000");
ws.onopen = function () {
//Sends the socket message to the application which listens the port 21000
ws.send(foot + "-" + #ProjectHelper.CurrentProject.Proj_ID);
};
ws.onerror = function myfunction() {
$("#div-wait").hide();
alert("Erreur connection scanner.");
}
ws.onmessage = function (evt) {
//Receives the message and do something...
var received_msg = evt.data;
if (received_msg == "ErrorScan") {
alert("Erreur scan.");
}
else {
refreshCurrentProject();
}
};
ws.onclose = function () {
$("#div-wait").hide();
};
};
And I created a windows forms application who listens the localhost and port 21000.
This application is hidden, only shown in icon tray.
The only thing to do is to add the application on windows startup via code on the first load to assure that the next restart of windows it will be executed and listen the port.
private static WebSocketServer wsServer;
static WebSocketSession LastSession;
private void Form1_Load(object sender, EventArgs e)
{
wsServer = new WebSocketServer();
int port = 21000;
wsServer.Setup(port);
wsServer.NewMessageReceived += WsServer_NewMessageReceived;
wsServer.Start();
}
private static void WsServer_NewMessageReceived(WebSocketSession session, string value)
{
if (value.StartsWith("ScanComplete-"))
{
//If the scan is ok, uploads the result to the server via a webservice and updates the database.
UploadImage(value);
//Sends a confirmation answer to the web page to make it refresh itself and show the result.
if (LastMacSession != null)
LastMacSession.Send("ScanComplete");
}
else if (value == "ErrorScan")
{
//If the C++ application sends an error message
if (LastMacSession != null)
LastMacSession.Send("ErrorScan");
}
else//call the 3D Scanner from the web page
{
LastSession = session;//Keeps in memory the last session to be able to answer via a socket message
//Calls the C++ exe with parameters to save the scan in the related folder.
//In could be don in this same application if I had a solution to consume the scanner in C#.
var proc = System.Diagnostics.Process.Start(#"C:\Program Files\MyProjectFolder\MyScannerAppC++.exe", projectID + " " + param);
}
}
I hope it will help.
Use System.Diagnostics.Process.Start() method.
protected void LinkButton1_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("notepad.exe");
}
You'll have to use C#, but since that's on your post, it should work. You'll also need the full path, if the file is not in your environment path that's loaded in memory.
For a 'regular link' you'd still need to place this in an ASPX page.....
Click me
We're getting really fugly now though.
You can't run an exe file on a website. (First, if it's a Linux server, exe files won't run on it and second, if you're on a Windows server, your host would kill the program immediately. And probably terminate your account.)
That link (assuming it was Play Now!) will just allow your user to download the file. (C:\Program Files\World of Warcraft\ exists on your computer, but it doesn't exist on the web server.)
You could setup a custom protocol on your local OS, if it's Windows, in regedit.
Check out this and this.
Then you create a simple HTML page, and place a link, something like this :
Start!
Given that you registered your custom "presentation" protocol, and configured it correctly in the registry, the application should launch when you click that link.

Setting up policies for an Applet embedded in HTML

I have designed an Applet to take a screenshot and save it on the users computer using the java.awt.Robot class. I need to embedd this applet into an html page (using the object tag) so that when the user clicks a button on the webpage the screenshot is taken.
The applet itself works fine, i've tested it by adding a temporary main method to it and running it on my local machine as a regular java app.
Where I'm having difficulty is setting up permissions to allow it to run from its embedded location. Obviously the robot class is somewhat hazardous so an AWTPermission needs to be established and the applet itself needs to be signed.
I followed through the tutorial at http://download.oracle.com/javase/tutorial/security/toolsign/index.html and succeeded in creating a signed .jar file and then a policy file that allowed the demo application in that tutorial to run. Where I am now running into issues is how to reconcile what I've learned with the situation my applet will be used in.
My target audience comprises around 100 machines and I need it to be executable on all of them. I have packed my java .class file into a .jar and signed it using keytool and jarsigner. I then uploaded the .jar and .cer files to the server directory where the pages in question are hosted.
However: When I then used policytool to create a new policy file on one of the machines to test the setup I am still unable to execute the applet from the HTML. I get Java.Security.AccessControlException Acess Denied java.awt.AWTPermission createRobot errors.
I rather suspect its the policy step that is going awry, so I'll outline the steps I took:
I download the certificate to the local machine and generate a keystore from it, I launch 'policytool' from this directory through the commandline
I add the directory on the local machine where the keystore generated from and my certificate is located.
I then hit the add policy button and enter the SignedBy alias
Then Add Permissions and select AWTPermission
Targets name I select createRobot
The function field I have been leaving blank as I cant think what would apply here
Signed By in this window is also left blank
I then hit 'OK' and 'Done' and get a warning that there is no public key for the alias I've entered in the first step. I do a 'save as' and save my policyfile to the same directory as I put the certificate and the keystore generated from it.
This is not allowing me to run the applet from the webpage however and my limited understanding of this aspect of programming offers no clues as to what has gone wrong.
Ideas, thoughts, observations? If I havent explicitly mentioned something then I havent done it. My biggest suspect is the warning I recieve but I cant seem to find why its appearing
EDIT: Forgot to mention a step. I manually added to my jre\lib\security\java.security file the line 'policy.url.3=file:/C:/Testing/debugpolicy' since thats the path and policy filename I created during the above steps. I also just now managed to remove the warning I mentioned earlier, I'd been mixing up my alias' and gave the alias for the private keystore rather than the public one during policyfile creation, however I still encounter the same problems
If an applet is correctly signed, no policy file is required, nor is it required to separately upload any certificate. A correctly signed applet will prompt the user for permission when the applet is visited, before it loads. Does the prompt appear?
Here is a small demo. I wrote that demonstrates Defensive loading of trusted applets. That is the security prompt I am referring to.
If the applet is both digitally signed by the developer and trusted by the end user, it should be able to take a screen-shot.
There is one other thing you might try if the applet is trusted, just as an experiment (1). Early in the applet init(), call System.setSecurityManager(null). That will both test if the applet has trust, and wipe away the last remnants of the 'trusted' security manager given to applets.
And in the case that works, and it makes the screen capture successful, it suggests either a bug or Oracle changed their mind about the defaults of what a trusted applet could do.
1) Don't do this in a real world or production environment. To quote Tom Hawtin:
This question appears to have given some the impression that calling System.setSecurityManager(null); is okay. ... In case anyone has any doubts, changing global state in an applet will affect all applets in the same process. Clearing the security manager will allow any unsigned applet to do what it likes. Please don't sign code that plays with global state with a certificate you expect anyone to trust.
Edit 1:
Here is the source of the simple applet used in that demo. For some reason when I originally uploaded it, I decided the source was not relevant. OTOH 3 people have now asked to see the source, for one reason or another. When I get a round tuit I'll upload the source to my site. In the mean time, I'll put it here.
package org.pscode.eg.docload;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.security.*;
/** An applet to display documents that are JEditorPane compatible. */
public class DocumentLoader extends JApplet {
JEditorPane document;
#Override
public void init() {
System.out.println("init()");
JPanel main = new JPanel();
main.setLayout( new BorderLayout() );
getContentPane().add(main);
try {
// It might seem odd that a sandboxed applet can /instantiate/
// a File object, but until it goes to do anything with it, the
// JVM considers it 'OK'. Until we go to do anything with a
// 'File' object, it is really just a filename.
File f = new File(".");
// set up the green 'sandboxed page', as a precaution..
URL sandboxed = new URL(getDocumentBase(), "sandbox.html");
document = new JEditorPane(sandboxed);
main.add( new JScrollPane(document), BorderLayout.CENTER );
// Everything above here is possible for a sandboxed applet
// *test* if this applet is sandboxed
final JFileChooser jfc =
new JFileChooser(f); // invokes security check
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfc.setMultiSelectionEnabled(false);
JButton button = new JButton("Load Document");
button.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
int result = jfc.showOpenDialog(
DocumentLoader.this);
if ( result==JFileChooser.APPROVE_OPTION ) {
File temp = jfc.getSelectedFile();
try {
URL page = temp.toURI().toURL();
document.setPage( page );
} catch(Exception e) {
e.printStackTrace();
}
}
}
} );
main.add( button, BorderLayout.SOUTH );
// the applet is trusted, change to the red 'welcome page'
URL trusted = new URL(getDocumentBase(), "trusted.html");
document.setPage(trusted);
} catch (MalformedURLException murle) {
murle.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (AccessControlException ace) {
ace.printStackTrace();
}
}
#Override
public void start() {
System.out.println("start()");
}
#Override
public void stop() {
System.out.println("stop()");
}
#Override
public void destroy() {
System.out.println("destroy()");
}
}