Is there any final even happen before a XF application exits for ever? - xamarin

I realize there are these events:
protected override void OnSleep()
{
base.OnSleep();
}
protected override void OnResume()
{
base.OnResume();
}
But is there any event that is called in which I could perform a logging action, before the app is finally swiped out of view and closed?

No there are only 3 lifecycle events for a Xamarin.Forms application. See documentation. They are:
OnStart(), OnSleep(), and OnResume().
What you could do is just do whatever you need to in OnSleep and reverse it in OnResume. That way whether the user comes back or not, you've handled what you need to handle.

No, and it is technically impossible to make something like that on iOS and Android. On UWP you could make some native code that would invoke this on Xamarin.Forms project. But I don't think that anyone is interested in such UWP only feature on Xamarin.Forms, so if you need it you will probably need to implement it yourself.

Related

Xamarin Forms - How to open specific page after clicking on notification when the app is closed?

I'm actually working on a Xamarin Forms application that need push notifications. I use the Plugin.PushNotification plugin.
When the app is running in the foreground or is sleeping (OnSleep), I have no problem to open a specific page when I click on a notification that I receive. But I was wondering how can I do that when the app is closed. Thanks!
I finally found the answer by myself and I want to share it in case someone needs it.
Nota bene: according to the official documentation of the plugin, it's Xam.Plugin.PushNotification that is deprecated. I use the new version of this plugin, Plugin.PushNotification which uses FCM for Android and APS for iOS.
There is no significant differences to open a notif when the app is running, is sleeping or is closed. Just add the next callback method in the OnCreate method (MyProject.Droid > MainApplication > OnCreate) and FinishedLaunching method (MyProject.iOS > AppDelegate > FinishedLaunching):
CrossPushNotification.Current.OnNotificationOpened += (s, p) =>
{
// manage your notification here with p.Data
App.NotifManager.ManageNotif(p.Data);
};
Common part
App.xaml.cs
// Static fields
// *************************************
public static NotifManager NotifManager;
// Constructor
// *************************************
public App()
{
...
NotifManager = new NotifManager();
...
}
NotifManager.cs
public class NotifManager
{
// Methods
// *************************************
public void ManageNotif(IDictionary<string, object> data)
{
// 1) switch between the different data[key] you have in your project and parse the data you need
// 2) pass data to the view with a MessagingCenter or an event
}
}
Unfortunately there is no succinct answer for either platform. Generally speaking, you need to tell the OS what to do when it starts the app as a result of the push notification. On both platforms, you should also consider what API level you are targeting, otherwise it won't work or even crash the app.
On iOS, you will need to implement this method in AppDelegate appropriately: FinishedLaunching(UIApplication application, NSDictionary launchOptions). The launchOptions will have the payload from the push notification for you to determine what to do with it (e.g. what page to open). For more information on iOS, Xamarin's documentation is a good place to start.
Android has a more complicated topology in terms of more drastic differences between API levels, whether you are using GCM/FCM, as well as requiring more code components. However, to answer the question directly, you will need to handle this in OnCreate(Bundle savedInstanceState) of your main Activity. If you are using Firebase, the push notification payload is available in Intent.Extras. Again, Xamarin's documentation has a good walkthrough.
Finally, note that the Plugin.PushNotification library you are using has been deprecated. I suggest you either change your library and/or your implementation soon. Part of the reason that library has been deprecated is because Google has deprecated the underlying Google Cloud Messaging (GCM) service, which will be decommissioned on April 11, 2019.

Error while leaving my application xamarin forms android in the background

My solution when I leave the application or leave it in the background gives an error 'The test application stopped', I can not find out where this queue comes from. Does anyone know where this trigger comes from the moment it leaves in the background
Is it something in this part of the code?
protected override void OnStart()
{
Debug.WriteLine("OnStart");
}
protected override void OnResume()
{
Debug.WriteLine("OnResume");
}
protected override void OnSleep()
{
Debug.WriteLine("OnSleep");
}
This type of errors came along with a specific part of your code, like #apineda mentioned maybe you are using an Android service that is updating some data on your application or it may be there to show a local notification who knows? but the thing I want to imply is that you need to take a look at your code and investigate further which is the part that is making the crash. Here are some tips:
1.- If you are using push notifications that may lead to something!
2.- Check you MainActivity.cs class since this is the one responsible of the Xamarin.Forms activity life cycle.
3.- If you have any timers on your shared code or even a background Task created with Task.Run or a Task.Factory.StartNew() check those too, deadlocks on Xamarin.Forms applications between the UI thread and background threads are a common thing on Xamarin.Forms.
I hope this helps!

How to use WebView in Xamarin.Mac

I need to authenticate user in my app, and for that I want to spawn another window with Cocoa WebView control. The problem is that I can't do anything with that control from C# code, and can't find any documentation for it :(
Trying to use
WebViewWindow.MainFrame.LoadRequest (Request);
But it throws exception of some kind. How to properly open URL in that WebView? Maybe using something like GeckoFX instead is a good idea?
Also I'll need to get back url that user was redirected to. How to do this?
Thanks.
you can use like this
public override void AwakeFromNib()
{
base.AwakeFromNib();
webView.MainFrame.LoadRequest(new NSUrlRequest
(new NSUrl( "http://www.google.com)));
}

How to terminate a Xamarin application?

How to terminate a Xamarin application from any of the activities?
I have tried both System.Environment.Exit(0) and System.Environment.Exit(1) as well as Finish() and killing all the activities.
It still opens one blank page with default activity name and a black screen.
Is there any specific solution for this?
If you are using Xamarin.Forms create a Dependency Service.
Interface
public interface ICloseApplication
{
void closeApplication();
}
Android : Using FinishAffinity() won't restart your activity. It will simply close the application.
public class CloseApplication : ICloseApplication
{
public void closeApplication()
{
var activity = (Activity)Forms.Context;
activity.FinishAffinity();
}
}
IOS : As already suggested above.
public class CloseApplication : ICloseApplication
{
public void closeApplication()
{
Thread.CurrentThread.Abort();
}
}
UWP
public class CloseApplication : ICloseApplication
{
public void closeApplication()
{
Application.Current.Exit();
}
}
Usage in Xamarin Forms
var closer = DependencyService.Get<ICloseApplication>();
closer?.closeApplication();
A simple way to make it work cross platform is by this command:
System.Diagnostics.Process.GetCurrentProcess().CloseMainWindow();
Got it from this link.
EDIT: After using it for a while, I discovered that .CloseMainWindow() don't kill the application, only Closes it (well, thats obvious). If you want to terminate the app (kill), you shoud use the following:
System.Diagnostics.Process.GetCurrentProcess().Kill();
For Android, you can do
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
iOS explicitly does not provide any API for existing an App. Only the OS can close an App.
For iOS, you can use this code:
Thread.CurrentThread.Abort();
For Android, as #Jason mentioned here:
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
System.Environment.Exit(0);
Works for me.
In your activity, use this code
this.FinishAffinity();
I tried this code
protected override bool OnBackButtonPressed()
{
Device.BeginInvokeOnMainThread(async () =>
{
var result = await DisplayAlert("", "Would you like to exit from application?", "Yes", "No");
if (result)
{
if (Device.OS == TargetPlatform.Android)
{
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
}
else if (Device.OS == TargetPlatform.iOS)
{
Thread.CurrentThread.Abort();
}
}
});
return true;
}
In this, iOS and Android application close when a user chooses to terminate the application. Maybe it helps you.
A simple all-in-one combination of the previous answers, instead of the interface/dependency:
protected override bool OnBackButtonPressed()
{
Device.BeginInvokeOnMainThread(async () =>
{
var result = await this.DisplayAlert("Alert!", "want to exit?", "Yes", "No");
if (result)
{
#if __ANDROID__
var activity = (Android.App.Activity)Forms.Context;
activity.FinishAffinity();
#endif
#if __IOS__
Thread.CurrentThread.Abort();
#endif
}
});
return true;
}
System.Diagnostics.Process.GetCurrentProcess().CloseMainWindow();
System.Diagnostics.Process.GetCurrentProcess().Kill();
None of the methods above helped my Xamarin Android app to completely shut down. I tried to close it from Activity B, having Activity A also open under it.
A clever guy left a trick here.
First call FinishAffinity() in Activity B (closes both activities,
however, the app is still alive in the background)
Then call JavaSystem.Exit(0) to kill the background app (I think it can be replaced with Android.OS.Process.KillProcess(Android.OS.Process.MyPid()); or System.Diagnostics.Process.GetCurrentProcess().Kill();)
My method to close the app:
private void CloseBtn_Click(object sender, EventArgs e){
FinishAffinity();
JavaSystem.Exit(0);
}
As your original question mentions activities, your question is specifically for Android, you should probably update the question title with that in mind to avoid people looking for a cross-platform solution coming here.
For iOS and Android (say in Xamarin Forms) you can just throw an exception, which while being the "heavy handed" approach, will do the job:
throw new Exception();
As this isn't the best user experience and you may only want to use this for iOS because on Android, you are likely to get a system popup telling you the app crashed. However, unlike other iOS methods like calling exit(0) or calling private iOS methods like "terminateWithSuccess" via a selector, it shouldn't fail app store validation purely based on how you do it. They may still fail you because your app tries to terminate itself.
You may want to implement something different specifically for Android, in which case Jason's answer is sufficient, again if not a little on the nose i.e. using this approach may not allow your app to clean itself up:
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
Either way, you should really question why you need to provide this option. Unlike desktop applications where closing an application is needed because apps reside inside windows which by design allow multi-tasking and are not task orientated, mobile platforms are primarily designed for users to focus on one task at a time. Once the user is finished the task, they should decide to exit this task by clicking the home button, back button or change app (task) button. This really applies to all platforms.
None of these work with Android 8. They all left the app in the background.
I can prove this by pressing the close all button and the app is still there.
For my testing I used a brand new simple Android app and tried all of your answers.
Application.Quit();
I'm assuming you are using C#
Call
public void Quit ();
This will quit the application the correct way without it "crashing".

DidReceiveMemoryWarning in IOS using Xamarin Forms

How can you catch the DidReceiveMemoryWarning using xamarin forms.
I can see them in the application output when debugging in xamarin studio, but i cant find how to catch the event or how to see how much memory is used.
I tried AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize but it throws a not implemented exception
There are 3 ways to capture Memory Warnings in iOS (or at least this what I know of :)
These three ways are:
In your ViewControllers, you could override DidReceiveMemoryWarning() and handle the warning there. This is not really the best way for Xamarin.Forms as you do not have UIViewController to override these methods, so move on to options 2 and 3.
In your AppDelegate, override ReceiveMemoryWarning method. This will get fired when the iOS is running low on memory. You could wire this method to any code you have on your PCL code or just handle it in your platform-specific project.
public override void ReceiveMemoryWarning (UIApplication application)
{
// handle low memory warnings here
}
You could use iOS NotificationCentre to receive a notification when there is a memory warning. This could be done like this:
// Method style void Callback (NSNotification notification)
{
Console.WriteLine ("Received a notification UIApplication", notification);
}
void Setup ()
{
NSNotificationCenter.DefaultCenter.AddObserver (UIApplication.DidReceiveMemoryWarningNotification, Callback);
}
You could then wire this "CallBack" to your PCL project to free up some memory.
You could also test this on the simulator using
Hardware >> Simulate Memory Warnings
You can override DidReceiveMemoryWarning in you iOS project, and from there notify the Xamarin.Forms pages. I can think of many ways to achieve this, but here are the 2 more obvious:
use Dependency Injection, and inject the warning as an event. Xamarin.Forms provides DependencyService as a DI container, but you can use the one you want: http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/
send messages from the native project to the other one, e.g. by using Xamarin.Forms MessagingCenter: http://developer.xamarin.com/guides/cross-platform/xamarin-forms/messaging-center/
Easiest way is to override ReceiveMemoryWarning in AppDelegate.cs as follows-
[Export("applicationDidReceiveMemoryWarning:")]
public override void ReceiveMemoryWarning(UIApplication application)
{
try
{
base.ReceiveMemoryWarning(application);
Console.WriteLine("****************************************************************");
Console.WriteLine("****************RECIEVED MEMORY WARNING***********************");
Console.WriteLine("****************************************************************");
Console.WriteLine("TOTAL MEMORY {0}",GC.GetTotalMemory(false));
AnalyticsService.Current.TrackUserActions("RECIEVED MEMORY WARNING");
}
catch (Exception ex)
{
AnalyticsService.Current.TrackException(ex);
}
}
Every time iOS running on low memory this method will get called and will crash app. Total memory(RAM) allocated/available can be checked by calling this method GC.GetTotalMemory(false) after app launch or wherever you want to check the available memory.

Resources