XNA application crashed after hibernate - xna

I create simple XNA fullscreen application. If it is active and the system goes into sleep mode or hibernate mode after resume the application is crashed. How can I solve this problem?
UPD:
I added handler for system message
public Game()
{
SystemEvents.PowerModeChanged += OnPowerChange;
this.graphics.PreferredBackBufferWidth = 1920;
this.graphics.PreferredBackBufferHeight = 1080;
this.graphics.PreferredBackBufferFormat = SurfaceFormat.Bgr565;
this.graphics.IsFullScreen = true;
}
void OnPowerChange(Object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Suspend:
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
graphics.ToggleFullScreen();
graphics.ApplyChanges();
break;
}
}
If application is in window mode, then OnPowerChange() work fine and change resolusion from 1920x1080 to 800x600. But if application is fullscreen mode, then this method not called. Also, I get runtime error here
static void Main(string[] args)
{
using (Game game = new Game())
{
game.Run();
}
}
Error is: Cannot access a disposed object. Object name: 'WindowsGameForm'.

Related

Please point me in the correct direction to understand how to run in the background in iOS

I'm working on a fitness app (using Xamarin) and would like it to continue running in the background if the user switches to another app or pushes the side button to blank out the screen. I have looked at multiple tutorials, include this one https://robgibbens.com/backgrounding-with-xamarin-forms/, which seemed very promising. However, when running my app and switching to another application or blanking the screen, my app simply suspends. Hers is the iOS specific code that starts the background task:
public class IOSPlayWorkoutTask
{
nint _taskID;
CancellationTokenSource _cts;
Workout _workout;
public async Task Start()
{
_cts = new CancellationTokenSource();
_taskID = UIApplication.SharedApplication.BeginBackgroundTask("IOSPlayWorkoutTask", OnExpiration);
try
{
WorkoutPlayer.Shared.Workout = _workout;
await WorkoutPlayer.Shared.PlayWorkout(_cts.Token);
}
catch (OperationCanceledException)
{
}
finally
{
if (_cts.IsCancellationRequested)
{
//Device.BeginInvokeOnMainThread(
// () => MessagingCenter.Send(new CancelPlayingWorkoutMessage(), CancelPlayingWorkoutMessage.MessageText));
}
}
UIApplication.SharedApplication.EndBackgroundTask(_taskID);
}
public void Pause()
{
WorkoutPlayer.Shared.RequestPause();
_cts.Cancel();
Device.BeginInvokeOnMainThread(
() => MessagingCenter.Send(new PausedWorkoutMessage(), PausedWorkoutMessage.MessageText));
}
public void Stop()
{
_cts.Cancel();
Device.BeginInvokeOnMainThread(
() => MessagingCenter.Send(new FinishedWorkoutMessage(), FinishedWorkoutMessage.MessageText));
}
void OnExpiration()
{
_cts.Cancel();
}
public IOSPlayWorkoutTask(Workout w)
{
_workout = w;
}
}
The iOS app delegate registers to receive messages, one of which starts the task above. I know I must be missing something very basic. Any help would be greatly appreciated. I know this has to be possible based on my experience using other fitness apps like Couch to 5k.
Thanks #sushihangover and #Paulw11 for your input. Looks like the secret is adding a handler to BeginBackgroundTask that calls EndBackgroundTask. Not sure I understand fully at this point, but apparently this give iOS the impression that you are a "good citizen", but continues processing your task. Here is my code that works:
public async Task Start()
{
_cts = new CancellationTokenSource();
//_taskID = UIApplication.SharedApplication.BeginBackgroundTask("IOSPlayWorkoutTask", OnExpiration);
_taskID = UIApplication.SharedApplication.BeginBackgroundTask(() =>
{
Console.WriteLine("Guess my time is up");
UIApplication.SharedApplication.EndBackgroundTask(_taskID);
});
try
{
WorkoutPlayer.Shared.Workout = _workout;
await WorkoutPlayer.Shared.PlayWorkout(_cts.Token);
//finished = true;
}
catch (OperationCanceledException)
{
Console.WriteLine("OperationCanceledException");
//finished = true;
}
finally
{
if (_cts.IsCancellationRequested)
{
//Device.BeginInvokeOnMainThread(
// () => MessagingCenter.Send(new CancelPlayingWorkoutMessage(), CancelPlayingWorkoutMessage.MessageText));
}
}
UIApplication.SharedApplication.EndBackgroundTask(_taskID);
}

Xamarin iOS - Handling Geofence intersection triggers after terminating an app

I am trying to handle geofence intersection triggers when my app is terminated (not background). I want handle the enter/exit triggers from CLLocationManager even if my app is not running. It should wake up my app at the background, do the required processing on enter/exit.
To do this, a lot of places its given that it is possible using background app refresh functionality. I have the following code written but as soon as i terminate the application, it stops hearing the geofence trigger events.
Can anybody please guide me how to handle these events even if application is terminated ?
public async Task StartLocationUpdates()
{
_cts = new CancellationTokenSource();
_taskId = UIApplication.SharedApplication.BeginBackgroundTask("LongRunningTask", OnExpiration);
try
{
if (CLLocationManager.LocationServicesEnabled)
{
LocMgr.DesiredAccuracy = 1;
LocMgr.LocationsUpdated += (object sender, CLLocationsUpdatedEventArgs e) =>
{
var locations = e.Locations;
};
LocMgr.StartUpdatingLocation();
if (CLLocationManager.LocationServicesEnabled)
{
if (CLLocationManager.Status != CLAuthorizationStatus.Denied)
{
if (CLLocationManager.IsMonitoringAvailable(typeof(CLCircularRegion)))
{
LocMgr.DidStartMonitoringForRegion += (o, e) =>
{
Console.WriteLine("Now monitoring region {0}", e.Region.ToString());
};
LocMgr.RegionEntered += (o, e) =>
{
Instance.Speak("Just entered " + e.Region.ToString());
};
LocMgr.RegionLeft += (o, e) =>
{
Instance.Speak("Just left " + e.Region.ToString());
};
foreach (CLCircularRegion region in RegionList)
{
if (region != null)
{
StopMonitoringRegion(region);
}
LocMgr.StartMonitoring(region);
}
}
else
{
Console.WriteLine("This app requires region monitoring, which is unavailable on this device");
}
LocMgr.Failed += (o, e) =>
{
Console.WriteLine(e.Error);
};
}
else
{
Console.WriteLine("App is not authorized to use location data");
}
}
else
{
Console.WriteLine("Location services not enabled, please enable this in your Settings");
}
}
}
catch (OperationCanceledException)
{
}
}
Thank You in advance.
It seems you have added the privacy keys in the info.plist to enable the location service. If you want to enable it when the app is on background state or terminated, we also should turn on the Background Modes: Capabilities > Background Modes > Location updates.
Then we can initialize the location manager in AppDelegate:
CLLocationManager locationManager;
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
locationManager = new CLLocationManager();
locationManager.Delegate = new MyLocationDelegate();
//enable service when app is on background or terminated
locationManager.PausesLocationUpdatesAutomatically = false;
locationManager.AllowsBackgroundLocationUpdates = true;
locationManager.RequestAlwaysAuthorization();
locationManager.DistanceFilter = 100.0;
locationManager.DesiredAccuracy = 1;
// The important request can awake your app
locationManager.StartMonitoringSignificantLocationChanges();
locationManager.StartUpdatingLocation();
return true;
}
The event LocationsUpdated() will also fire if your location has been changed even your app has been terminated:
public class MyLocationDelegate : CLLocationManagerDelegate
{
public override void LocationsUpdated(CLLocationManager manager, CLLocation[] locations)
{
//Handle your method here
}
}
You can test this with your simulator: Debug > Location > Freeway Drive. Store the locations to your sandbox folder in the event above. Force quit your app, after a few seconds open it, retrieve the file you stored. You will find the whole locations records.

Gluon iOS audio Player

I've been following various answers to various questions on the subject and I've come to a result and some code which looks like it works. I'm getting stuck with the NSURL part of it. I've got 2 mp3 tracks in the assets folder of my iOS gluon project. I've made the IOSAudioService Class to handle the playback. and I'm passing an argument from the play button in the view to the Play() method. Everything other than the actual file is registering as working. I'm getting an NSError, which from looking at the code is a nil value, so either the argument isn't passing correctly or it can't find the file. Code below.
public AVAudioPlayer backgroundMusic;
private double currentPosition;
NSURL songURL = null;
#Override
public void Play(String filename){
songURL = new NSURL(filename);
try {
if (backgroundMusic != null) {
Resume();
}
else {
//Start the audio at the beginning.
currentPosition = 0;
backgroundMusic = new AVAudioPlayer(songURL);
//create the mendia player and assign it to the audio
backgroundMusic.prepareToPlay();
backgroundMusic.play();}
//catch the audio error
} catch(NSErrorException e) {
System.out.println("error: " + e);
}
}
#Override
public void Stop() {
backgroundMusic.stop();
backgroundMusic = null;
}
#Override
public void Pause() {
currentPosition = backgroundMusic.getCurrentTime();
backgroundMusic.pause();
}
#Override
public void Resume() {
backgroundMusic.setCurrentTime(currentPosition);
backgroundMusic.play();
}
try {
services = (AudioService) Class.forName("com.gluonhq.charm.down.plugins.ios.IOSAudioService").newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
System.out.println("Error " + ex);
}
I'm getting the error at the catch block for NSExceptionError e.
if (services != null) {
final HBox hBox = new HBox(10,
MaterialDesignIcon.PLAY_ARROW.button(e -> services.Play("/audio.mp3")),
MaterialDesignIcon.PAUSE.button(e -> {
if (!pause) {
services.Pause();
pause = true;
} else {
services.Resume();
pause = false;
}
}),
MaterialDesignIcon.STOP.button(e -> services.Stop()));
//set the HBox alignment
hBox.setAlignment(Pos.CENTER);
hBox.getStyleClass().add("hbox");
//create and set up a vbox to include the image, audio controls and the text then set the alignment
final VBox vBox = new VBox(5, Image(), hBox, text1);
vBox.setAlignment(Pos.CENTER);
setCenter(new StackPane(vBox));
} else {
//start an error if service is null
setCenter(new StackPane(new Label("Only for Android")));
}
Services.get(LifecycleService.class).ifPresent(s -> s.addListener(LifecycleEvent.PAUSE, () -> services.Stop()));
}
I've also follow the advice on creating the service factory class and the interface from Audio performance with Javafx for Android (MediaPlayer and NativeAudioService) taking out the add audio element and I'm intending to do this on a view by view basis if possible.
Problem solved after must fiddling and looking in the Javadocs.Solved by adding/replacing some code with the below.
songURL = new NSURL("file:///" + NSBundle.getMainBundle().findResourcePath(filename, "mp3"));
try {
songURL.checkResourceIsReachable();}
catch(NSErrorException d) {
System.out.println("Song not found!" + d);
}

Difficulty updating InkPresenter visual after removing strokes?

I am creating an inkcanvas (CustomInkCanvas) that receives Gestures. At different times during its use, I am placing additional panels over different parts of the inkcanvas. All is well, and the part of the CustomInkCanvas that is not covered by another panel responds appropriately to ink and gestures.
However, occasionally a Gesture is not recognized, so in the default code of the gesture handler, I am trying to remove the ink from the CustomInkCanvas--even when it is not the uppermost panel.
How is this done?
Note: I have tried everything I can think of, including:
Dispatcher with Background update as:
cink.InkPresenter.Dispatcher.Invoke(DispatcherPriority.Background, EmptyDelegate);
Clearing the strokes with:
Strokes.Clear();
cink.InkPresenter.Strokes.Clear();
Invalidating the visual with:
cink.InkPresenter.InvalidateVisual();
cink.InavlidateVisual();
And even
foreach (Stroke s in Strokes)
{
cink.InkPresenter.Strokes.Remove(s);
}
Here is the full code...
void inkCanvas_Gesture(object sender, InkCanvasGestureEventArgs e)
{
CustomInkCanvas cink = sender as CustomInkCanvas;
ReadOnlyCollection<GestureRecognitionResult> gestureResults = e.GetGestureRecognitionResults();
StylusPointCollection styluspoints = e.Strokes[0].StylusPoints;
TextBlock tb; // instance of the textBlock being used by the InkCanvas.
Point editpoint; // user point to use for the start of editing.
TextPointer at; // textpointer that corresponds to the lowestpoint of the gesture.
Run parentrun; // the selected run containing the lowest point.
// return if there is no textBlock.
tb = GetVisualChild<TextBlock>(cink);
if (tb == null) return;
// Check the first recognition result for a gesture.
isWriting = false;
if (gestureResults[0].RecognitionConfidence == RecognitionConfidence.Strong)
{
switch (gestureResults[0].ApplicationGesture)
{
#region [Writing]
default:
bool AllowInking;
editpoint = GetEditorPoint(styluspoints, EditorPoints.Writing);
at = tb.GetPositionFromPoint(editpoint, true);
parentrun = tb.InputHitTest(editpoint) as Run;
if (parentrun == null)
{
AllowInking = true;
TextPointer At = tb.ContentEnd;
Here = (Run)At.GetAdjacentElement(LogicalDirection.Backward);
}
else
{
Here = parentrun;
AllowInking = String.IsNullOrWhiteSpace(parentrun.Text);
}
*** THIS FAILS TO REMOVE THE INK FROM THE DISPLAY ???? *********
if (AllowInking == false)
{
foreach (Stroke s in Strokes)
{
cink.InkPresenter.Strokes.Remove(s);
}
// remove ink from display
// Strokes.Clear();
// cink.InkPresenter.Strokes.Clear();
cink.InkPresenter.InvalidateVisual();
cink.InkPresenter.Dispatcher.Invoke(DispatcherPriority.Background, EmptyDelegate);
return;
}
// stop the InkCanvas from recognizing gestures
EditingMode = InkCanvasEditingMode.Ink;
isWriting = true;
break;
#endregion
}
}
}
private static Action EmptyDelegate = delegate() { };
Thanks in advance for any help.
It would be nice to get a guru response to this, but for anybody else getting here, apparently the strokes that go into creating the gesture have not yet been added to the InkCanvas, so there is nothing to remove or clear from the inkcanvas from within the gesture handler. Strokes are only added to the InkCanvas AFTER the gesture handler. The solution this newbie ended up with was to set a flag when ink was not allowed, and then act on it in the StrokesChanged handler like:
if (AllowInking == false)
{
ClearStrokes = true;
return;
}
void Strokes_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
{
if (ClearStrokes == true)
{
ClearStrokes = false;
Strokes.Clear();
return;
}
All works now. Is there a better way?

BlackBerry application unistallation problem?

In my balckberry application i am using the Persistance,List and Threads to execute the code.
The code is given below:
enter code here
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
CategoryListScreen.getInstance(
UiApplication.getUiApplication())
.setCategoryListContent();
}
});
public void setCategoryListContent() {
categoryList.delete(0);
CategoryListScreen categoryListScreen = CategoryListScreen
.getInstance(UiApplication.getUiApplication());
PersistentObject categoryListPersistObject = PersistentStore
.getPersistentObject(0x73c8d3592648fea5L);
PersistentObject datePersistObject = PersistentStore
.getPersistentObject(0xe453c1c0c14b9aebL);
categoryListPersistObject.setContents(Communicator.categoryDatas);
datePersistObject.setContents(new Date());
categoryListScreen.setCategoryListVector(new Vector());
categoryDataList = Communicator.categoryDatas;
System.out.println("-------------------- " + Communicator.categoryDatas.length);
for (int i = 0; i < Communicator.categoryDatas.length; i++) {
if (Communicator.categoryDatas[i] != null) {
if (Communicator.categoryDatas[i].getName() != null) {
categoryListScreen.getCategoryListVector().addElement(
Communicator.categoryDatas[i].getName());
}
}
}
testListCallback = new ListCallback();
categoryList.setCallback(testListCallback);
int i = categoryListScreen.getCategoryListVector().size();
categoryListScreen.getCategoryList().setSize(i);
System.out.println("---------------------->" + categoryListScreen.getCategoryListVector().size());
//
categoryListScreen.getCategoryList().setRowHeight(40);
// categoryListScreen.invalidate();
invalidate();
System.out.println("End.........................");
}
The application is Using the Threads to execute the persistance and also setting the size of the list.The application is running fine and exiting successfully.
But at the time of unistalling the application the device get being restarted and also after restarting the application ,there is no effect on the application.The application still remains there.
what is the problem in uinstalling the application which uses Threads,persistance and list?
why is it being restarted without any user confirmation or alert?
why is it not get being uninsall after restart?
please give the resolution for the given problem or any useful code snippet ,which would be appreciated.
Thanks,
Mishal Shah
Is this on a device simulator or a real device? As far as I know, if you reset the simulator, it loads back all the installed apps onto to simulator.

Resources