Fatal: Crash on Android when cancelling login dialog
Tommigun1980 opened this issue · 3 comments
Hi and thanks for a great plugin!
There is a problem on Android though -- if you start the login flow and close the FB login dialog, the app crashes with:
[MonoDroid] UNHANDLED EXCEPTION:
[MonoDroid] System.NullReferenceException: Object reference not set to an instance of an object.
[MonoDroid] at Plugin.FacebookClient.FacebookClientManager.RequestUserData (System.Collections.Generic.Dictionary`2[TKey,TValue] fieldsDictionary) [0x0009b] in <dfbb93ebf988478da14a244e77f0c9cd>:0
[MonoDroid] at Plugin.FacebookClient.FacebookPendingAction`1[T].Execute () [0x0000a] in <dfbb93ebf988478da14a244e77f0c9cd>:0
[MonoDroid] at Plugin.FacebookClient.FacebookClientManager+<>c.<Initialize>b__62_1 () [0x0004d] in <dfbb93ebf988478da14a244e77f0c9cd>:0
[MonoDroid] at Plugin.FacebookClient.FacebookClientManager+FacebookCallback`1[TResult].OnCancel () [0x0000a] in <dfbb93ebf988478da14a244e77f0c9cd>:0
[MonoDroid] at Xamarin.Facebook.IFacebookCallbackInvoker.n_OnCancel (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <d779dac91ffd425596b5bc3069ab871d>:0
[MonoDroid] at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.25(intptr,intptr)
The error happens inside the FacebookClientManager.OnActivityResult handler, as invoked from OnActivityResult in MainActivity:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
base.OnActivityResult(requestCode, resultCode, intent);
FacebookClientManager.OnActivityResult(requestCode, resultCode, intent); // <-- error happens here
...
}
The error happens both with 3.0.7-beta and 2.2.1 stable.
Here's hoping for a fix,
Thanks!
This is probably a duplicate of #63.
Considering it was reported in February and not fixed -- is this plugin maintained anymore or are we to expect it won't get fixed and should look into alternatives?
Thanks.
The problem lies within the method:
Plugin.FacebookClient.FacebookClientManager.RequestUserData
Specifically:
var fbResponse = new FBEventArgs<string>(null, FacebookActionStatus.Canceled, "User cancelled facebook operation"); _onUserData.Invoke(CrossFacebookClient.Current, fbResponse); // This is a problem if you are not subscribing to the event: facebookService.OnUserData _userDataTcs?.TrySetResult(new FacebookResponse<string>(fbResponse));
If you subscribe to the event "facebookService.OnUserData", then this value will not be null, and will be invoked.
You have 1 of 2 options to fix this.
1: Simply subscribe to the event like so:
string[] fbRequestFields = { "email", "first_name", "gender", "last_name" };
string[] fbPermisions = { "email" };
EventHandler<FBEventArgs<string>> userDataDelegate = null;
Models.loginDetails loginDetails;
userDataDelegate = async (object sender, FBEventArgs<string> e) =>
{
if (e == null) return;
switch (e.Status)
{
case FacebookActionStatus.Completed:
break;
case FacebookActionStatus.Canceled:
break;
}
facebookService.OnUserData -= userDataDelegate;
};
facebookService.OnUserData += userDataDelegate;
var response = await facebookService.RequestUserDataAsync(fbRequestFields, fbPermisions);
2: Simply edit the RequestUserData method and check for the null value, and dont invoke it if it doesnt exist:
if(_onUserData != null)
{
_onUserData.Invoke(CrossFacebookClient.Current, fbResponse);
}
New version released with this fix