Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor #8337

Closed
gmck opened this issue Sep 15, 2023 · 29 comments · Fixed by dotnet/java-interop#1149
Closed

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor #8337

gmck opened this issue Sep 15, 2023 · 29 comments · Fixed by dotnet/java-interop#1149
Assignees
Labels
Area: App Runtime Issues in `libmonodroid.so`. needs-triage Issues that need to be assigned.

Comments

@gmck
Copy link

gmck commented Sep 15, 2023

Android application type

.NET Android (net7.0-android, etc.)

Affected platform version

VS 2022 17.8.0 Preview 2

Description

net8.0-android - (no option to choose net8 above) . - Deploying to Pixel 6 - Android 14 beta.

The release version builds ok, it had some build errors, but they were simple to fix. The app starts ok but then fails at run time when I try to open my GoogleSignInFragment with the error below.

If a debug build everything works ok.

If I replace the button click with IView.IOnClickListener in the release build and use the following, the error goes away and I can sign in.

public void OnClick(View? v)
{
 ...
}

It appears as though, R8 is stripping something away, but I'm not sure how to fix it.

I do have a proguard.cfg which has the following.

-keep class com.google.android.gms.common.SignInButton
-keep class com.google.android.gms.auth.api.signin.GoogleSignInOptions { *; }
-keep class com.google.android.gms.auth.api.signin.internal.SignInHubActivity {*; }

According to my comments, this was added in June 2020, so I'm not sure it is even required now. I now can't remember how I came up with that, but it was crashing back then and the above fixed it.

After I got the GoogleSignInFragment working I then tried the SubscriptionFragment and that also failed with the same error.

Can you please suggest what is required?

Prior to working on this app, I first converted one of my GitHub test apps to net8.0-android and that is working fine, but obviously, that doesn't have any buttons. I could add a button to one of its fragments and upload it there if you need a sample.

Steps to Reproduce

See above

Did you find any workaround?

See above

Relevant log output

Unhandled Exception from source=AndroidEnvironment

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor
                                                                                                       at Java.Interop.JniEnvironment.Types.TryFindClass(String , Boolean )
                                                                                                       at Java.Interop.JniEnvironment.Types.FindClass(String )
                                                                                                       at Java.Interop.JniType..ctor(String )
                                                                                                       at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
                                                                                                       at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
                                                                                                       at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
                                                                                                       at Android.Views.View.IOnClickListenerImplementor..ctor()
                                                                                                       at Android.Views.View.__CreateIOnClickListenerImplementor()
                                                                                                       at Java.Interop.EventHelper.AddEventHandler[IOnClickListener,IOnClickListenerImplementor](WeakReference& , Func`1 , Action`1 , Action`1 )
                                                                                                       at Android.Views.View.add_Click(EventHandler )
                                                                                                       at com.glmsoftware.obdnowpros.Fragments.SubscriptionFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
                                                                                                       at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState)
                                                                                                       at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2)
                                                                                                      --- End of managed Java.Lang.Exception stack trace ---
@gmck gmck added Area: App Runtime Issues in `libmonodroid.so`. needs-triage Issues that need to be assigned. labels Sep 15, 2023
@gmck
Copy link
Author

gmck commented Sep 19, 2023

@grendello

I forgot to update this.

On another fragment, I got the same exception but for the OnLongClickListener and had to add the following
to the proguard.cfg

-keep class android.view.View_IOnClickListenerImplementor
-keep class android.view.View_IOnLongClickListenerImplementor

Adding these allowed me to revert my code to what it was previously.

Can you explain why these two are necessary in the Net8 build when they weren't before in the Net7 or the X.A. builds?

@gmck
Copy link
Author

gmck commented Sep 19, 2023

@grendello

From #8285

.NET's HttpClient? If yes, then part of the slowdown might be caused by dotnet/runtime#89880.

Do you know if the fix in that issue you referred to made it into the Net8 RC1 release?

@moljac
Copy link
Contributor

moljac commented Oct 3, 2023

Can you please suggest what is required?

Believe me I would like more than you to have more time to work on samples to learn and understand and to boost my growth mindset...

android.view.View_IOnClickListenerImplementor

Is this really native Android? IsomethingImplementor looks like bindings, so R8 has not much to do with those.

... thinking ...

Maybe ACWs (Android Callable wrappers) are stripped too...

@moljac
Copy link
Contributor

moljac commented Oct 3, 2023

@jpobst

Your thoughts?

@gmck
Copy link
Author

gmck commented Oct 3, 2023

@moljac, @jpobst

I've just updated a sample (added a button click event to the MaterialWidgetsFragment) on my GitHub which demonstrates the problem. Build it as a debug release and it works fine. Crashes with the same exception in release build. See notes in the readme for further details.

https://github.com/gmck/NavigationGraph8Net8

@jpobst
Copy link
Contributor

jpobst commented Oct 3, 2023

@dellis1972 dellis1972 self-assigned this Oct 3, 2023
@dellis1972
Copy link
Contributor

I'll see if I can repo

@gmck
Copy link
Author

gmck commented Oct 4, 2023

@dellis1972, @moljac, @jpobst

I updated the sample app above adding the lines from the previous message to a new proguard.cfg and that fixes the crash seen in the release build. I'd still like to know why it was necessary in the .Net8 project compared to the .Net7 project where it wasn't.

@dellis1972
Copy link
Contributor

I think we updated R8 in .net 8 compared to .net 7, so its possible that its more aggressive in what it removes.

@gmck
Copy link
Author

gmck commented Oct 4, 2023

@dellis1972, @Mojac, @jpobst

I find this to be confusing. Is it R8 or IILink responsible?

First, why would Xamarin.Android C# programmers expect a fragment containing a click event using a C# event handler like in the example fail to open.

It is not exactly intuitive to think that the app needs an IView.IOnClickListener interface and Click() method instead. So it's not obvious that the failure is caused by the fact that you have used a C# event handler. It is not as though it fails when you click the button, cause you never get that far before it crashes.

If you've used IView.IOnClickListener in the past or seen equivalent Android code, then I guess after seeing the exception you would realise, but I'd reckon most wouldn't.

I just added the same event handler to the Net7 version of the same app and it too failed with the same exception, so I don't think it is related Net8 RC1 release.

@dellis1972
Copy link
Contributor

Its probably not intuative.

I guess its down to how the bindings work. C# programmers like events like OnClick. The android side uses the Listener pattern to handle interactions, so the binding will setup the Listener on the Java side and then include a C# event on the C# side to make it easier on the C# programmer. I guess the prooblem there is all that is abstracted away, but I'm not sure what we can do about that in the case of the Listener being stripped away.

Using R8 and even proguard has always been a case of "Run it and see what crashes" since they might remove some things that are needed. There is a linker step which is designed to produce the -keep stuff for all the java classes we need that are used by the bindings.

@jpobst do you think JavaCallableWrapperGenerator should be someout producing a -keep list in addition to the Java code? Since its called after the linker it should contain only the code that is needed.

@jpobst
Copy link
Contributor

jpobst commented Oct 5, 2023

Since this appear to be a regression, I think the best course of action would be to figure out what change(s) broke it. Then we can determine what sort of fix is needed.

Whatever we've been doing has worked for many years.

I don't know anything about R8, do you get to choose which .jar files it runs against? Perhaps we didn't use to run it against our generated code since we know it only contains things that need to be kept?

@jpobst
Copy link
Contributor

jpobst commented Oct 6, 2023

I spent yesterday investigating this without much luck yet. Some notes:

  • net8.0-android crashes
  • net7.0-android works
  • net8.0-android with R8 from net7.0 crashes (**)

I compared both the JCW's and Proguard configurations that we generate and could not find any relevant differences.

I get the warning mentioned in #8397 with both .NET 7 and 8, so it feels unrelated, but could probably be investigated further:

warning XA4304: ProGuard configuration file 'C:\Program Files (x86)\Android\android-sdk\tools\proguard\proguard-android.txt' was not found.

** Using

<AndroidR8JarPath>C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\33.0.68\tools\r8.jar</AndroidR8JarPath>

@gmck
Copy link
Author

gmck commented Oct 7, 2023

@jpobst

  • net7.0-android works

It is very interesting that you can get your net7.0 version to work for I had exactly the same problem with my .Net7 version. If you check out the link below for the project Navigation8Net7 you'll see in the MaterialWidgetsFragment that there is no click event or clicklistener and the release build of the app as is runs fine.

Now insert the following lines before the line return view; in the OnCreateView of MaterialWidgetsFragment.

MaterialButton? materialButton = view.FindViewById<MaterialButton>(Resource.Id.button1);
materialButton!.Click += (sender, e) =>
{
    if (materialCheckBox.Checked)
    {
        materialCheckBox.Checked = false;
        materialSwitch.Checked = false;
    }
    else
    {
        materialCheckBox.Checked = true;
        materialSwitch.Checked = true;
    }
};

Build and rerun it and it should crash as soon as you select that fragment. Adding a proguard.cfg with the keep rule -keep class android.view.View_IOnClickListenerImplementor will fix it.

If you don't need that, then I guess my installation could be screwed up.

https://github.com/gmck/NavigationGraph8Net7

@tipa
Copy link

tipa commented Oct 7, 2023

It is very interesting that you can get your net7.0 version to work for I had exactly the same problem with my .Net7 version

Unless I am mixing something up, this is the exact problem I was just reporting here: #8397
.NET7 R8 compilation fails if the default proguard file from the Android SDK is missing (which is the case on fresh VS/Android SDK installations).

@tipa
Copy link

tipa commented Oct 7, 2023

Here's a very small NET7 project that crashes when run in Release mode, maybe it helps finding the problem:

New folder.zip

java.lang.NoSuchFieldError: no "Lcom/google/android/material/elevation/SurfaceColors;" field "SURFACE_1" in class "Lcom/google/android/material/elevation/SurfaceColors;" or its superclasses

@gmck
Copy link
Author

gmck commented Oct 7, 2023

@tipa
I tried your test app with both Net7 and Net8. They both run in release mode - no crashes. Deployed to a Pixel 6 (android 13) and Pixel 7 (android 14). Have you tried with Net8?

I don't get the warnings that @jpobst noted.

@tipa
Copy link

tipa commented Oct 9, 2023

@gmck
I just tested my test app from above on my other machine, where I had a VS installation from a few months ago (android-sdk folder was created in March). And indeed - no crashes.
I copied the tools/proguard folder (attached) to my new PC where the proguard folder hasn't been present, and then it started working there too...
proguard.zip

@gmck
Copy link
Author

gmck commented Oct 9, 2023

@tipa

You might be on to something.

Last month when I went to install Net8 RC1, I couldn't find the .Net Maui (Net8 Preview) option in the installer. When you look at the post from @jonathanpeppers, https://github.com/xamarin/xamarin-android/releases/ you will see that it shows in his VS 2022 enterprise version. It just wasn't there for me in the Community edition, so I followed his instructions and did a > dotnet workload install android and then checked it with > dotnet workload list which reported the expected result.

Maybe there is a difference between installing when using either of those methods

In the morning I'll go through your notes about the tools/proguard folder and check if it is there.

I'm assuming that your test app now runs, without having to add a proguard.cfg to your project. Can you please confirm?

@tipa
Copy link

tipa commented Oct 9, 2023

My test app now runs without proguard.cfg - yes.
However - depending on event handlers I register in my app - I still see the other runtime exceptions you reported above, because R8 seems to link out the *Implementor classes. In one of my apps, I have to add all these to the proguard.cfg:

-keep class android.content.IDialogInterfaceOnShowListenerImplementor { *; } # new MaterialAlertDialogBuilder(ctx).Create().ShowEvent += (s, e) => { };
-keep class android.widget.AdapterView_IOnItemClickListenerImplementor { *; } # FindPreference("xy").PreferenceClick += (s, e) => { };
-keep class android.view.View_IOnClickListenerImplementor { *; }
-keep class android.view.View_IOnLongClickListenerImplementor { *; }

This certainly wasn't needed with .net7...

@dellis1972
Copy link
Contributor

My guess is that it is this line in the now missing proguard-android.txt file (see https://android.googlesource.com/platform/sdk/+/refs/heads/main/files/proguard-android.txt#36)

# We want to keep methods in Activity that could be used in the XML attribute onClick
--
  | -keepclassmembers class * extends android.app.Activity {
  | public void *(android.view.View);
  | }

My guess is by not stripping out and method which contains android.view.View that causes R8 to keep the other things.

dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Oct 9, 2023
Context dotnet#8337
        dotnet#8397

The latest Android sdk no longer ships with `proguard` as a result the
file in proguard-android.txt [1] is missing. As a result customers are
reporting errors such as

```
Unhandled Exception from source=AndroidEnvironment

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor
    at Java.Interop.JniEnvironment.Types.TryFindClass(String , Boolean )
    at Java.Interop.JniEnvironment.Types.FindClass(String )
    at Java.Interop.JniType..ctor(String )
    at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
    at Android.Views.View.IOnClickListenerImplementor..ctor()
    at Android.Views.View.__CreateIOnClickListenerImplementor()
    at Java.Interop.EventHelper.AddEventHandler[IOnClickListener,IOnClickListenerImplementor](WeakReference& , Func`1 , Action`1 , Action`1 )
    at Android.Views.View.add_Click(EventHandler )
    at com.glmsoftware.obdnowpros.Fragments.SubscriptionFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState)
    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2)
    --- End of managed Java.Lang.Exception stack trace ---
```

This is probably because certain code is removed that in the latest version of R8 that used to be
left in place.
We should include the contents of this removed file in our own proguard_xamarin.cfg file.

[1] https://android.googlesource.com/platform/sdk/+/refs/heads/main/files/proguard-android.txt
@dellis1972
Copy link
Contributor

I created a PR which pulls in the contents of the missing proguard-android.txt file.
It would be useful to get confirmation that these changes /file contents actually fix the issue?

See #8403

@tipa
Copy link

tipa commented Oct 9, 2023

Will this really fix the issue? I copy-pasted the contents of proguard-android.txt into my own .cfg file and the app still crashes with the same exceptions. And android.content.IDialogInterfaceOnShowListenerImplementor doesnt contain anything with View.

@dellis1972
Copy link
Contributor

I guess it will fix the android.view.View_IOnClickListenerImplementor issue. The issue you have looks slightly different.

@tipa
Copy link

tipa commented Oct 9, 2023

It also didn't fix the android.view.View_IOnClickListenerImplementor issues. Sample repo:
New folder.zip

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.companyname.New_folder/crc64abe8cc9139195b67.MainActivity}: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor

@dellis1972
Copy link
Contributor

well in that case is not the fact that the proguard-android.txt is missing.

There has always been situations where the end user has to add certain -keep options when trying to build a Release build with r8. I'm not sure how much we should put in the default proguard.cfg as we might end up keeping stuff that really doesn't need to be kept.

@jonpryor @jonathanpeppers do you have any thoughts on this?

@tipa
Copy link

tipa commented Oct 9, 2023

There has always been situations where the end user has to add certain -keep options when trying to build a Release build with r8.

I'm aware of that, the weird thing is just that it wasn't necessary with .NET7. My attached example project above built with NET7 does not crash

@jpobst
Copy link
Contributor

jpobst commented Oct 9, 2023

It is very interesting that you can get your net7.0 version to work for I had exactly the same problem with my .Net7 version.

Interesting, I was using your NavigationGraph8Net8 to test, with 2 changes to make it .NET 7:

  • net8.0-android -> net7.0-android
  • Setting android:targetSdkVersion="33" in AndroidManifest.xml since I couldn't get 34 to compile for other reasons.

jonathanpeppers added a commit to jonathanpeppers/java.interop that referenced this issue Oct 9, 2023
Fixes: dotnet/android#8337

A customer's app with the code:

    SetContentView(Resource.Layout.activity_main);
    FindViewById<Button>(Resource.Id.asd).Click += MainActivity_Click;

Crashes with `-c Release -p:AndroidLinkMode=r8` with:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.companyname.New_folder/crc64abe8cc9139195b67.MainActivity}: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3644)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3781)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:138)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2306)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7918)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
    Caused by: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor
        at crc64abe8cc9139195b67.MainActivity.n_onCreate(Native Method)
        at crc64abe8cc9139195b67.MainActivity.onCreate(MainActivity.java:30)
        at android.app.Activity.performCreate(Activity.java:8342)
        at android.app.Activity.performCreate(Activity.java:8321)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3625)
        ... 12 more

Which, can be solved by adding your own `proguard` rules like:

    -keep class android.view.View_IOnClickListenerImplementor { *; }

In a91ae7f, we thought (incorrectly):

> Additionally, stop emitting the `[Register]` attribute for
> `*Implementor` classes:
>
>    [global::Android.Runtime.Register ("mono/android/view/View_OnFocusChangeListenerImplementor")]
>    partial class IOnFocusChangeListenerImplementor {/* … */}
>
> The `[Register]` attribute is not needed, because `*Implementor`
> classes are generated internal implementation details.

`proguard_xamarin.cfg` has the entry:

    -keep class mono.android.** { *; <init>(...); }

So we could do `android.**`, but that would certainly preserve way too
much!

For now, let's just restore `[Register]` to revisit this issue at a
later date -- maybe .NET 9?
@jpobst
Copy link
Contributor

jpobst commented Oct 9, 2023

Thanks to a full team effort 😅, we believe we have tracked down the regression.

This optimization we did: dotnet/java-interop#1105, removed the [Register] attribute from our generated *Implementor (and other) C# classes. This moved and renamed the Java classes from:

package mono.android.view;
public class View_OnClickListenerImplementor { ... }

to:

package android.view;
public class View_IOnClickListenerImplementor { ... }

Because of this, the Proguard rule we ship to keep these classes no longer works:

-keep class mono.android.** { *; <init>(...); }

We are discussing the best fix given the timeline for .NET 8 GA, likely putting the [Register] attributes back (PR).

Thanks everyone for your reports and test cases, they definitely helped track down this hard to find 🐛!

jonathanpeppers added a commit to jonathanpeppers/java.interop that referenced this issue Oct 9, 2023
Fixes: dotnet/android#8337

A customer's app with the code:

    SetContentView(Resource.Layout.activity_main);
    FindViewById<Button>(Resource.Id.asd).Click += MainActivity_Click;

Crashes with `-c Release -p:AndroidLinkMode=r8` with:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.companyname.New_folder/crc64abe8cc9139195b67.MainActivity}: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3644)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3781)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:138)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2306)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7918)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
    Caused by: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor
        at crc64abe8cc9139195b67.MainActivity.n_onCreate(Native Method)
        at crc64abe8cc9139195b67.MainActivity.onCreate(MainActivity.java:30)
        at android.app.Activity.performCreate(Activity.java:8342)
        at android.app.Activity.performCreate(Activity.java:8321)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3625)
        ... 12 more

Which, can be solved by adding your own `proguard` rules like:

    -keep class android.view.View_IOnClickListenerImplementor { *; }

In a91ae7f, we thought (incorrectly):

> Additionally, stop emitting the `[Register]` attribute for
> `*Implementor` classes:
>
>    [global::Android.Runtime.Register ("mono/android/view/View_OnFocusChangeListenerImplementor")]
>    partial class IOnFocusChangeListenerImplementor {/* … */}
>
> The `[Register]` attribute is not needed, because `*Implementor`
> classes are generated internal implementation details.

`proguard_xamarin.cfg` has the entry:

    -keep class mono.android.** { *; <init>(...); }

So we could do `android.**`, but that would certainly preserve way too
much!

For now, let's just restore `[Register]` to revisit this issue at a
later date -- maybe .NET 9?
jonpryor pushed a commit to dotnet/java-interop that referenced this issue Oct 9, 2023
Fixes: dotnet/android#8337

A customer's app with the code:

	SetContentView(Resource.Layout.activity_main);
	FindViewById<Button>(Resource.Id.asd).Click += MainActivity_Click;

Crashes with `-c Release -p:AndroidLinkMode=r8` with:

	java.lang.RuntimeException: Unable to start activity ComponentInfo{com.companyname.New_folder/crc64abe8cc9139195b67.MainActivity}: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor
	    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3644)
	    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3781)
	    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
	    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:138)
	    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
	    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2306)
	    at android.os.Handler.dispatchMessage(Handler.java:106)
	    at android.os.Looper.loopOnce(Looper.java:201)
	    at android.os.Looper.loop(Looper.java:288)
	    at android.app.ActivityThread.main(ActivityThread.java:7918)
	    at java.lang.reflect.Method.invoke(Native Method)
	    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
	Caused by: java.lang.ClassNotFoundException: android.view.View_IOnClickListenerImplementor
	    at crc64abe8cc9139195b67.MainActivity.n_onCreate(Native Method)
	    at crc64abe8cc9139195b67.MainActivity.onCreate(MainActivity.java:30)
	    at android.app.Activity.performCreate(Activity.java:8342)
	    at android.app.Activity.performCreate(Activity.java:8321)
	    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
	    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3625)
	    ... 12 more

Which, can be solved by adding your own `proguard` rules like:

	-keep class android.view.View_IOnClickListenerImplementor { *; }

In a91ae7f, we thought (incorrectly):

> Additionally, stop emitting the `[Register]` attribute for
> `*Implementor` classes:
>
>     [global::Android.Runtime.Register ("mono/android/view/View_OnFocusChangeListenerImplementor")]
>     partial class IOnFocusChangeListenerImplementor {/* … */}
>
> The `[Register]` attribute is not needed, because `*Implementor`
> classes are generated internal implementation details.

`proguard_xamarin.cfg` has the entry:

	-keep class mono.android.** { *; <init>(...); }

We could do `-keep class android.**` [^0], but that would certainly
preserve way too much!

For now, let's just restore `[Register]` to revisit this issue at a
later date -- maybe .NET 9?

[^0]: Why is `View_IOnClickListenerImplementor` in the `android.view`
      package?!  Because package name generation for Java Callable
      Wrappers is special-cased for `Mono.Android` to simply
      [lowercase the namespace name][0], which applies only if the 
      type *doesn't* have `[RegisterAttribute]`!

[0]: https://github.com/xamarin/java.interop/blob/8e63cc8da1882cadc7db329bfa6cafb6f914769f/src/Java.Interop.Tools.TypeNameMappings/Java.Interop.Tools.TypeNameMappings/JavaNativeTypeManager.cs#L200-L209
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Oct 12, 2023
Context dotnet#8337
        dotnet#8397

The latest Android sdk no longer ships with `proguard` as a result the
file in proguard-android.txt [1] is missing. As a result customers are
reporting errors such as

```
Unhandled Exception from source=AndroidEnvironment

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor
    at Java.Interop.JniEnvironment.Types.TryFindClass(String , Boolean )
    at Java.Interop.JniEnvironment.Types.FindClass(String )
    at Java.Interop.JniType..ctor(String )
    at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
    at Android.Views.View.IOnClickListenerImplementor..ctor()
    at Android.Views.View.__CreateIOnClickListenerImplementor()
    at Java.Interop.EventHelper.AddEventHandler[IOnClickListener,IOnClickListenerImplementor](WeakReference& , Func`1 , Action`1 , Action`1 )
    at Android.Views.View.add_Click(EventHandler )
    at com.glmsoftware.obdnowpros.Fragments.SubscriptionFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState)
    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2)
    --- End of managed Java.Lang.Exception stack trace ---
```

This is probably because certain code is removed that in the latest version of R8 that used to be
left in place.
We should include the contents of this removed file in our own proguard_xamarin.cfg file.

[1] https://android.googlesource.com/platform/sdk/+/refs/heads/main/files/proguard-android.txt
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Oct 23, 2023
Context dotnet#8337
        dotnet#8397

The latest Android sdk no longer ships with `proguard` as a result the
file in proguard-android.txt [1] is missing. As a result customers are
reporting errors such as

```
Unhandled Exception from source=AndroidEnvironment

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor
    at Java.Interop.JniEnvironment.Types.TryFindClass(String , Boolean )
    at Java.Interop.JniEnvironment.Types.FindClass(String )
    at Java.Interop.JniType..ctor(String )
    at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
    at Android.Views.View.IOnClickListenerImplementor..ctor()
    at Android.Views.View.__CreateIOnClickListenerImplementor()
    at Java.Interop.EventHelper.AddEventHandler[IOnClickListener,IOnClickListenerImplementor](WeakReference& , Func`1 , Action`1 , Action`1 )
    at Android.Views.View.add_Click(EventHandler )
    at com.glmsoftware.obdnowpros.Fragments.SubscriptionFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState)
    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2)
    --- End of managed Java.Lang.Exception stack trace ---
```

This is probably because certain code is removed that in the latest version of R8 that used to be
left in place.
We should include the contents of this removed file in our own proguard_xamarin.cfg file.

[1] https://android.googlesource.com/platform/sdk/+/refs/heads/main/files/proguard-android.txt
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Nov 7, 2023
Context dotnet#8337
        dotnet#8397

The latest Android sdk no longer ships with `proguard` as a result the
file in proguard-android.txt [1] is missing. As a result customers are
reporting errors such as

```
Unhandled Exception from source=AndroidEnvironment

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor
    at Java.Interop.JniEnvironment.Types.TryFindClass(String , Boolean )
    at Java.Interop.JniEnvironment.Types.FindClass(String )
    at Java.Interop.JniType..ctor(String )
    at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
    at Android.Views.View.IOnClickListenerImplementor..ctor()
    at Android.Views.View.__CreateIOnClickListenerImplementor()
    at Java.Interop.EventHelper.AddEventHandler[IOnClickListener,IOnClickListenerImplementor](WeakReference& , Func`1 , Action`1 , Action`1 )
    at Android.Views.View.add_Click(EventHandler )
    at com.glmsoftware.obdnowpros.Fragments.SubscriptionFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState)
    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2)
    --- End of managed Java.Lang.Exception stack trace ---
```

This is probably because certain code is removed that in the latest version of R8 that used to be
left in place.
We should include the contents of this removed file in our own proguard_xamarin.cfg file.

[1] https://android.googlesource.com/platform/sdk/+/refs/heads/main/files/proguard-android.txt
dellis1972 added a commit to dellis1972/xamarin-android that referenced this issue Nov 16, 2023
Context dotnet#8337
        dotnet#8397

The latest Android sdk no longer ships with `proguard` as a result the
file in proguard-android.txt [1] is missing. As a result customers are
reporting errors such as

```
Unhandled Exception from source=AndroidEnvironment

Java.Lang.Exception: android.view.View_IOnClickListenerImplementor
    at Java.Interop.JniEnvironment.Types.TryFindClass(String , Boolean )
    at Java.Interop.JniEnvironment.Types.FindClass(String )
    at Java.Interop.JniType..ctor(String )
    at Java.Interop.JniPeerMembers.JniInstanceMethods..ctor(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.GetConstructorsForType(Type )
    at Java.Interop.JniPeerMembers.JniInstanceMethods.StartCreateInstance(String , Type , JniArgumentValue* )
    at Android.Views.View.IOnClickListenerImplementor..ctor()
    at Android.Views.View.__CreateIOnClickListenerImplementor()
    at Java.Interop.EventHelper.AddEventHandler[IOnClickListener,IOnClickListenerImplementor](WeakReference& , Func`1 , Action`1 , Action`1 )
    at Android.Views.View.add_Click(EventHandler )
    at com.glmsoftware.obdnowpros.Fragments.SubscriptionFragment.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState)
    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2)
    --- End of managed Java.Lang.Exception stack trace ---
```

This is probably because certain code is removed that in the latest version of R8 that used to be
left in place.
We should include the contents of this removed file in our own proguard_xamarin.cfg file.

[1] https://android.googlesource.com/platform/sdk/+/refs/heads/main/files/proguard-android.txt
@github-actions github-actions bot locked and limited conversation to collaborators Jan 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App Runtime Issues in `libmonodroid.so`. needs-triage Issues that need to be assigned.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants