Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when navigating away from a page with a map on Android, while the on-screen keyboard is visible

While testing an Android application that contains a couple of Entry textboxes and a map with geolocation enabled, I found that if I clicked the back button on Android while the on-screen keyboard was up (that is, while inserting text on one of the Entries), the app would crash and I'd get the following exception logged on the debug output:

09-09 00:10:38.187 I/MonoDroid(14174): UNHANDLED EXCEPTION: System.NotSupportedException: Unable to activate instance of type Xamarin.Forms.Maps.Android.MapRenderer from native handle b250001d ---> System.MissingMethodException: No constructor found for Xamarin.Forms.Maps.Android.MapRenderer::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership) ---> Java.Interop.JavaLocationException: Exception of type 'Java.Interop.JavaLocationException' was thrown.

Whole stack trace here: http://pastebin.com/hDAS4JLV

Some things to keep in mind:

1 - The keyboard types used on those textboxes are Text and Telephone.

2 - Contrary to what the stack trace tells, I am not using the camera at all on the application.

3 - The MapRenderer does not come with such a constructor on Xamarin Forms. Mind you, I'm using Xamarin.Forms 1.2.3 (the -Pre version).

4 - I tried adding a Custom Map Renderer with a dummy constructor that accepted the required params according to the exception, to no avail.

5 - This does not happen on any other (tested) situation, only when the on-screen keyboard is displayed.

6 - This does not happen in the iOS version.

7 - The same steps were tested on several devices (Galaxy Nexus, Galaxy S5, Alcatel One Touch) with the same result.

like image 997
EfrainReyes Avatar asked Sep 09 '14 15:09

EfrainReyes


1 Answers

I encountered this problem multiples times in my project. What's happening in summary is that :

The hidden page can be released while our app is running by Android to save memory. Thus, when you go back to that page Android needs to recreate it.

When that happens Mono will create an instance of the appropriate type via the (IntPtr, JniHandleOwnership) constructor and later it will call the page constructor.

So the problem is that you need to implement the "(IntPtr, JniHandleOwnership) constructor" so that Mono can create the instance when needed. It usually looks like this :

public YourClassName(IntPtr javaReference, JniHandleOwnership jniHandleOwnership) 
    : base(javaReference, jniHandleOwnership) { }

John Pryor, the current lead of Xamarin Android has a pretty detailed answer about it which explains the behavior.

I actually already highlighted the important part of his explanation in this post.

like image 142
ForceMagic Avatar answered Oct 10 '22 02:10

ForceMagic