dotnet / android-samples

A collection of .NET for Android sample projects
https://dotnet.microsoft.com/apps/mobile
MIT License
2.21k stars 4.05k forks source link

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

Closed harrypotter06 closed 5 months ago

harrypotter06 commented 4 years ago

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 commented 4 years ago

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?

jpobst commented 4 years ago

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.

harrypotter06 commented 4 years ago

Hello @jpobst ,

i have installed the Nuget

Have the "Using" but what i see:

image

On Support-Lib no FindFragmentByID:

image

jpobst commented 4 years ago

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.

harrypotter06 commented 4 years ago

@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?

jpobst commented 4 years ago

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

harrypotter06 commented 4 years ago

sorry for the confusion:

Default lib: image

and Support-lib: image

On Xamarin example, same issue.

jpobst commented 4 years ago

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);
harrypotter06 commented 4 years ago

image

harrypotter06 commented 4 years ago

image

jpobst commented 4 years ago

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);
harrypotter06 commented 4 years ago

image

jpobst commented 4 years ago

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.

harrypotter06 commented 4 years ago

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.

jpobst commented 4 years ago

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.

harrypotter06 commented 4 years ago

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 commented 4 years ago

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.

jpobst commented 4 years ago

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:

harrypotter06 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

@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

jpobst commented 4 years ago

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 commented 4 years ago

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.