Error while leaving my application xamarin forms android in the background - xamarin

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!

Related

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

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.

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.

Background service confusion

I'm trying to find out how to keep an Android service running after the starting app is closed. I've tried looking at samples for background services (e.g this one, and some on the Xamarin site) but in every case the service stops running if the minimised app is 'swiped' off the screen. I don't want the service to accidently stop like this, it should run continually until a confirmed stop is requested. The service does not consume much in the way of resources, just gets a GPS location and posts it to a website every 2 minutes.
By way of background, I am a newbie to Xamarin/Android, but have in the past created several successful services in Windows with C#
(Later)
One sample I tried did leave an item in the Settings list of running apps, but didn't actually perform any service tasks once swiped off the screen. Additionally there was no icon in the status bar. After doing some reading it seems that my androidmanifest file is missing a 'service' attribute (although none of the samples I tried have this); what I have now tried is this
<service
android:name=".LocationService"
android:icon="#drawable/icon"
android:label="#string/service_name"
>
<intent-filter>
<action android:name="android.service.LocationService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
...but still no luck.
Have you had a look at the Xamarin sample here the source is here
They create a service like so:
[Service]
public class SimpleService : Service
{
System.Threading.Timer _timer;
public override StartCommandResult OnStartCommand (Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
Log.Debug ("SimpleService", "SimpleService started");
DoStuff ();
return StartCommandResult.Sticky;
}
public override void OnDestroy ()
{
base.OnDestroy ();
_timer.Dispose ();
Log.Debug ("SimpleService", "SimpleService stopped");
}
public void DoStuff ()
{
_timer = new System.Threading.Timer ((o) => {
Log.Debug ("SimpleService", "hello from simple service");}
, null, 0, 4000);
}
public override Android.OS.IBinder OnBind (Android.Content.Intent intent)
{
throw new NotImplementedException ();
}
}
And start and stop it with this:
StartService (new Intent (this, typeof(SimpleService)));
StopService (new Intent (this, typeof(SimpleService)));
Also it sounds like you want a Sticky service Docs
When the system is under memory pressure, Android may stop any running services. The exceptions to this rule are services explicitly started in the foreground, which are discussed later in this article.
When a service is stopped by the system, Android will use the value returned from OnStartCommand to determine how or if the service should be restarted. This value is of type StartCommandResult, which can be any of the following:
Sticky – A sticky service will be restarted, and a null intent will be delivered to OnStartCommand at restart. Used when the service is continuously performing a long-running operation, such as updating a stock feed.
RedeliverIntent – The service is restarted, and the last intent that was delivered to OnStartCommand before the service was stopped by the system is redelivered. Used to continue a long-running command, such as the completion of a large file upload.
NotSticky – The service is not automatically restarted.
StickyCompatibility – Restart will behave like Sticky on API level 5 or greater, but will downgrade to pre-level 5 behavior on earlier versions.
Hope this helps.
Solved it now. The confusion was mainly due to many samples being out-of-date (using deprecated methods) and different suggestions for 'pure' Android projects and Xamarin ones. Certainly don't need to modify the androidmanifest file as I suggested above.
If anyone is trying to find something similar, my project is here.
Solving the initial issue has now raised some new questions, of course, but I will post separately about that if needed.

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.

How can I test the background scan and launch the application in background with iBeacon-Android?

I am using the pro library.
But I just found doc for free library
I cannot find any doc for pro version.
Also, I don't know how to implement the background mode even using the pro sample.
Here are the steps:
Build the pro sample project
start the iBeacon source(using iPad) and it can be detected
start the application and then press home button the make it in
background
Turn off the iBeacon source
Turn on the iBeacon source
However, more than 5 minutes, the application does not launch
So, can anyone verify the step I did?
How can I test the background mode more easily?
Also, for the BootstrapNotifier, is it just work only first time when the device reboot?
After that, even I put application in background, the application will not launch when it detect iBeacon?
Your testing method sounds fine. I think the issue is that the reference app for the pro library only auto launches the app on the first detection after boot. After that, it sends a notification instead, and tapping on that notification launches the app.
This is purely for demonstration purposes. You can change it to auto launch on every detection if you wish. Simply alter the haveDetectedIBeaconsSinceBoot logic in this code:
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever an iBeacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedIBeaconsSinceBoot) {
Log.d(TAG, "auto launching MainActivity");
// The very first time since boot that we detect an iBeacon, we launch the
// MainActivity
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Important: make sure to add android:launchMode="singleInstance" in the manifest
// to keep multiple copies of this activity from getting created if the user has
// already manually launched the app.
this.startActivity(intent);
haveDetectedIBeaconsSinceBoot = true;
} else {
// If we have already seen iBeacons and launched the MainActivity before, we simply
// send a notification to the user on subsequent detections.
Log.d(TAG, "Sending notification.");
sendNotification();
}
}
The javadoc link was missing from the main documentation page when you posted this question. That is fixed now.

Resources