locked
Multi Dex app with a custom application class that runs on pre-Lollipop RRS feed

  • Question

  • User212348 posted

    There are a quite a few posts scattered around about this but my question is:

    Has anyone managed to successfully build a MultiDex enabled app that utilizes a custom Application class that will run on pre - Lollipop devices?

    For people who wanted to learn more about it keep reading.

    The issues is that when creating a MultiDex app that uses a custom application class (I'd guess the vast majority of apps over the 65k limit would be in this category), that class does not end up in the first dex file which causes devices without built in MultiDex support to crash with the error

    [AndroidRuntime] java.lang.RuntimeException: Unable to instantiate application md5a3fc106bb082f0a6c07b5025b0a464e3.MyApplication: java.lang.ClassNotFoundException: Didn't find class "md5a3fc106bb082f0a6c07b5025b0a464e3.MyApplication" on path

    I've tried all of the listed solutions, including from Xamarin support in order to get to this to work.

    There are numerous articles about it:

    https://bugzilla.xamarin.com/showbug.cgi?id=35491 https://bugzilla.xamarin.com/showbug.cgi?id=38693 https://forums.xamarin.com/discussion/57485/multiple-issues-with-library-project-and-multidex

    What I've done:

    I have created a custom MultiDexMainDexList file by using a modified version of the mainDexClasses.bat file (as per the articles).

    I then modified the command that Xamarin throws at it to use the full path names as Xamarin just tries to use "obj\Debug"

    mainDexClassesfixed.bat --output C:\Users\bradl000\Documents\blocke79\App\App\obj\Debug\multidex.keep "'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v6.0\mono.android.jar';'C:\androidsdk\extras\android\support\multidex\library\libs\android-support-multidex.jar';'C:\Users\bradl000\Documents\blocke79\App\App\obj\Debug_libraryprojects\Aniways.AndroidBinding\libraryproject_imports\aniways-V2.3.08.jar'" (have trimmed this massive list for reading)

    This produces a MultiDexMainDexList file with all of the classes in my project. which I then add this to my project with the new build action of "MultiDexMainDexList" (only available in Alpha channel v6).

    This gets rid of the error regarding the application class but instead throws a new error regarding not being able to find the PackageManager class.

    I then started thinking that I should trim down the entire list of classes in the MultiDexMainDexList file and keep only the ones that I think my custom application class needs to load. No matter what I've done to this list I still get the error regarding the PackageManager.

    Has anyone traveled the same path with more success than me? Is it even possible?

    Thursday, April 7, 2016 5:34 PM

Answers

  • User212348 posted

    Thanks to the genius of Alexandre Chohfi there is now a fix for this. Following the routine I described above to create the MultiDexMainDexList file using the custom batch file.

    You then need to create the MultiDexApplication class below. In your custom application class overload this class instead of Application.

    Details are here: https://bugzilla.xamarin.com/show_bug.cgi?id=40515

    using System;
    using Android.App;
    using Android.Runtime;
    using Java.Interop;
    
    namespace Sample
    {
        [Register("android/support/multidex/MultiDexApplication", DoNotGenerateAcw = true)]
        public class MultiDexApplication : Application
        {
            internal static readonly JniPeerMembers _members =
                new XAPeerMembers("android/support/multidex/MultiDexApplication", typeof (MultiDexApplication));
    
            internal static IntPtr java_class_handle;
    
            private static IntPtr id_ctor;
    
            [Register(".ctor", "()V", "", DoNotGenerateAcw = true)]
            public MultiDexApplication()
                : base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
            {
                if (Handle != IntPtr.Zero)
                    return;
    
                try
                {
                    if (GetType() != typeof (MultiDexApplication))
                    {
                        SetHandle(
                            JNIEnv.StartCreateInstance(GetType(), "()V"),
                            JniHandleOwnership.TransferLocalRef);
                        JNIEnv.FinishCreateInstance(Handle, "()V");
                        return;
                    }
    
                    if (id_ctor == IntPtr.Zero)
                        id_ctor = JNIEnv.GetMethodID(class_ref, "<init>", "()V");
                    SetHandle(
                        JNIEnv.StartCreateInstance(class_ref, id_ctor),
                        JniHandleOwnership.TransferLocalRef);
                    JNIEnv.FinishCreateInstance(Handle, class_ref, id_ctor);
                }
                finally
                {
                }
            }
    
            protected MultiDexApplication(IntPtr javaReference, JniHandleOwnership transfer)
                : base(javaReference, transfer)
            {
            }
    
            internal static IntPtr class_ref
            {
                get { return JNIEnv.FindClass("android/support/multidex/MultiDexApplication", ref java_class_handle); }
            }
    
            protected override IntPtr ThresholdClass
            {
                get { return class_ref; }
            }
    
            protected override Type ThresholdType
            {
                get { return typeof (MultiDexApplication); }
            }
        }
    }
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, May 4, 2016 5:10 PM

All replies

  • User212348 posted

    As an update the actual error about package manager is

    java.lang.NoClassDefFoundError%3A+mono.MonoPackageManager_Resources

    Friday, April 8, 2016 2:52 PM
  • User212348 posted

    I've also posted on StackOverflow. Might get a better response there

    http://stackoverflow.com/q/36502564/4349446

    Friday, April 8, 2016 2:54 PM
  • User27321 posted

    I have the same issue.

    Sunday, April 10, 2016 2:41 PM
  • User27321 posted

    Switch Beta channel , Update to Xamarin 4.1.0.33 and Xamarin Studio 6.0.0 version! They have fixed the bug! My app can work below 5.0!Thanks Xamarin Team!

    Tuesday, April 12, 2016 2:17 AM
  • User212348 posted

    Hi klark - thanks for the heads up.

    I've just upgraded and tried my app but I'm getting the same issue as before.

    java.lang.NoClassDefFoundError: mono.MonoPackageManager_Resources.

    Would you mind sharing you MultiDexKeepList file so I can compare with mine?

    Tuesday, April 12, 2016 6:47 AM
  • User193464 posted

    Having the same error as @BradleyLocke.1401 on the latest beta : [AndroidRuntime] Shutting down VM [AndroidRuntime] FATAL EXCEPTION: main [AndroidRuntime] Process: com.eroad.driverna, PID: 31444 [AndroidRuntime] java.lang.NoClassDefFoundError: mono.MonoPackageManager_Resources [AndroidRuntime] at mono.MonoPackageManager.LoadApplication(MonoPackageManager.java:52) [AndroidRuntime] at mono.MonoRuntimeProvider.attachInfo(MonoRuntimeProvider.java:22) [AndroidRuntime] at android.app.ActivityThread.installProvider(ActivityThread.java:5199) [AndroidRuntime] at android.app.ActivityThread.installContentProviders(ActivityThread.java:4794) [AndroidRuntime] at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4734) [AndroidRuntime] at android.app.ActivityThread.access$1500(ActivityThread.java:166) [AndroidRuntime] at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1343) [AndroidRuntime] at android.os.Handler.dispatchMessage(Handler.java:102) [AndroidRuntime] at android.os.Looper.loop(Looper.java:136) [AndroidRuntime] at android.app.ActivityThread.main(ActivityThread.java:5590) [AndroidRuntime] at java.lang.reflect.Method.invokeNative(Native Method) [AndroidRuntime] at java.lang.reflect.Method.invoke(Method.java:515) [AndroidRuntime] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) [AndroidRuntime] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) [AndroidRuntime] at dalvik.system.NativeStart.main(Native Method)

    Wednesday, April 13, 2016 5:05 AM
  • User212348 posted

    Does anyone from Xamarin Support have anything to say about this one?

    Thursday, April 14, 2016 8:09 AM
  • User212348 posted

    Thanks to the genius of Alexandre Chohfi there is now a fix for this. Following the routine I described above to create the MultiDexMainDexList file using the custom batch file.

    You then need to create the MultiDexApplication class below. In your custom application class overload this class instead of Application.

    Details are here: https://bugzilla.xamarin.com/show_bug.cgi?id=40515

    using System;
    using Android.App;
    using Android.Runtime;
    using Java.Interop;
    
    namespace Sample
    {
        [Register("android/support/multidex/MultiDexApplication", DoNotGenerateAcw = true)]
        public class MultiDexApplication : Application
        {
            internal static readonly JniPeerMembers _members =
                new XAPeerMembers("android/support/multidex/MultiDexApplication", typeof (MultiDexApplication));
    
            internal static IntPtr java_class_handle;
    
            private static IntPtr id_ctor;
    
            [Register(".ctor", "()V", "", DoNotGenerateAcw = true)]
            public MultiDexApplication()
                : base(IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
            {
                if (Handle != IntPtr.Zero)
                    return;
    
                try
                {
                    if (GetType() != typeof (MultiDexApplication))
                    {
                        SetHandle(
                            JNIEnv.StartCreateInstance(GetType(), "()V"),
                            JniHandleOwnership.TransferLocalRef);
                        JNIEnv.FinishCreateInstance(Handle, "()V");
                        return;
                    }
    
                    if (id_ctor == IntPtr.Zero)
                        id_ctor = JNIEnv.GetMethodID(class_ref, "<init>", "()V");
                    SetHandle(
                        JNIEnv.StartCreateInstance(class_ref, id_ctor),
                        JniHandleOwnership.TransferLocalRef);
                    JNIEnv.FinishCreateInstance(Handle, class_ref, id_ctor);
                }
                finally
                {
                }
            }
    
            protected MultiDexApplication(IntPtr javaReference, JniHandleOwnership transfer)
                : base(javaReference, transfer)
            {
            }
    
            internal static IntPtr class_ref
            {
                get { return JNIEnv.FindClass("android/support/multidex/MultiDexApplication", ref java_class_handle); }
            }
    
            protected override IntPtr ThresholdClass
            {
                get { return class_ref; }
            }
    
            protected override Type ThresholdType
            {
                get { return typeof (MultiDexApplication); }
            }
        }
    }
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, May 4, 2016 5:10 PM
  • User169500 posted

    A Xamarin guy helped this guy fix it.

    https://www.jimbobbennett.io/fixing-issues-with-multidex-on-pre-lollipop-devices-on-windows/

    Thursday, July 7, 2016 8:29 AM
  • User275505 posted

    @BradleyLocke your solution working so thanks

    But I override OnCreate() on MultiDexApplication class but this method does not call on application start Have any idea about this issue.

    Wednesday, May 24, 2017 7:34 AM
  • User293644 posted

    i'm also getting this error and i have changed my mainDexClasses.bat file but still unable to run my project on pre-lollipop devices please help me with issue.

    Wednesday, July 19, 2017 6:14 AM
  • User29278 posted

    I'm having an issue where even after modifying the build process to ensure that the base application class (and dependencies) are in the first dex file, the app still fails on 4.4 devices. I can unpack the dex and confirm that the correct class files are there, but it still fails. Is this completely broken? I have resorted to rolling back to older versions of the support libraries to prevent my application from going over the 64k limit to bypass multidex altogether.

    Also, does the linker only apply to .NET dlls or should it also apply to Java .class files? It currently has no affect on the size of the .class files.

    Wednesday, July 19, 2017 11:58 PM
  • User31956 posted

    Hello,

    I'm working on a custom application class, I can make the application running which extends from MultiDexApplication but not custom application.

    Any clues?

    Thursday, July 27, 2017 3:39 PM
  • User78724 posted

    I got the similar issue on Mac. Does anyone solve the issue on Mac?

    Friday, August 18, 2017 4:22 AM
  • User245831 posted

    @KohCheanSiong said: Hello,

    I'm working on a custom application class, I can make the application running which extends from MultiDexApplication but not custom application.

    Any clues?

    Which version of Xamarin Android SDK do you use? Look here:

    https://forums.xamarin.com/discussion/comment/292493/#Comment_292493

    Monday, August 21, 2017 7:24 PM