Closing Mvvmcross tutorial with back button - xamarin.android

If I run the implementation of the tutorial being on the MainMenuView and pressing back will exit the application, but in my app it just goes to SplashScreenView and is redirected back to MainMenuView and I cant find where in the tutorial its specified or overrided what happens when the back button is clicked
EDIT:
Solution found here https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20Tutorial/Tutorial/Tutorial.UI.Droid/SplashScreenActivity.cs
[Activity(Label = "Tutorial.UI.Droid", MainLauncher = true, NoHistory = true, Icon = "#drawable/icon")]
public class SplashScreenActivity
: MvxBaseSplashScreenActivity
{
public SplashScreenActivity()
: base(Resource.Layout.SplashScreen)
{
}
protected override void OnViewModelSet()
{
// ignored
}
}

There's no hidden code for this - its just the android back stack.
Are you sure your app is actually exiting cleanly? It sounds a bit like your app is crashing and being restarted? Check the debug log to find out.
Alternatively it might also be that you have missed the nohistory flag on the splashscreen

Related

Xamarin Forms Plugin.Share not working for unknown reason

We have an image with a gesture recognizer, which calls the CrossShare.Current.Share method. On Android this works fine but on iOS it does not. No error is thrown and there doesn't seem to be any issues, but the share sheet does not appear and from the user's point of view nothing happens when you click the button.
Have I missed some permissions or something somewhere?
This is my method;
async void On_Share(object sender, EventArgs e)
{
if (CrossConnectivity.Current.IsConnected)
{
var message = "Check out this";
var title = "Share this";
await CrossShare.Current.Share(new ShareMessage { Text = message, Title = title}, new ShareOptions { ExcludedUIActivityTypes = new[] { ShareUIActivityType.PostToFacebook } });
}
else
{
NoInternetLabel.IsVisible = true;
}
}
It doesn't throw any errors and I can step through the method fine - it definitely hits the Share line. This problem is only showing on iOS, Android has no issues.
EDIT: Seems to be working fine (we've tried doing it natively as well - without plugin) but now I'm getting Warning: Attempt to present on whose view is not in the window hierarchy!

GWT Window.confirm() triggered by onchange of ValueListBox crashing Safari on iPad iOS 7.0.6

I recently received a support ticket that some of our web app's functionality is crashing safari on the iPad. This functionality had no problems prior to the latest iOS 7.0.6 update. We have a few GWT ValueListBoxes that change the DOM when their values are changed. Prior to making the changes, we present the user with a Window.confirm() message to inform them of the effects the changes will have and ask whether or not they would still like to proceed. Since the update, the confirm choices do nothing and Safari crashes. This is only happening on the iPad. The functionality works fine on the desktop browsers (IE, Chrome, Firefox, Safari and the Chrome mobile emulator), but crashes safari on the iPad. Is anyone else having this issue?
Here's a screenshot of the crash:
And here's a sample of the code:
this._view.isPrimaryFoodGen().addValueChangeHandler(new ValueChangeHandler<Boolean>()
{
#Override
public void onValueChange(final ValueChangeEvent<Boolean> event)
{
#SuppressWarnings("unchecked")
ValueListBoxWithOldValue<Boolean> vlb = (ValueListBoxWithOldValue<Boolean>)event.getSource();
if (confirmQuestionChange() ){
changeGroupAndQuestions(CONSTANTS.PRIMARY_FOOD, event.getValue());
}
else {
vlb.setValue(vlb.getOldValue());
}
}
});
public boolean confirmQuestionChange()
{
if (!this._view.isImageCriteriaQuestionsVisible())
{ //questions aren't currently visible
return true;
}
boolean confirmed = Window.confirm("Changing this response will delete image data already collected. Do you wish to proceed?");
return confirmed;
}
Any help on a solution for preventing the crash on the iPad would be greatly appreciated. I have tried focusing on another element prior to calling Window.confirm() in hopes that the overlay and the ValueListBox choices would be removed to stop any JS conflicts, but it hasn't worked.
Am I at the mercy of Apple until the next update fixes this?
Or is there a viable solution?
OK, so it turns out that since I couldn't find a fix to continue using Window.confirm(), I had to implement a solution by changing the onValueChange() and confirmQuestionChange() methods to use a manually created DialogBox instead of Window.confirm(). It isn't the optimal solution, but Safari does not crash on the iPad anymore and users can get their work done. Here are the code changes:
this._view.isPrimaryFoodGen().addValueChangeHandler(new ValueChangeHandler<Boolean>()
{
#Override
public void onValueChange(final ValueChangeEvent<Boolean> event)
{
confirmQuestionChange(CONSTANTS.PRIMARY_FOOD, event);
}
});
public void confirmQuestionChange(final String question, ValueChangeEvent<Boolean> event)
{
final ValueListBoxWithOldValue<Boolean> vlb = (ValueListBoxWithOldValue<Boolean>)event.getSource();
if (!this._view.isImageCriteriaQuestionsVisible()) //questions aren't currently visible, can change them no problem
{
changeGroupAndQuestions(question, vlb.getValue());
}
else{
//the following fix was put in place for issues with Safari on the iPad OPS-76
final DialogBox dialogBox = new DialogBox();
dialogBox.setHTML("<center>Changing this response will delete<br />image data already collected.<br />Do you wish to proceed?</center>");
dialogBox.setAnimationEnabled(true);
Button yesButton = new Button("YES");
Button noButton = new Button("NO");
HorizontalPanel dialogHPanel = new HorizontalPanel();
dialogHPanel.setWidth("100%");
dialogHPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
dialogHPanel.add(noButton);
dialogHPanel.add(yesButton);
noButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
vlb.setValue(vlb.getOldValue());
dialogBox.hide();
}
});
yesButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
changeGroupAndQuestions(question, vlb.getValue());
dialogBox.hide();
}
});
// Set the contents of the Widget
dialogBox.setWidget(dialogHPanel);
dialogBox.setPopupPosition(180, 425);
dialogBox.show();
}
}
Here's a screenshot:
As you can see, the ValueListBox options close before the DialogBox appears and the screen no longer locks.

Strange behaviour of Geolocator.GetGeopositionAsync() after first launch

I'm writing Windows Phone 8 app that needs to get location of device (do not track changes, just get location). I added next code to the method OnNavigatedTo() of my start page but after launching app, the progress indicator does not hide even after 10 seconds timeout. But if I navigate to another page and then go back, everything works fine. This happens on the emulator, I don't have a real device. What am I doing wrong?
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
if(_geoPosition == null)
{
try
{
var geolocator = new Geolocator();
geolocator.DesiredAccuracyInMeters = 50;
_progressIndicator = new ProgressIndicator
{
IsIndeterminate = true,
Text = "Getting current location, please wait...",
IsVisible = true
};
SystemTray.SetIsVisible(this, true);
SystemTray.SetProgressIndicator(this, _progressIndicator);
_geoPosition = await geolocator.GetGeopositionAsync(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10));
_progressIndicator.IsVisible = false;
SystemTray.SetIsVisible(this, false);
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Location is disabled in phone settings");
}
}
}
Thanks!
UPD: just tried to add this code to empty project and it works fine. Tried to comment out some parts of OnNavigatedTo that I did not include to the snippet and found out that the reason somewhere in initialization of data source for this page. I'm sorry for false alarm.
Your code works fine for me, try the classic restart VS and the projecy!
The code should work, tested it with an emulator and a device (nokia 820).
Best of luck

Trouble bringing a Blackberry App to Foreground

I have an app that is listening in background and when the user clicks "send" it displays a dialogue. However I need to bring my app to foreground so the user answers some questions before letting the message go. but I haven't been able to do this, this is the code in my SendListener:
SendListener sl = new SendListener(){
public boolean sendMessage(Message msg){
Dialog myDialog = new Dialog(Dialog.D_OK,
"message from within SendListener",
Dialog.OK,Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),
Dialog.GLOBAL_STATUS)
{
//Override inHolster to prevent the Dialog from being dismissed
//when a user holsters their BlackBerry. This can
//cause a deadlock situation as the Messages
//application tries to save a draft of the message
//while the SendListener is waiting for the user to
//dismiss the Dialog.
public void inHolster()
{
}
};
//Obtain the application triggering the SendListener.
Application currentApp = Application.getApplication();
//Detect if the application is a UiApplication (has a GUI).
if( currentApp instanceof UiApplication )
{
//The sendMessage method is being triggered from
//within a UiApplication.
//Display the dialog using is show method.
myDialog.show();
App.requestForeground();
}
else
{
//The sendMessage method is being triggered from
// within an application (background application).
Ui.getUiEngine().pushGlobalScreen( myDialog, 1,
UiEngine.GLOBAL_MODAL );
}
return true;
}
};
store.addSendListener(sl);
App is an object I created above:
Application App = Application.getApplication();
I have also tried to invoke the App to foreground using its processID but so far no luck.
i have managed to achieve something similar to what you're describing but the difference is, my dialogs are displayed asynchronously, which might actually be easier... so in your case..
the first i could suggest you try is get the event lock before pushing the screen, ala:
synchronized(Application.getEventLock()){
final UiEngine ui = Ui.getUiEngine();
ui.pushGlobalScreen(theScreen, 1, UiEngine.GLOBAL_MODAL);
}
I would also just create a custom class of type MainScreen and push that instead of plain Dialog.
There, that's better (now with code formatting).
public class MYSendListener implements SendListener {
private UiApplication _myApp;
public MySendListener(UiApplication myApp) {
_myApp = myApp;
}
public boolean sendMessage(Message m) {
...
_myApp.requestForeground();
}
}
Cache your app instance inside your send listener when you construct it, and use that when sendMessage is fired.
Application.getApplication() only gets you the app of the calling thread.

Windows forms window starting up out of focus (and behind executable folder)

I'm getting some strange behaviour in the start-up of a Windows app and wondered if anyone could throw any light on what is happening and how to get around it.
The problem is with the start-up of the app - it should show a splash screen then a login form. The code for this is:
[STAThread]
static void Main()
{
Application.ThreadException += Application_ThreadException;
MainForm mainForm = null;
Thread splashThread = new Thread(ShowSplash);
try
{
// set up app
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Splash screen
Splash splash = new Splash();
splashThread.Start(splash);
// enable logging
log4net.Config.XmlConfigurator.Configure();
// Create main form
mainForm = new MainForm();
// kill splash
HideForm(splash);
splashThread.Abort();
}
catch (Exception e)
{
splashThread.Abort();
MessageBox.Show(e.Message, "An exception occurred: ", MessageBoxButtons.OK, MessageBoxIcon.Error);
Environment.Exit(0);
}
// start
Login login = new Login();
login.Show();
if (!mainForm.IsDisposed)
{
Application.Run(mainForm);
}
}
static void ShowSplash(object splash)
{
if (!(splash is Splash))
throw new ArgumentException("Splash screen is of wrong type.");
Splash splashForm = (Splash) splash;
splashForm.ShowDialog();
}
// Thread safe hide form
private delegate void HideFormCallback(Form form);
private static void HideForm(Form form)
{
if (form == null || form.IsDisposed)
return;
if (form.InvokeRequired)
{
HideFormCallback d = HideForm;
form.Invoke(d, new object[] { form });
}
else
{
form.Hide();
}
}
So, we're starting up a new thread with the splash screen, setting up the rest of the app in the meantime, then killing the splash screen just before showing the login form.
The problem I'm having is that the login form doesn't have focus when the app starts. The splash screen pops up and goes away as expected. The login form pops up in front of any open windows but doesn't have focus - the folder containing the executable (that I double-clicked to launch) still has focus even when it's behind the login form.
If I comment out all the lines to do with the splash screen, the login form has focus when it appears.
My guess would be that the focus reverts back to the executable folder when the splash screen is hidden but I don't know why the login form doesn't get focus when it launches.
Calling .Focus() on the login form returns null so doesn't work.
Neither form have TopMost or such set on them.
If anyone has any suggestions for what's going on, it would be much appreciated.
This is what I've ended up doing as a somewhat hacky fix:
void LoginView_Shown(object sender, EventArgs e)
{
SetForegroundWindow(Handle);
this.BringToFront();
Activate();
}
[DllImport("user32")]
public static extern int SetForegroundWindow(IntPtr hwnd);

Resources