NSApplication.SharedApplication.Terminate doesn't actually terminate my application after unhandled exception - terminate

I am developing a simple application for OSX with MonoMac. When my application experiences unhandled exceptions, I catch them with:
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
Unhandled(e.ExceptionObject as Exception);
Inside the function Unhandled(), I log the exception and run a modal window to inform the user that something went wrong.
I then proceed to test this by throwing a regular Exception somewhere in the application. The crash report window appears as it should, and the error is logged.
But after this window has been closed, I would expect the application to quit, as it would have done if I hadn't caught the error. It does not; the application's main window and the dock icon are still there, but the window is completely frozen.
If I remove the above code line, the application closes completely when it crashes.
I try to force the application to quit by calling:
NSApplication.SharedApplication.Terminate(myAppDelegate);
But this seems to do nothing at all. I use the exact same code line in the application's Quit button, and there it works as expected, so there must be something special about the application state after catching an unhandled exception. But what?
I have overriden the following in my AppDelegate just in case, but it doesn't seem to make any difference:
public override NSApplicationTerminateReply ApplicationShouldTerminate (NSApplication sender)
{
return NSApplicationTerminateReply.Now;
}
I thought that maybe displaying a modal form did something to the application state, but after testing I see that whether I show the modal form or not makes no difference. Still the frozen main window instead of closing.
EDIT: I must've done something wrong when testing this. It actually works as it should if I don't display the error form.
Any ideas?

I don't have an answer for you exactly, and a comment wouldn't hold my code sample; but I can tell you that I'm conceptually doing almost exactly the same thing in my application and it works just fine. My code:
private static void OnException(Exception ex)
{
new NSObject().InvokeOnMainThread(() => {
try
{
using (ErrorWindowController frmErrorMessage = new ErrorWindowController(ex))
{
Console.WriteLine(ex);
NSApplication.SharedApplication.RunModalForWindow(frmErrorMessage.Window);
}
}
finally
{
NSApplication.SharedApplication.Terminate(NSApplication.SharedApplication);
}
});
}
EDIT:
Make sure you are stopping the modal session when you close the window, or the call to RunModalForWindow will never return.
I close my modal window using a button, something like this:
partial void butClose_Click(NSObject sender)
{
this.Window.OrderOut(sender);
this.Window.Close();
NSApplication.SharedApplication.StopModal();
}

Related

When $ionicView.enter is really triggered

Having this function in a controller:
$scope.$on('$ionicView.enter', function() {
seemed to be good. Everytime I open the app in the real device, this functions is actually triggered. But then, after a while I realized that this is not always true.
If I open my app, and then close it. And then some time goes, maybe a few minutes. And I open the app again. Well, then the app doesnt start from scratch. It goes back to latest screen/controller I was. And, worst of all, the $ionicView.enter is NOT fired.
If the app is closed and I open again after a while (maybe 5 minutes) then it starts from beginning (showing splash etc).
So, is there a way to solve this issue? How to make the app react going into $ionicView.enter each time it is opened again? Even if picked up from background?
You could use resume event when the app picked up from background, like below:
document.addEventListener("resume", onResume, false);
function onResume() {
setTimeout(function() {
// TODO: do your thing
}, 0);
}

Click Event handler

when i click on a button the click event handler executes a code . If by mistake(if browser hangs) i click on the button twice the code gets executed twice.i dont want that to happen.
Any suggestions to stop that?
i suppose i should use a schedular or timer but i am not sure
below is the code:
public void onSendButtonClicked() {
disableButtons();
eventBus.fireEvent(new SendEmcsDeclarationEvent(getDeclaration(), getMsgType()));
}
You can - as Abdullah mentioned - disable/enable every widget in GWT with
widget.setEnable(false)
and
widget.setEnable(true).
If you want to lock the whole screen, create a modal popup, show it, after the button is pressed and hide it, after the code has finished.
public void onSendButtonClicked() {
myProgessBar.show();
eventBus.fireEvent(new SendEmcsDeclarationEvent(getDeclaration(), getMsgType()));
myProgressBar.hide();
}
If you are using a async call, you have to hide the progessbar in the callbacks. In this case the finally command might be executed before the callback is executed. In your case it might be a good idea to create a ShowProgressBarEvent and HideProgressbarEvent, so that you can use the progressbar in your whole application.
If your are using a widget library f.e.: GXT, you will find a ProgressBar ready to use.
Hope that helps.
The best way I can think of is to enable/disable the button itself so as to make sure that the code in handler is not called again until before the previous call finishes up.
public void onSendButtonClicked()
{
try
{
disableButtons();
eventBus.fireEvent(new SendEmcsDeclarationEvent(getDeclaration(), getMsgType()));
}
catch (Exception ex)
{
throw ex;
}
finally
{
enableButtons();
}
}
When I create a button, I always also add an animating gif (ajaxloader).
When the button is clicked I make the button invisble, the ajaxloader visible.
When the action is done, I make the ajaxloader invisible, and the button visible.
This way the user has some visual feedback that something is happening (what you don't get when disabling the button), and not the entire application gets blocked (as a modal does) which is one of the plus points using ajax.

Back and volume buttons not working when app is resumed in certain conditions

I'm starting a new activity to display a leaderboard in my Android App.
When the leaderboard activity is displayed, and the user presses the home key and then resumes the app (so the leaderboard activity comes up again), and then navigates back to the main activity by pressing the back key, the back key and volume keys stop working).
I've attempted to override onBackPressed in my activity class. I can confirm that when this problem occurs, onBackPressed is not called (When back / volume is working, pressing back does trigger onBackPressed).
Normally I get a message in LogCat when I press the back key 'Unimplemented WebView method onKeyDown called from android.webkit.WebView,onKeyDown(WebView.java.2178)' - Again I can confirm that this message doesn't come up when the back key isn't working
Armed with the above information, I can only assume that it's something to do with the View not having focus or something along those lines. I would point out that touch input on the screen itself does work. It just seems to be the back and volume keys/buttons that have no effect.
It's an openGL ES 2.0 app so in my onPause() I'm calling view.onPause(); and in onResume, I'm calling view.onResume();
I really have no idea what's going on and I've been on this for 3 days straight so if anyone can point me in the right direction, that would be great.
If the user comes out of the leaderboard and back into the main app before they press the home key, then everything is OK, it's just if the home key is pressed while the leaderboard activity is displayed as described above.
So when I'm at the point where the back / volume keys aren't working, if I click my scores button and fire up the leaderboard activity again, they work. On returning to my activity, they stop working again.
Not sure if this is relevant at all but the following shows how I'm starting my leaderboard activity:
if (scoresButtonPresses){
displayLeaderBoard();
}
void displayLeaderBoard(){
//Display the leaderboard if already signed in
if (checkSignedIn()){
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(getApiClient(), leaderboardID), 1);
}
//if not already connected, then set flag and connect to play services before displaying leaderbaord
else{
signInAction=SHOW_LEADERBOARD;
getGameHelper().beginUserInitiatedSignIn();
}
}
#Override
public void onSignInSucceeded() {
//If the flag is set, then display the leaderboard
if (signInAction==DISPLAY_LEADERBOARD){
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(getApiClient(), leaderboardID), 1);
}
//Otherwise, reset the flag and take no action
else {signInAction=NO_ACTION;}
}
This is driving me crazy so any help or even a nudge in the right direction would be very much appreciated!!
Edit
After much testing I have learned a couple of things:
If I remove the view.onPause() && view.onResume() the problem seems to go away. So this appears to be something to do with the way key events are captured by the view. Pausing and resuming seems to mess something up.
I have also tried removing the view.onPause() and view.onResume() as above, but instead, putting in View.setVisibility(View.GONE); and then making it visible again in public void onWindowFocusChanged(boolean hasFocus). Again, I get the same problem. Interestingly, when I open the leaderboard, as expected the view's staus is 'gone' then hitting the home key and running the app again, it's set back to 'visible' - I don't understand this behaviour but I'll ask another question for that.
Lastly, and this I find really odd. If I put my app back to as I had it, then after hitting the home key and relaunching the app via Eclipse (and I can do this multiple times) the problem doesn't seem to occur. So in that respect, it appears to be something to do with touching the screen.
Edit
It appears as though this isn't limited to my app. I've tested this on a couple of other apps from the Play store and get the same result.
One app clearly uses a single activity model like mine and the back and volume stop working throughout the app.
The other may use a different activity for it menu and game. When I test on this app, the back/volume breaks but if you start a game (therefore a second activity), the back key starts working again, even when you return to the first activity (recreated this activity?!)
So maybe I can get around this by ensuring the activity is recreated? I thought i was already but maybe I'm not getting something. Maybe it's something to do with the stack.........
I have no solution to your problem but some additional insights since I'm facing the same bug/problem with the leaderboards and the back button (and it's driving me crazy).
I'm using a single activity with fragments from which I login to Google Play, open Leaderboards and Achievements in the exact way you are doing it (startActivityForResult). Always when I come back from any Google Play Service activity my back button is broken. Sometimes it's even enough if I try to login to Google Play for it to break, meaning the login popup sometimes breaks the back button (but not always).
Some more insights which might help to solve the problem:
I'm not using OpenGL, so it's not related to this - I'm just using a single activity and fragments
It's also breaking for me when I just use the back button for going back from any Google Play Activity (I don't even need to go via the home key, just normal back is enough).
When the back button is broken the Activity is not receiving any Key Events (OnKeyDown, OnKeyUp, dispatchKeyEvent) are all not working, although using the activity and touching it fully works. My guess is that some view is catching the events...
Edit:
I also tried checking activity.getCurrentFocus() and activity.hasWindowFocus() as well as the parent and context classes of activity.getCurrentFocus() to see if there is any difference between when it's working and when it's not - and there isn't any difference...
Edit:
It seems that a simple call to View.requestFocus() is fixing the problem. For my single activity (using fragments implementation) I have now added:
#Override
public void onResume(){
super.onResume();
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragmentContainer);
fragment.getView().requestFocus();
}
and this seems to be fixing the problem. Sill have to do long term checking if it's always fixed. In your OpenGL implementation I guess you will have to get the main view of the activity in some other way since you are not using fragments.
I know it's pretty old question, but for clarification: accepted answer is correct, but incomplete. Focus requesting should be done in onResume, onActivityResult, onSignInSucceeded and onSignInFailed. In first two you have! to call super. Some code:
private void requestFocusAfterGooglePlay(){
if(gimmeFocus==null)
return;
View currFocus=getCurrentFocus();
gimmeFocus.setFocusableInTouchMode(true);
gimmeFocus.setFocusable(true);
gimmeFocus.requestFocus();
gimmeFocus.setFocusableInTouchMode(false);
gimmeFocus.setFocusable(false);
if(currFocus!=null)
currFocus.requestFocus();
}
#Override
public void onSignInFailed() {
requestFocusAfterGooglePlay();
}
#Override
public void onSignInSucceeded() {
requestFocusAfterGooglePlay();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
requestFocusAfterGooglePlay();
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onResume(){
super.onResume();
requestFocusAfterGooglePlay();
}
in my case gimmeFocus is a dummy View created as below:
<View
android:id="#+id/gimme_focus"
android:layout_width="0px"
android:layout_height="0px"
android:focusable="false"
android:focusableInTouchMode="false"/>
I have dynamic layout so I can't never be sure that any view exists in my layout, so I've created this dummy View, it might be also added programmatically. You might choose your fixed View for gaining focus, but rembember that changing focus might change view's look (drawable state).

How to close a dialog in code?

So I'm making a eclipse plugin and I have a made my own dialog by extending the dialog class.
My dialog basically populates a treeview with data from a server. Sometimes the data cannot be populated (because the server is down) so my treeview is empty.
I have made another dialog appear reporting the error if I am unable to connect to the server.
My problem is that I would like to close the initial dialog when I press ok in the error dialog.
I have not been able to find a good way to do this.
I have tried setting setBlockOnOpen to false.
I have tried calling cancelPressed.
Neither of them have worked.
I called them in the createDialogArea function.
Any Ideas on how I could get this to work?
It is basically user cancelling dialog. you need to invoke cancelPressed() so it will be consistent handling if you have any code that depends on returnCode
if(noDataLoaded){
Display.getDefault().asyncExec(new Runnable() {
public void run() {
cancelPressed():
}
});
}
You need to do the close call after the dialog creation has finished. You can do this by using this code:
parent.getDisplay().asyncExec(new Runnable()
{
#Override
public void run()
{
close();
}
});
in your createDialogArea method. However the dialog may appear briefly. It would be better to do your check before creating the dialog.

How do I close the splash screen in an eclipse RCP application?

In an eclipse RCP application, a splash.bmp is used as the splash screen. It closes after about 5-6 minutes of the application being run. I want it to close as soon as some UI displays. I tried using Platform.endSplash() and also applicationRunning() of the application context just before PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor()).
It fails to close the splash screen.
Any suggestions would be helpful. It would also be okay if I could close the splash screen after about 10 -15 seconds.
public Object start(IApplicationContext arg0) throws Exception {
Display display = PlatformUI.createDisplay();
int returnCode = 0;
try {
//arg0.applicationRunning();
Platform.endSplash();
returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART) {
return PlatformUI.RETURN_RESTART;
}
return PlatformUI.RETURN_OK;
} finally {
//some other code here.
display.dispose();
}
}
I would expect the splash screen to close when everything is initialized, not after a set amount of seconds. Otherwise you don't even need one.
According to this thread, you should make sure to call the Platform.endSplash() method in the right context, meaning the method start(IApplicationContext context)
If you already do this, please provide some code to help us understand your problem
The closing of a splash screen is handled by the created StartupMonitor in Workbench.
After the workbench part is created (as you say, "as soon as some UI displays"), it will be cycling through all registered startup services. The fact that you have your workbench visible and have to wait ~5-6 minutes (or seconds) for your splash screen to close means you have another startup monitor preventing your desired UI transition.