How do I deal with a possible exception in a Xamarin Forms application deployed to iOS or Android? - xamarin

I have a finished application which I would like to make available to run on the iOS and Android platforms.  I have tested the application as much as possible and it works without problem.  But I know there is always the chance that something might go wrong and I could get an exception.
My question is how can I deal with this or what should I do. What happens on the phone, if a Forms application is deployed and there is an exception.
Would appreciate any advice or even links as to how this is handled.

If an exception is thrown and not handled by your code, the app will stop working (i.e. crash).
In order to handle these crashes we are using MS AppCenter (the successor to HockeyApp/Xamarin AppInsights).
You'll have to create a project there (one for each platform), and add the NuGet package to your projects. Afterwards you can initialize it with
AppCenter.Start("ios={Your App Secret};android={Your App Secret}",
typeof(Crashes)); // you'll get the app secrets from appcenter.ms
Crashes will be logged to AppCenter now and you'll be informed whenever there is a new crash.
Please note that it's best practice (if not required by law), that you ask the user for consent before sending the crash report (see here). You are using the delegate Crashes.ShouldAwaitUserConfirmation for that matter. You could for example show an action sheet with Acr.UserDialogs
private bool AwaitUserConfirmation()
{
// you should of course use your own strings
UserDialogs.Instance.ActionSheet(
new ActionSheetConfig
{
Title = "Oopsie",
Message = "The app crashed. Send crash to developers.",
Options = new List<ActionSheetOption>
{
new ActionSheetOption("Sure", () => Crashes.NotifyUserConfirmation(UserConfirmation.Send)),
new ActionSheetOption("Yepp, and don't bug be again.", () => Crashes.NotifyUserConfirmation(UserConfirmation.AlwaysSend)),
new ActionSheetOption("Nope", () => Crashes.NotifyUserConfirmation(UserConfirmation.DontSend))
}
});
return true;
}

Related

Need to store handled exceptions globally without calling the save log method inside Every catch in xamarin.forms

try
{
int c = 0;
int a = 5 / c;
}
catch (Exception ex)
{
}
Need to write Handled Exceptions globally in one place and without calling the errorlog method in each and every catch block in xamarin.forms and expect to get details in mainactivity for android and appdelegate for ios or any comman place in xamarin.forms
In your case you could use App Center . App Center Crashes will automatically generate a crash log every time your app crashes. The log is first written to the device's storage and when the user starts the app again, the crash report will be sent to App Center. Collecting crashes works for both beta and live apps, i.e. those submitted to the App Store. Crash logs contain valuable information for you to help fix the crash.
App Center Crashes provides you with an API to generate a test crash for easy testing of the SDK. This API checks for debug vs release configurations. So you can only use it when debugging as it won't work for release apps.
Crashes.GenerateTestCrash();
If your app crashed previously, you can get details about the last crash.
ErrorReport crashReport = await Crashes.GetLastSessionCrashReportAsync();
Set this callback if you want to decide if a particular crash needs to be processed or not. For example, there could be a system level crash that you'd want to ignore and that you don't want to send to App Center.
Crashes.ShouldProcessErrorReport = (ErrorReport report) =>
{
// Check the report in here and return true or false depending on the ErrorReport.
return true;
};
For more details about App Center you could check Get Started with Xamarin .

App Center in-app updates not showing up in Xamarin Android app

I'm attempting to configure AppCenter.Distribute for in-app updates within my Xamarin Android app. Here is the very basic setup code, which I have in my main launcher activity's OnCreate method (AFTER the base.OnCreate call):
AppCenter.Start (Resources.GetString (Resource.String.appcenter_app_secret), typeof (Analytics), typeof (Crashes), typeof (Distribute));
I was able to get the in-app updates to supposedly initialize. When I first install and open the app, it shows a browser window for one second that says "In-app updates enabled! Returning to app in 1...", then it redirects back to my app. Unfortunately, when I then bump the version name and code and distribute a new build, I don't get a dialog within the app prompting me to update to the new version.
I even tried handling the Distribute.ReleaseAvailable action and showing a custom dialog, and that action isn't invoked either:
Distribute.ReleaseAvailable = OnReleaseAvailable;// Called before AppCenter.Start
private bool OnReleaseAvailable(ReleaseDetails releaseDetails)
{
// Show custom dialog.
Droid.ApplicationContext.Activity.CustomDialogBuilder().Show(new NotificationArgs
{
Title = "New update available!",
Message = "A new version of RPR Mobile, {0} ({1}) is available. Release notes: {2}"
.WithFormat(releaseDetails.ShortVersion, releaseDetails.Version, releaseDetails.ReleaseNotes),
PositiveButtonText = "Update",
PositiveAction = () =>
{
// Notify SDK that user selected to update...
Distribute.NotifyUpdateAction(UpdateAction.Update);
},
HideNegativeButton = releaseDetails.MandatoryUpdate,
NegativeButtonText = "Postpone Update",
NegativeAction = () =>
{
// Notify SDK that user selected to postpone (for 1 day)...
// Note that this method call is ignored by the SDK if the update is mandatory.
Distribute.NotifyUpdateAction(UpdateAction.Postpone);
}
});
// Return true if you are using your own dialog, false otherwise.
return true;
}
I'm wondering what I'm missing. Some questions that may or may not be relevant...
Does it matter whether the AppCenter.Start code executes before or after the base.OnCreate call?
Does it matter whether the activity that AppCenter.Start is called from is running or finished? Because in our case, the main launcher is just a splash screen that closes after a couple seconds.
Is the App Center SDK supposed to poll every few seconds for an update? Or does it check only when opening and closing activities?
It turns out that you have to close and relaunch your app for it to check for new updates. The documentation could be more clear on this...

Visual Studio App Center Analytics Not working for Xamarin Forms Android Project

I am using Visual Studio App Center for my Xamarin Forms Android Application for capturing the Analytics(Events and Crashes)
I am configuring crashes and analytics in OnStart of my App.Xaml.cs
AppCenter.Start($"android={Settings.Current.AppCenterAnalyticsAndroid};" +
typeof(Analytics), typeof(Crashes));
And for invoking the Events I am calling the below Method.
public void TrackEvent(string name, Dictionary<string, string> properties = null)
{
Analytics.SetEnabledAsync(true).ConfigureAwait(false);
Analytics.TrackEvent(name, properties);
}
Crashes are logging correctly in App Center But the events are not.
Also I can see the corresponding entries in Log Flow
Your app secret string is invalid because it contains + typeof(Analytics), it should be , typeof(Analytics).
Since you used the android key/value delimiter we could extract the appSecret and make it work with Crashes, but typeof(Analytics) ended up in the wrong appSecret parameter string.
You shouldn't need to add Analytics.SetEnabledAsync(true).ConfigureAwait(false);
Simply Call Analytics.TrackEvent(name, properties); (it doesn't need to be in a task anyways. I track my events in the Construtor of pages, for example.
Also, when you run the application, you get a debug Message confirming that AppCenter has been configured correctly, check if that is the case.
And, it may take a while, for them to appear in the Events.

How to prevent app from crashing on uncaughtErrorEvent

Is there a way to prevent the app from crashing when JS uncaught errors occur?
Already tried to wrap app.start(...) inside try/catch, but it sure doesn't work:)
There is indeed, you can register an uncaughtErrorEvent listener.
Refer to the official documentation - https://docs.nativescript.org/core-concepts/application-lifecycle#use-application-events
You can drop the following in your app.js before bootstrapping the application
var application = require("application");
application.on(application.uncaughtErrorEvent, function (args) {
if (args.android) {
// For Android applications, args.android is an NativeScriptError.
console.log("NativeScriptError: " + args.android);
} else if (args.ios) {
// For iOS applications, args.ios is NativeScriptError.
console.log("NativeScriptError: " + args.ios);
}
});
There's no way to prevent the app from crashing. You can catch the error in the uncaughtError application event but the app will crash afterwards regardless.
Attempting to navigate to an error page won't work.
According to the comments on this GitHub issue:
Ability to specify custom error pages on uncaughtErrors · Issue #1718 · NativeScript/NativeScript
there is a way to customize the error page shown, but only on Android. Apparently there isn't anything similar available for iOS.
This is an older question but there is a documented way to prevent this using Nativescript older than 4.2 (you should be on 6+ now)
Disable rethrowing of uncaught js exceptions to native
Basically, catch the JS errors but do not crash the native app.
Note the disclaimer there as well. The script will be unstable at this point. Yes, it did not crash, but wherever it dies did not continue, so you might be worse off for stability. Putting the app in a bad state or just quitting/recrashing might be safer.

Change Parse Application when App is running

I have an Android Application that works with locals instalations and I want use it with diferents Parse applications. Each instalation administrator will contract with Parse directly. When app start it will look for the keys for parse.
I wonder how to change the Parse App linkeded in the Android App once this is running
I have tried to call Parse.initialize (context, apllicationId, clientKey) twice but it doesn't work. I have tried the app register in diferent Parse App every time you start the App link with a different Parse App
It´s always linked only with the first application
public void onCreate(final Bundle icicle){
super.onCreate(icicle);
final Context context = this;
setContentView(R.layout.ssa);
getActionBar().hide();
// Getting the global variables
fmGlobalsBean = Utilities.getGlobals(this);
if(!"".equals(fmGlobalsBean.getUrl_server())){
Parse.initialize(contexto, "p4IWkTRc0WTdKkMH6r60hjYzwX1TIXChy8VcDvPb", "KhkcX4G3dqVpRawHyIYfnHAWqj1H2vyhwD3wINlQ");
ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground(fmGlobalsBean.getUrl_server());
}
else
{
Parse.initialize(this, "Y3xgZ58u4Qcn9TrovFqCOe4PBzhURjXooZ3vDKgB", "ealo3nm4wa4lbJ7KrSR2OSf60DZiUjEUjdUJTQzs");
ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground("INITIAL");
}
}

Resources