Background Task to record time and write it into file in uwp application - windows-store-apps

Toast notification have a "close button" in the upper right corner.I want to get the current time when user click that "close button" and append the time in the text file in UWP application.
I have tried with ToastNotificationHistoryChangedTrigger while registering background task But in LifeCycleEvents in visual studio it does not shows any events and the code is executed without any error.
builder.Name = "Sample";
builder.TaskEntryPoint = "BackgroundTaskGps.SampleBackgroundTask";
builder.SetTrigger(new T ToastNotificationHistoryChangedTrigger());
BackgroundTaskRegistration taskRegistration = builder.Register();
and In manifest
<Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTaskGps.SampleBackgroundTask">
<BackgroundTasks>
<Task Type="System Event" />
</BackgroundTasks>
</Extension>
</Extensions>
Is there any other way to achive this.

I have tried with ToastNotificationHistoryChangedTrigger while registering background task But in LifeCycleEvents in visual studio it does not shows any events
According to this article:
The debugger can trigger only those events that do not contain data, such as events that indicate a change of state in the device. You have to manually trigger background tasks that require user input or other data.
The ToastNotificationHistoryChangedTrigger requires user to close the notification so it cannot be triggered by debugger. But actually it does work when you close the notification on the action center. The notification official sample has a scenario page about HistoryChangedTrigger which register the ToastNotificationHistoryChangedTrigger and when notification in action center closed by user it will trigger a background task to update the badge of tile. Add writing file logic inside this background task will meet your requirements. Code like follows:
public async void Run(IBackgroundTaskInstance taskInstance)
{
var details = taskInstance.TriggerDetails as ToastNotificationHistoryChangedTriggerDetail;
if (details == null)
return;
StorageFolder localfolder = ApplicationData.Current.LocalFolder;
StorageFile tempfile = await localfolder.CreateFileAsync("temp.txt", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(tempfile, "test time");
...
taskInstance.Progress = (uint)details.ChangeType;
}
Pay attention that this trigger worked for notification closed from action center, closed directly when notification is pushing is not supported. You may custom a button in the notification content to try to interaction with user. If you want to handle activation from a toast notification please reference Handling activation from a toast.

Related

XCode 7 UI Testing: Dismissal of system-generated UIAlertController does not work

I have a UI test which involves the dismissal of a system-generated UIAlertController. This alert asks the user for the permission to access the device's calendar. The objective of the test is the behaviour after a tap on the OK button:
1 let app = XCUIApplication()
...
// this code was basically generated by the recording feature of XCode 7
2 app.alerts.elementBoundByIndex(0).collectionViews.buttons["OK"].tap()
Now, instead of clicking the OK button, line 2 makes the simulator tap onto the first button which happens to be the Cancel button...
Additionally, I found out that the testing framework does not accurately recognize the appearing alert. So if I check the current count of alerts I always get 0:
// ...tap...
let count = app.alerts.count // == 0
This also happens if I use an NSPredicate for the condition and wait for several seconds.
Is it possible that UI tests do not work reliably with system-generated alerts? I am using XCode 7.0.1.
Xcode 7.1 has finally fixed the issue with system alerts. There are, however, two small gotchas.
First, you need to set up a "UI Interuption Handler" before presenting the alert. This is our way of telling the framework how to handle an alert when it appears.
Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.
addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
The "Location Dialog" is just a string to help the developer identify which handler was accessed, it is not specific to the type of alert. I believe that returning true from the handler marks it as "complete", which means it won't be called again.
I managed to dismiss access prompt for contacts like this:
let alert = app.alerts["\u{201c}******\u{201d} Would Like to Access Your Contacts"].collectionViews.buttons["OK"]
if alert.exists
{
alert.tap()
}
Replace asterisks with your app's name. It might work the same for calendar.
This is what I ended up using to get the prompt to appear and then allow access to Contacts:
func allowAccessToContacts(textFieldsName: String)
{
let app = XCUIApplication()
let textField = app.textFields[textFieldsName]
textField.tap()
textField.typeText("aaa")
let alert = app.alerts["\u{201c}******\u{201d} Would Like to Access Your Contacts"].collectionViews.buttons["OK"]
if alert.exists
{
alert.tap()
}
textField.typeText("\u{8}\u{8}\u{8}")
}

Handling back button on launch from secondary tile

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);
}
}

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.
};

Application_Deactivated and Application_Closing events are not triggering after launching ConnectionSettings Task in WP8

I am launching ConnectionSettings Task from Secondary tile.like
ShellTile.Create(new Uri("/Settings.xaml?Tile=miMobile", UriKind.Relative), NewTileData);
in Settings.xaml code is like
if ((Tile == "miMobile"))
await Launcher.LaunchUriAsync(new Uri("ms-settings-cellular:"));
once user changes the settings, based on that settings status I need to update secondary tile's image.
But once settings changed if I click Home button none of the events are triggering(Application_Deactivated,Application_Closing).
How to handle Start button click event?
Thanks.

When should I save application data in WinRT?

In WinRT the Suspended event is supposed to be used to save application data. It is even written in the templates that come with Visual Studio. However when the user closes the app the Suspended event does not fire until 10 seconds later. If the user starts the application in the meantime the data is lost. How should I proceed in this case? I tried other events like page's NavigatedFrom but none of them fired.
You could try this:
Window.Current.Activated += (sender, args) =>
{
if (args.WindowActivationState ==
CoreWindowActivationState.Deactivated)
; //save data
};
If an user close the App he expects the App start from scratch next time. But if user left the App to do another things he expects to return back to the last action.
If you force your app to save state even when user close the app:
How could the user start the app from scratch in any time he wants?