maui icon indicating copy to clipboard operation
maui copied to clipboard

RegisterForActivityResult does not work

Open dimonovdd opened this issue 2 years ago • 20 comments

Description

RegisterForActivityResult does not work correctly with MauiAppCompatActivity.

I think the issue lies in these two lines:

savedInstanceState?.Remove("android:support:fragments");
savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key");

Steps to Reproduce

  1. Clone the repository
  2. Open AndroidApp1.sln
  3. Enable Don't keep activities on Device\Simulator
  4. Add breakpoints in two projects in methods OnActivityResult
  5. Run AndroidApp1
  6. Touch Get result
  7. Choose a contact
  8. Run MauiApp1
  9. Touch Get result
  10. Choose a contact

Link to public reproduction project repository

https://github.com/dimonovdd/RegisterForActivityResult.MAUI

Version with bug

8.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Any

Did you find any workaround?

No response

Relevant log output

No response

dimonovdd avatar Mar 17 '23 22:03 dimonovdd

@PureWeen Hi

Do you have any ideas? These lines have been changed in #1241

dimonovdd avatar Mar 17 '23 22:03 dimonovdd

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

ghost avatar Mar 20 '23 15:03 ghost

Backlog? @jsuarezruiz Do you understand the seriousness of this problem? Are we following the path of Xamarin.Froms? If an issue is difficult, then you simply do not have the desire to solve it for several years?

@jonathanpeppers Hi, You are strong in Android development. Do you have any ideas? How can we disable fragment restore without disabling restore of other things?

dimonovdd avatar Mar 21 '23 07:03 dimonovdd

@dimonovdd it looks like you are supposed to override:

protected virtual bool AllowFragmentRestore => false;

Did that not work for you?

@PureWeen can maybe share details on why we need:

savedInstanceState?.Remove("android:support:fragments");
savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key");

jonathanpeppers avatar Mar 21 '23 13:03 jonathanpeppers

@dimonovdd it looks like you are supposed to override:

I didn't understand the meaning of it https://github.com/dotnet/maui/discussions/14039

dimonovdd avatar Mar 21 '23 14:03 dimonovdd

I think you override it and return true, will prevent savedInstanceState from being modified?

jonathanpeppers avatar Mar 21 '23 14:03 jonathanpeppers

will prevent savedInstanceState from being modified?

Yes, but the app will crash. And there is no documentation of what else needs to be changed.

dimonovdd avatar Mar 21 '23 14:03 dimonovdd

What is the error message?

jonathanpeppers avatar Mar 21 '23 14:03 jonathanpeppers

A screenshot was attached in the discussion. This exception is not only related to ShellItemRenderer. Almost nothing has ctor (IntPtr javaReference, JniHandleOwnership transfer) or empty ctor

dimonovdd avatar Mar 21 '23 15:03 dimonovdd

MAUI changed the logic of restoring activity after destroy. These two lines disable default restore of fragments and other Views. But it also disables state restore of other things (RegisterForActivityResult and etc.)

savedInstanceState?.Remove("android:support:fragments");
savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key");

dimonovdd avatar Mar 21 '23 15:03 dimonovdd

@dimonovdd it looks like you are supposed to override:

protected virtual bool AllowFragmentRestore => false;

Did that not work for you?

@PureWeen can maybe share details on why we need:

savedInstanceState?.Remove("android:support:fragments");
savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key");

The top one has been around forever in Forms https://github.com/xamarin/Xamarin.Forms/pull/246

The second one we added when we bumped up AndroidX because it was causing a similar issue indicated by https://github.com/xamarin/Xamarin.Forms/pull/246

https://github.com/xamarin/Xamarin.Forms/pull/14101/files#diff-89f66fc6d9b2094dcce8863bd3db93823b5ca20d2f2ef588b8e6ffff46fcb0b6R226

Do you happen to know which of these lines is breaking RegisterForActivityResult?

We should probably re-evaluate these. They feel like something that's just adding a band-aid to a different problem.

PureWeen avatar Mar 21 '23 16:03 PureWeen

Do you happen to know which of these lines is breaking RegisterForActivityResult?

yep, savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key");

dimonovdd avatar Mar 21 '23 16:03 dimonovdd

Do you happen to know which of these lines is breaking RegisterForActivityResult?

yep, savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key");

If you set AllowFragmentRestore to true and then just add

savedInstanceState?.Remove("android:support:fragments");

Does that workaround your issue?

PureWeen avatar Mar 21 '23 16:03 PureWeen

Does that workaround your issue?

No, I changed MauiAppCompatActivity code like this and also the exception

image

dimonovdd avatar Mar 22 '23 06:03 dimonovdd

Does that workaround your issue?

No, I changed MauiAppCompatActivity code like this and also the exception

image

Hmm, yea, it looks like that path broke when we updated AndroidX and then needed to add that other line to account for it.

PureWeen avatar Mar 22 '23 13:03 PureWeen

Hmm, yea, it looks like that path broke when we updated AndroidX and then needed to add that other line to account for it.

I think it will be very painful to tear off this patch. But we definitely have to fix it

dimonovdd avatar Mar 23 '23 07:03 dimonovdd

Is that issue still in backlog? In how many years will we be able to see a solution?

dimonovdd avatar May 11 '23 13:05 dimonovdd

Verified this issue with Visual Studio Enterprise 17.8.0 Preview 1.0. Can repro on android platform with sample project. https://github.com/dimonovdd/RegisterForActivityResult.MAUI image image

homeyf avatar Sep 05 '23 08:09 homeyf

~~The issue in the sample is probably in creating ActivityResultLauncher before base.OnCreate: https://github.com/dimonovdd/RegisterForActivityResult.MAUI/blob/main/MauiApp1/Platforms/Android/MainActivity.cs#L18 Not in MAUI.~~

Seems like it doesn't matter where it's registered. So @dimonovdd is right that removing the lifecycle saved state doesn't let Activity Result Registry restore and apply pending results.

entdark avatar Feb 09 '24 08:02 entdark

I'm having success with this workaround:

public class MainActivity : MauiAppCompatActivity
{
    protected override bool AllowFragmentRestore => true;

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        ...

        savedInstanceState?
            .GetBundle("androidx.lifecycle.BundlableSavedStateRegistry.key")?
            .Remove("android:support:fragments");

        base.OnCreate(savedInstanceState);
    }
}

This should probably be the fix that goes in MauiAppCompatActivity but I'm having trouble proving it in their unit/device/ui test projects.

Basically, I've found that android:support:fragments is no longer a direct child of savedInstanceState (probably an AndroidX change somewhere) but rather a child of the androidx.lifecycle.BundlableSavedStateRegistry.key bundle. Thus, savedInstanceState?.Remove("android:support:fragments"); doesn't appear to have any affect and savedInstanceState?.Remove("androidx.lifecycle.BundlableSavedStateRegistry.key"); wipes out both the fragment bundle and the ActivityResultRegistry required by the new Activity Result API's.

14037_api33_workaround

phunkeler avatar Aug 07 '24 18:08 phunkeler