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.
Related
I am developing application in windows phone 10
For some reason, I must handle application state (go to background, enter foreground). I have handle event suspend and resume at App.xaml.cs but it does not works, OnSuspending and OnResuming are not reached. Please help me check my source code and show me how to handle those events.
Here is my code:
public App()
{
Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
Microsoft.ApplicationInsights.WindowsCollectors.Session);
this.InitializeComponent();
this.Suspending += OnSuspending;
Application.Current.Suspending += new SuspendingEventHandler(OnSuspending);
Application.Current.Resuming += new EventHandler<Object>(OnResuming);
}
private void OnSuspending(Object sender, Windows.ApplicationModel.SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
private void OnResuming(object sender, object e)
{
// do some thing
}
You should use the Lifecycle Events dropdown of Visual Studio 2015. It lets you choose between Suspend, Resume or Suspend and Shutdown states.
Whenever you run your app in debug, it never goes to suspended state on its own.
Some doc here: https://blogs.windows.com/buildingapps/2016/04/28/the-lifecycle-of-a-uwp-app/
You are subscribing to suspend event twice
this.Suspending += OnSuspending;
Application.Current.Suspending += new SuspendingEventHandler(OnSuspending);
better leave classic
this.Suspending += OnSuspending;
this.Resuming += App_Resuming;
And also same way add resuming event
private void App_Resuming(object sender, object e)
{
// TODO
}
Do you debug is suspend/resume event works like it's described in this article:
How to trigger suspend, resume, and background events for Windows Store apps in Visual Studio
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 just started developing a Windows Phone 8.1 app.
The app allows the user to add 'data' (strings) to his favorites-list.
Now the question is:
What is the best way to save the list or the single entries of the list so I am able load these favorites again on the next app start?
I thought I should save the data to a (text-) file so I can read it line by line and put the list together again.
What do you think, is this the best way to handle something like this? I am new to the Windows Phone 8.1 platform and any help is really appreciated - thanks!
The best method depends on size of data and your needs. As for saving it in Settings you can try to make an array of string upon save and make list upon loading data. Simple example can look like this:
List<string> favourites = new List<string>();
protected void Method()
{
// save as array
ApplicationData.Current.LocalSettings.Values["myList"] = favourites.ToArray();
// retrive your array and make a list from it
favourites = ((string[])ApplicationData.Current.LocalSettings.Values["myList"]).ToList();
}
Remember that LocalSettings support only simple types and have other limits - for more information take a look at MSDN.
I think i finally got it to work. Should thought about something like that much earlier.
So I got my async Task SaveAppSettingsAsync() and just call it in the Suspending-Event and in my Hardwarebuttons_Pressed-Event when the app closes:
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await SaveAppSettingsAsync();
deferral.Complete();
}
private async void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null)
{
e.Handled = true;
if (rootFrame.CurrentSourcePageType == typeof(MainPage))
{
await SaveAppSettingsAsync();
this.Exit();
}
else if (rootFrame.CanGoBack)
rootFrame.GoBack();
}
}
Thanks for helping. I think I got better at understanding how to handle async tasks now. As I said - I'm new to Windows Phone and never really used them before.
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.
Not sure if the title covers the question well, but here it comes.
I have a project with:
A website: webforms (Aps.net 4,c#) where the user can upload files, interact with them and manually trigger some batch processing
A classlib with all the business logic for the processing
An app that runs on a machine at the customers location and is scheduled to upload files by SFTP to our server.
A console app that is scheduled on the server and does the batch processing for the files that are uploaded by SFTP.
'heavy use customers' use the SFTP app, the others use the website.
The console app and the website both use the same classlib.
What mechanism can I use to send logging/progress information to the website or the console app without implementing two classlibs? I do not want the classlib to be aware that it is called by the console app or the website. For example they also share the same settings. etc.
Any ideas?
Events.
You could add events to the classes that perform the actual business logic in your shared lib. When something happens that requires feedback, you can raise that event in the class.
The consuming application (either the console app or the web-app) can subscribe to those events, and take the appropriate action that is specific to their platform.
A very simplyfied example:
public class SomeLogicClass
{
public event EventHandler SomethingDone;
protected virtual void OnSomethingDone()
{
if( SomethingDone != null )
{
SomethingDone(this, EventArgs.Empty);
}
}
public void DoSomething()
{
// Do some work.
OnSomethingDone();
}
}
In your console-app you can do this, for instance:
var x = new SomeLogicClass();
x.SomethingDone += (s,e) => Console.WriteLine ("Work done.");
x.DoSomething();
The Events idea solves nothing as it will block the main thread and e.g. not be useful for reporting progress in a responsive UI.
Use BackgroundWorker:
public static void Main(string[] args)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.ProgressChanged += ReportProgress;
worker.RunWorkerCompleted += ProgressComplete;
worker.DoWork += DoWork;
worker.RunWorkerAsync();
}
private static void DoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
//Runs on seperate thread
//Do stuff
//(sender as BackgroundWorker).ReportProgress... reports back to main thread
//Do other stuff
}
private static void ProgressComplete(object sender, RunWorkerCompletedEventArgs e)
{
//Executed on main thread
Console.Out.WriteLine("All Done");
}
private static void ReportProgress(object sender, ProgressChangedEventArgs e)
{
//Can be used to asynchronously send status updates or update UI elements on the main thread
Console.Out.WriteLine("{0:P} done", e.ProgressPercentage/100.0);
}