I need detect rebooting or device starting, to do this I followed this topic (Detecting reboot programmatically in Windows Phone 8.1), but in my case the method canceled is never called in background task.
When I starting debug, my method is called after forcing changes in timezone that made by:
builder.SetTrigger(new SystemTrigger(SystemTriggerType.TimeZoneChange, false));
My background task is:
public void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral defferal = taskInstance.GetDeferral();
taskInstance.Canceled += TaskInstance_Canceled;
defferal.Complete();
}
private async void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
BackgroundTaskDeferral defferal = sender.GetDeferral();
try
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
await localFolder.CreateFileAsync("bruno.txt", CreationCollisionOption.OpenIfExists);
}
catch (Exception e)
{
Debug.WriteLine("Fail to create File test: " + e);
}
defferal.Complete();
}
I know that is never called, because the next routine is always in false (it works when app is starting MainPage method):
After using some hours in this problem, I found the solution, Windows Phone have a System Trigger type that is called when device is booted, named: SessionConnected.
Thus, only need simple changes:
builder.SetTrigger(new SystemTrigger(SystemTriggerType.SessionConnected, false));
Related
Reproducible repo here
My app has a WebView for UI and it notifies the backend code by using window.external.notify:
public MainPage()
{
this.InitializeComponent();
this.web.ScriptNotify += this.Web_ScriptNotify;
this.web.Navigate(new Uri("ms-appx-web:///index.html"));
}
private void Web_ScriptNotify(object sender, NotifyEventArgs e)
{
_ = this.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
async () =>
{
var d = new FileOpenPicker();
// Changing UI text is okay
this.lbl.Text = "Hello!";
// Crash here:
var file = await d.PickSingleFileAsync();
});
}
One of the command I want to do is to open a File Picker. However, it crashes with this exception System.Runtime.InteropServices.COMException: 'Unspecified error'. I thought it is because I tried to open it from outside UI thread, so I run it in a Dispatcher already but it still happens.
What should I do?
It crashes because I didn't set FileTypeFilter, not because of the event. Adding this helps:
diagOpen.FileTypeFilter.Add("*");
I am creating a Windows 8.1 Phone App. The UI has a button and a TextBox (called txtStatus)
Basically, when I click a button in the UI, the following code kicks off (only some of it is shown):
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
try
{
// Get the list of Microsoft Bands paired to the phone.
IBandInfo[] pairedBands = await BandClientManager.Instance.GetBandsAsync();
if (pairedBands.Length < 1)
{
txtStatus.Text = "This sample app requires a Microsoft Band paired to your device. Also make sure that you have the latest firmware installed on your Band, as provided by the latest Microsoft Health app.";
return;
}
// Connect to Microsoft Band.
using (IBandClient bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
{
bandClient.SensorManager.HeartRate.ReadingChanged += HeartRate_ReadingChanged;
await bandClient.SensorManager.HeartRate.StartReadingsAsync();
// Receive Accelerometer data for a while, then stop the subscription.
await Task.Delay(TimeSpan.FromSeconds(50));
await bandClient.SensorManager.HeartRate.StopReadingsAsync();
}
}
catch (Exception ex)
{
}
private void HeartRate_ReadingChanged(object sender, Microsoft.Band.Sensors.BandSensorReadingEventArgs<Microsoft.Band.Sensors.IBandHeartRateReading> e)
{
txtStatus.Text = string.Format("Current Heart Rate is: {0}", e.SensorReading.HeartRate.ToString());
}
When I run this code, it barfs at the following line in the handler:
txtStatus.Text = string.Format("Current Heart Rate is: {0}", e.SensorReading.HeartRate.ToString());
The exception message is as follows:
The application called an interface that was marshalled for a
different thread. (Exception from HRESULT: 0x8001010E
(RPC_E_WRONG_THREAD))
It sounds like the UI thread and the Sensor reading thread are different. Any suggestions on how to use the same thread for both. Or how to pass data between the two threads?
Thanks in anticipation.
The event is raised on a background thread. Use CoreDispatcher.RunAsync to marshal it back to the UI thread:
private async void HeartRate_ReadingChanged(object sender, Microsoft.Band.Sensors.BandSensorReadingEventArgs<Microsoft.Band.Sensors.IBandHeartRateReading> e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
txtStatus.Text = string.Format("Current Heart Rate is: {0}", e.SensorReading.HeartRate.ToString())
}).AsTask();
}
I wrote a Windows Phone 8.1 (WINRT) App. I am trying to share an image from my app which is in LocalStorage of the app. I am using Windows Phone 8.1 Share Contract.
private async void OnShareDataRequested(DataTransferManager sender, DataRequestedEventArgs _dataRequestedEventArgs)
{
_dataRequestedEventArgs.Request.GetDeferral();
List<StorageFile> ListObject = new List<StorageFile>();
Uri UriObject = new Uri(FileLocation,UriKind.RelativeOrAbsolute);
_dataRequestedEventArgs.Request.Data.Properties.Title = "Dr. App";
_dataRequestedEventArgs.Request.Data.Properties.Description = "Photo from my Dr. App Album.";
StorageFolder StorageFolderObject;
StorageFile StorageFileObject;
try
{
StorageFolderObject = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFolderAsync(LocalCache);
StorageFileObject = await StorageFolderObject.GetFileAsync(FileNameSaved);
_dataRequestedEventArgs.Request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(StorageFileObject);
_dataRequestedEventArgs.Request.Data.SetBitmap(RandomAccessStreamReference.CreateFromFile(StorageFileObject));
ListObject.Add(StorageFileObject);
_dataRequestedEventArgs.Request.Data.SetStorageItems(ListObject);
}
catch(Exception ex_)
{
}
finally
{
_dataRequestedEventArgs.Request.GetDeferral().Complete();
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested -= OnShareDataRequested;
base.OnNavigatedFrom(e);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested += OnShareDataRequested;
base.OnNavigatedTo(e);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DataTransferManager.ShowShareUI();
}
I am getting PREPARING CONTENT TO SHARE and then it vanishes in a second. ShareUI doesnt open.
The documentation states that the asynchronous work has an upper limit of 200 ms. Are you violating this premise?
DataRequest.GetDeferral(): Use this method when you want to use an asynchronous function call to generate the DataPackage during a share operation. This function must return a DataPackage object within 200ms to prevent the operation from timing out. If your app shares content that takes more time to package, such as a collection of files or photos, don't use this method. Instead, use the SetDataProvider method to assign a delegate to a DataPackage and return that DataPackage to the target app.
Another thing that stands out to me when I look at your code is that you invoke the GetDeferral method twice instead of saving the result from the first invocation.
I have a question regarding saving/loading data in Windows Universal Apps 8.1.
I cannot seem to save the data when exiting the app. My call to the serialization is done in the OnSuspending method in App.xaml.cs, but I don't think it is called whenever I close the app.
It sometimes saves the data, sometimes not. Here is my code for OnSuspending and Save methods.
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
// TODO: Save application state and stop any background activity
Debug.WriteLine("SUSPENDING");
HabitManager.HabitSerializer.Save();
deferral.Complete();
}
public async static void Save()
{
Debug.WriteLine("SAVED");
var json = JsonConvert.SerializeObject(HabitList.Instance.GetHabits());
var habits = HabitList.Instance.GetHabits();
foreach (var h in habits)
{
Debug.WriteLine("S: " + h);
}
StorageFile saveFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteTextAsync(saveFile, json);
}
So my question is, what could be the problem, and if this isn't a good serializing mechanism, can you suggest me a better one? Thank you
Your OnSuspending call returns before the Save call finishes.
Change Save to return a Task so you can await it:
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
// TODO: Save application state and stop any background activity
Debug.WriteLine("SUSPENDING");
// Wait fir Save to finish its a sync operations
await HabitManager.HabitSerializer.Save();
deferral.Complete();
}
public async static Task Save()
{
// Same save code
}
Also be careful when testing suspension. The app won't suspend normally while debugging, but VS provides a suspend button to simulate the suspension process.
I want to save the application state when an metro style app receive the suspend event.
I found in this link the code below, but I donĀ“t find in .Net the class ApplicationStateModel:
public App()
{
InitializeComponent();
this.Suspending += new SuspendingEventHandler(App_Suspending);
this.Resuming += new Windows.UI.Xaml.EventHandler(App_Resuming);
}
void App_Resuming(object sender, object e)
{
// Write code to update ui only for items that are outdated.
// This is resume from suspended state, so it does not lose any data
}
async void App_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e)
{
// Write code to store data so that when the application is terminated the state can be recovered.
// Allowed only 5 seconds to do the storage
SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral();
await **ApplicationStateModel**.SaveAllApplicationDataAsync();
await ApplicationStateModel.SaveSessionStateAsync();
deferral.Complete();
}
You can use Windows.Storage.ApplicationData to save local settings.
Take a look at the Sample SDK app for a running app that saves your settings.