monodroid-samples icon indicating copy to clipboard operation
monodroid-samples copied to clipboard

Update mapsandlocationdemo-v3 to not use deprecated Android.App.Fragment

Open harrypotter06 opened this issue 5 years ago • 23 comments

Xamarin.Android Version (eg: 6.0):

Operating System & Version (eg: Mac OSX 10.11):

Support Libraries Version (eg: 23.3.0):

Describe your Issue:

Steps to Reproduce (with link to sample solution if possible):

Include any relevant Exception Stack traces, build logs, adb logs:

harrypotter06 avatar Oct 21 '20 17:10 harrypotter06

Hello,

by XAMARIN Examples to use gmap i have used this code;

image

This code works, but on AndroidX is is deprecated. "SupportFragemntMangager" did not work here

The code is a part of an activity (public class GeoActivityMap : Activity, IOnMapReadyCallback)

All what i found is this example, but that Example has the same issue: https://docs.microsoft.com/en-us/samples/xamarin/monodroid-samples/mapsandlocationdemo-v3/

Have everybody a solution?

harrypotter06 avatar Oct 21 '20 17:10 harrypotter06

It looks like FrangmentManager was deprecated in the base Android library (Mono.Android.dll) because it was moved to AndroidSupportLibrary/AndroidX: https://developer.android.com/reference/android/app/FragmentManager.html

You can try adding the Xamarin.AndroidX.Fragment NuGet and using the FragmentManager it provides: https://www.nuget.org/packages/Xamarin.AndroidX.Fragment.

jpobst avatar Oct 21 '20 19:10 jpobst

Hello @jpobst ,

i have installed the Nuget

Have the "Using" but what i see:

image

On Support-Lib no FindFragmentByID:

image

harrypotter06 avatar Oct 21 '20 19:10 harrypotter06

There definitely isn't a generic version of it, so you'll need something like:

FragmentManager.FindFragmentById (Resource.Id.googlemap) as MapFragment

I think the other issue is that this isn't a static method, and you don't have a FragmentManager object. Per Google's docs, it looks like your class will have to inherit from FragmentActivity in order to get an instance of the FragmentManager from SupportFragmentManager: https://developer.android.com/reference/android/support/v4/app/FragmentManager.html.

jpobst avatar Oct 21 '20 20:10 jpobst

@jpobst

Sorry, you a using C# on VS2019?

My code is based on this Xamarin Example: https://github.com/xamarin/monodroid-samples/blob/master/MapsAndLocationDemo_v3/SimpleMapDemo/MapWithMarkersActivity.cs

So this Xamarin Example has the same issue. Did you not have this issue if you change to API29/30? - If not, if you have a example?

harrypotter06 avatar Oct 21 '20 21:10 harrypotter06

I am just looking at your screenshots. For example, why does FragmentManager have a red squiggle under it in your screenshot?

jpobst avatar Oct 21 '20 21:10 jpobst

sorry for the confusion:

Default lib: image

and Support-lib: image

On Xamarin example, same issue.

harrypotter06 avatar Oct 21 '20 21:10 harrypotter06

That looks closer. The remaining issue is that there isn't a generic version of FindFragmentById<>, so you'll need:

(SupportFragmentManager.FindFragmentById (Resource.Id.googlemap) as MapFragment).GetMapAsync (this);

jpobst avatar Oct 21 '20 21:10 jpobst

image

harrypotter06 avatar Oct 21 '20 21:10 harrypotter06

image

harrypotter06 avatar Oct 21 '20 21:10 harrypotter06

I don't know if this will work at runtime, but it should at least compile:

SupportFragmentManager.FindFragmentById (Resource.Id.googlemap).JavaCast<MapFragment> ().GetMapAsync (this);

jpobst avatar Oct 21 '20 21:10 jpobst

image

harrypotter06 avatar Oct 21 '20 21:10 harrypotter06

Honestly, I would probably just live with the deprecated warning until you move your application to AndroidX. The AndroidSupport libraries are deprecated as well, they just don't have a the types marked that way. AndroidX is the way forward.

jpobst avatar Oct 21 '20 21:10 jpobst

That's what it's all about right now. We want to use the application on Xamarin.AndroidX and have also installed the Xamarin.Migrator first. Obviously the migration is not clean and now I need a solution, because "outdated code in an application is never an acceptable solution.

harrypotter06 avatar Oct 21 '20 22:10 harrypotter06

Ok, then back to your first screenshot. The issue is you are using the deprecated Android.App.FragmentManager that ships in Mono.Android.dll and not the AndroidX.Fragment.App.FragmentManager that ships in https://www.nuget.org/packages/Xamarin.AndroidX.Fragment.

You will need to update your code to use the AndroidX one instead, which will likely involve the same steps (inherit from FragmentActivity and use SupportFragmentManager). However use the ones from AndroidX and not the Support Components ones.

jpobst avatar Oct 21 '20 22:10 jpobst

I would love to do that if someone would tell me how to do this with Xamarin. Xamarin only documented that you should use the Xamarin.AndroidX.Migrator and you can now see what comes out of it.

harrypotter06 avatar Oct 21 '20 22:10 harrypotter06

Let's make it easy:

from: Using Android.Support.V4.App is under AndroidX ..... Using AndroidX .......

Unfortunately, the Android documentation is only of limited help to Xamarin programmers, as the syntax used is different.

harrypotter06 avatar Oct 21 '20 22:10 harrypotter06

Xamarin.AndroidX.Migrator updates your project from using AndroidSupportComponents to using AndroidX. You weren't using AndroidSupportComponents, you are using the even older implementation that ships directly with Android.

In order to use the AndroidX version, you will need to do the steps I outlined:

  • Make your activity inherit from AndroidX.Fragment.App.FragmentActivity.
  • Use one of these:
(SupportFragmentManager.FindFragmentById (Resource.Id.googlemap) as MapFragment).GetMapAsync (this);
SupportFragmentManager.FindFragmentById (Resource.Id.googlemap).JavaCast<MapFragment> ().GetMapAsync (this);

jpobst avatar Oct 21 '20 22:10 jpobst

I also think that you can expect the Xamarin developers to adapt the examples for Google Maps and not offer old code as an example that no longer works, as is currently the case.

Migration also means being able to provide appropriate examples and keeping existing examples up to date.

harrypotter06 avatar Oct 21 '20 22:10 harrypotter06

I change this: public class GeoActivityMap : Activity, IOnMapReadyCallback

to: public class GeoActivityMap : AndroidX.Fragment.App.FragmentActivity, IOnMapReadyCallback

and then i got some new issues:

values.xml(6): error APT1000: Attribute "mapType" already defined with incompatible format. values.xml(7): error APT1000: Original attribute defined here. values.xml(35): error APT1000: Attribute "imageAspectRatioAdjust" already defined with incompatible format. values.xml(36): error APT1000: Original attribute defined here. values.xml(48): error APT1000: Attribute "buttonSize" already defined with incompatible format. values.xml(49): error APT1000: Original attribute defined here. values.xml(56): error APT1000: Attribute "colorScheme" already defined with incompatible format. values.xml(57): error APT1000: Original attribute defined here.

__________________ value.xml ___________________

After change back to: public class GeoActivityMap : Activity, IOnMapReadyCallback

we have the errors also. - s 10 hours work are lost now, because we have no solution for the new issue.

harrypotter06 avatar Oct 21 '20 23:10 harrypotter06

@jpobst - The other issue on "values.xml" we found. Is only in "Debug-Mode" so think that Microsoft has a VS2019 issue.

Back to this issue - got a null reference, so also this does not work:

image

and the oster code-line, you send me:

image

harrypotter06 avatar Oct 22 '20 00:10 harrypotter06

This seems to be due to a difference in how the FragmentManager class and the SupportFragmentManager class function:

image

Calling the same code, the SupportFragmentManager class returns null while the original FragmentManager class works.

This seems to be referred to in Google's documentation here. Specifically:

Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>. Nested fragments are only supported when added to a fragment dynamically.

This fragment is defined as:

<LinearLayout>
  <fragment />
</LinearLayout>

Some more info is here: https://stackoverflow.com/questions/35059822/android-childfragmentmanager-findfragmentbyid-always-null.

I think your best option is to continue using the original FragmentManager that works correctly. Alternatively you can modify your app to use Fragments however Google now wants them done. There's some documentation here: https://developer.android.com/guide/components/fragments?hl=en.

jpobst avatar Oct 22 '20 18:10 jpobst

The remaining issue here seems to be to update the mapsandlocationdemo-v3 sample to no longer use the obsolete Android.App.Fragment so that users don't get pointed down the wrong path. Thus I moved this issue to the monodroid-samples repo to track it there.

jpobst avatar Oct 28 '20 18:10 jpobst