Guilherme Torres Castro
Guilherme Torres Castro

Reputation: 15350

ClassNotFoundException when inflating a binding library using Xamarin

I have made a custom binding for the twoway-view library.

The DLL generate seems to okay, I can do the following without any problem:

var twoWayView = new Org.Lucasr.TwoWayView.Widget.TwoWayView(this);

however if a try to instantiate the class using java reflection:

Java.Lang.Class.ForName("Org.Lucasr.TwoWayView.Widget.TwoWayView")

I got an ClassNotFoundException, which it the same exception that occur when trying to inflate a layout that have TwoWayView in it like this one:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:id="@+id/MyButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/Hello" />
    <Org.Lucasr.Twowayview.Widget.TwoWayView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:scrollbars="vertical"
        app:twowayview_layoutManager="StaggeredGridLayoutManager"
        app:twowayview_numColumns="2"
        app:twowayview_numRows="1" />
</LinearLayout>

Edit

Using dexdump as described here I can see the class is inside my apk:

Class #1172            -
  Class descriptor  : 'Lorg/lucasr/twowayview/widget/TwoWayView;'
  Access flags      : 0x0001 (PUBLIC)
  Superclass        : 'Landroid/support/v7/widget/RecyclerView;'
  Interfaces        -

Edit 2

Using org.lucasr.twowayview.widget.TwoWayView give me the same error.

The complete Exception is:

01-23 13:02:04.837 I/MonoDroid(17779): UNHANDLED EXCEPTION: 
01-23 13:02:04.861 I/MonoDroid(17779): Android.Views.InflateException: Exception of type 'Android.Views.InflateException' was thrown. 
01-23 13:02:04.861 I/MonoDroid(17779): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <IL 0x00011, 0x00068> 
01-23 13:02:04.861 I/MonoDroid(17779): at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (intptr,intptr,intptr,Android.Runtime.JValue[]) [0x00084] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:896 
01-23 13:02:04.861 I/MonoDroid(17779): at Android.App.Activity.SetContentView (int) [0x00070] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.App.Activity.cs:4253 
01-23 13:02:04.861 I/MonoDroid(17779): at Org.Lucasr.TwoWayView.Sample.MainActivity.OnCreate (Android.OS.Bundle) [0x0001d] in c:\Users\guilherme\Documents\Visual Studio 2013\Projects\Org.Lucasr.TwoWayView\Org.Lucasr.TwoWayView.Sample\MainActivity.cs:25 
01-23 13:02:04.862 I/MonoDroid(17779): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.App.Activity.cs:2179 
01-23 13:02:04.862 I/MonoDroid(17779): at (wrapper dynamic-method) object.e4603f87-2e86-4a8a-9cd2-213f87378350 (intptr,intptr,intptr) <IL 0x00017, 0x00043> 
01-23 13:02:04.862 I/MonoDroid(17779):   --- End of managed exception stack trace --- 
01-23 13:02:04.862 I/MonoDroid(17779): android.view.InflateException: Binary XML file line #1: Error inflating class Org.Lucasr.Twowayview.Widget.TwoWayView 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:757) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:806) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.inflate(LayoutInflater.java:414) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.inflate(LayoutInflater.java:365) 
01-23 13:02:04.862 I/MonoDroid(17779):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:377) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.Activity.setContentView(Activity.java:2144) 
01-23 13:02:04.862 I/MonoDroid(17779):  at org.lucasr.twowayview.sample.MainActivity.n_onCreate(Native Method) 
01-23 13:02:04.862 I/MonoDroid(17779):  at org.lucasr.twowayview.sample.MainActivity.onCreate(MainActivity.java:28) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.Activity.performCreate(Activity.java:5933) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.ActivityThread.access$800(ActivityThread.java:144) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.os.Handler.dispatchMessage(Handler.java:102) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.os.Looper.loop(Looper.java:135) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.app.ActivityThread.main(ActivityThread.java:5221) 
01-23 13:02:04.862 I/MonoDroid(17779):  at java.lang.reflect.Method.invoke(Native Method) 
01-23 13:02:04.862 I/MonoDroid(17779):  at java.lang.reflect.Method.invoke(Method.java:372) 
01-23 13:02:04.862 I/MonoDroid(17779):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
01-23 13:02:04.862 I/MonoDroid(17779):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
01-23 13:02:04.862 I/MonoDroid(17779): Caused by: java.lang.ClassNotFoundException: Didn't find class "Org.Lucasr.Twowayview.Widget.TwoWayView" on path: DexPathList[[zip file "/data/app/Org.Lucasr.TwoWayView.Sample-1/base.apk"],nativeLibraryDirectories=[/data/app/Org.Lucasr.TwoWayView.Sample-1/lib/arm, /vendor/lib, /system/lib]] 
01-23 13:02:04.862 I/MonoDroid(17779):  at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) 
01-23 13:02:04.862 I/MonoDroid(17779):  at java.lang.ClassLoader.loadClass(ClassLoader.java:511) 
01-23 13:02:04.862 I/MonoDroid(17779):  at java.lang.ClassLoader.loadClass(ClassLoader.java:469) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.createView(LayoutInflater.java:571) 
01-23 13:02:04.862 I/MonoDroid(17779):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743) 
01-23 13:02:04.862 I/MonoDroid(17779):  ... 21 more 
01-23 13:02:04.862 I/MonoDroid(17779):  Suppressed: java.lang.ClassNotFoundException: Org.Lucasr.Twowayview.Widget.TwoWayView 
01-23 13:02:04.862 I/MonoDroid(17779):      at java.lang.Class.classForName(Native Method) 
01-23 13:02:04.862 I/MonoDroid(17779):      at java.lang.BootClassLoader.findClass(ClassLoader.java:781) 
01-23 13:02:04.863 I/MonoDroid(17779):      at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) 
01-23 13:02:04.863 I/MonoDroid(17779):      at java.lang.ClassLoader.loadClass(ClassLoader.java:504) 
01-23 13:02:04.863 I/MonoDroid(17779):      ... 24 more 
01-23 13:02:04.863 I/MonoDroid(17779):  Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available An unhandled exception occured.  
01-23 13:02:05.453 E/mono    (17779):  
01-23 13:02:05.453 E/mono    (17779): Unhandled Exception: 
01-23 13:02:05.453 E/mono    (17779): Android.Views.InflateException: Exception of type 'Android.Views.InflateException' was thrown. 
01-23 13:02:05.453 E/mono (17779): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <IL 0x00011, 0x00068> 
01-23 13:02:05.453 E/mono    (17779): at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (intptr,intptr,intptr,Android.Runtime.JValue[]) [0x00084] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:896 
01-23 13:02:05.453 E/mono    (17779): at Android.App.Activity.SetContentView (int) [0x00070] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.App.Activity.cs:4253 
01-23 13:02:05.453 E/mono    (17779): at Org.Lucasr.TwoWayView.Sample.MainActivity.OnCreate (Android.OS.Bundle) [0x0001d] in c:\Users\guilherme\Documents\Visual Studio 2013\Projects\Org.Lucasr.TwoWayView\Org.Lucasr.TwoWayView.Sample\MainActivity.cs:25 
01-23 13:02:05.453 E/mono    (17779): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.App.Activity.cs:2179 
01-23 13:02:05.453 E/mono    (17779): at (wrapper dynamic-method) object.e4603f87-2e86-4a8a-9cd2-213f87378350 (intptr,intptr,intptr) <IL 0x00017, 0x00043> 
01-23 13:02:05.453 E/mono    (17779):  
01-23 13:02:05.453 E/mono    (17779):   --- End of managed exception stack trace --- 
01-23 13:02:05.453 E/mono    (17779): android.view.InflateException: Binary XML file line #1: Error inflating class Org.Lucasr.Twowayview.Widget.TwoWayView 
01-23 13:02:05.453 E/mono    (17779):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:757) 
01-23 13:02:05.453 E/mono    (17779):   at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
01-23 13:02:05.453 E/mono    (17779):   at android.view.LayoutInflater.inflate(LayoutInflater.java:414) 
01-23 13:02:05.453 E/mono    (17779):   at android.view.LayoutInflater.inflate(LayoutInflater.java:365) referenceTable GDEF length=670 1 referenceTable GSUB length=7202 1 referenceTable GPOS length=24560 1 
01-23 13:02:05.453 E/mono    (17779):   at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:377) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.Activity.setContentView(Activity.java:2144) 
01-23 13:02:05.453 E/mono    (17779):   at org.lucasr.twowayview.sample.MainActivity.n_onCreate(Native Method) 
01-23 13:02:05.453 E/mono    (17779):   at org.lucasr.twowayview.sample.MainActivity.onCreate(MainActivity.java:28) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.Activity.performCreate(Activity.java:5933) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.ActivityThread.access$800(ActivityThread.java:144) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
01-23 13:02:05.453 E/mono    (17779):   at android.os.Handler.dispatchMessage(Handler.java:102) 
01-23 13:02:05.453 E/mono    (17779):   at android.os.Looper.loop(Looper.java:135) 
01-23 13:02:05.453 E/mono    (17779):   at android.app.ActivityThread.main(ActivityThread.java:5221) 
01-23 13:02:05.453 E/mono    (17779):   at java.lang.reflect.Method.invoke(Native Method)

Upvotes: 7

Views: 1828

Answers (3)

user1725145
user1725145

Reputation: 4042

I got this error when I referenced a bindings libary in a .dll that was included in my Xamarin app. Using dexdump.exe, it was possible to see that the class was not defined in the dex files.

When I also referenced the bindings libary into the main Xamarin app, the class was properly generated and had an entry in classes.dex.

Upvotes: 1

tobi_b
tobi_b

Reputation: 1238

I had a similar problem with a Loading Progress Button library and I did the following steps to solve the problem:

  1. Create a custom view which you are able to inflate via xml
  2. Let this view extend from the original view you would like to inflate
  3. Pay attention to the Exception because it may be the case the library uses packages you didn't reference in your project yet and that's why you still get a ClassDefNotFoundException.

For me it turned out the library was using some classes of the kotlin stdLib during inflation. Because it happend during inflation the exceptions hadn't been thrown when I created the view via code. Adding the Xamarin.Kotlin.StdLib package to my project then solved the problem for me.

I've also learned the package name really is case sensitive, so you should use exactly the same package name as it is used in native android/java.

Upvotes: 1

jonjarn
jonjarn

Reputation: 56

This sound similar to an issue I had when trying to dynamically create objects using reflection. In my case, it was the Xamarin Linker that removed the class when building.

You can read more about the linker here: https://developer.xamarin.com/guides/android/advanced_topics/linking/

Try setting it to "Don't link", to see if that removes the error. If so, you need to reference the class statically or mark it as Preserve.

Upvotes: 1

Related Questions