Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Multidex option causes crashes on Android 4.4 and lower

ClockAppDevClockAppDev NLMember ✭✭
edited September 2016 in Xamarin.Android

Recently I updated to Xamarin.Android 7.0 and followed the steps at https://bugzilla.xamarin.com/show_bug.cgi?id=44187 (e.g. updating to Proguard 5.3) to make sure my application would build using Multidex.
However, ever since then my application won't run on Android 4.4 and lower anymore. When the application starts the following crash is thrown up:

java.lang.RuntimeException: Unable to instantiate application md54a1433ef09e6de402ea89150af9214f9.MyApplication
Caused by: java.lang.ClassNotFoundException: Didn't find class "md54a1433ef09e6de402ea89150af9214f9.MyApplication" on path: DexPathList[[zip file "/data/app/com.mymultidextest.TestApplication-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.mymultidextest.TestApplication-1, /vendor/lib, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    at android.app.Instrumentation.newApplication(Instrumentation.java:968)
    at android.app.LoadedApk.makeApplication(LoadedApk.java:499)

I unpacked and decompiled the build and it seems the MyApplication class has been placed in the classes2.dex file, causing Android 4.4 and lower to fail (since those Android versions only only support Application classes in the first classes.dex file). The compiled application class is still properly extending the MultiDexApplication class and works fine on Android 5.0 and up.

Is there a way to make sure classes that extends Android.App.Application end up in the first classes.dex file on Xamarin.Android 7.0?

Best Answer

Answers

  • ClockAppDevClockAppDev NLMember ✭✭
    edited September 2016

    Thanks! Indeed I was building on Windows. Adjusting the .bat script solved the issue for me!

  • JimBennettJimBennett GBXamarin Team, Insider, University, Developer Group Leader ✭✭✭✭

    Awesome! Happy to help (although all credit to @JonDouglas for finding the fix in the first place)

  • VarunRVarunR USUniversity ✭✭

    @JimBennett @JonDouglas @BradleyLocke @AlexandreChohfi.0033

    Hi
    I'm using xamarin studio on mac. The app has multidex option enabled.
    I'm trying to run the app on Jellybean devices and the app crashes with the following application output.

    App works fine on Android M,N,L devices

    [SELinux] Function: selinux_android_load_priority [0], There is no sepolicy file
    [SELinux]
    [SELinux] Function: selinux_android_load_priority [1], There is no sepolicy version file
    [SELinux]
    [SELinux] Function: selinux_android_load_priority , loading version is VE=SEPF_GT-I9300_4.3_0016
    [SELinux]
    [SELinux]
    [SELinux] selinux_android_seapp_context_reload: seapp_contexts file is loaded from /seapp_contexts
    [AndroidRuntime] Shutting down VM
    [AndroidRuntime] FATAL EXCEPTION: main
    [AndroidRuntime] java.lang.NoClassDefFoundError: mono.MonoPackageManager_Resources
    [AndroidRuntime] at mono.MonoPackageManager.LoadApplication(MonoPackageManager.java:54)
    [AndroidRuntime] at mono.MonoRuntimeProvider.attachInfo(MonoRuntimeProvider.java:22)
    [AndroidRuntime] at android.app.ActivityThread.installProvider(ActivityThread.java:5119)
    [AndroidRuntime] at android.app.ActivityThread.installContentProviders(ActivityThread.java:4725)
    [AndroidRuntime] at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4665)
    [AndroidRuntime] at android.app.ActivityThread.access$1400(ActivityThread.java:159)
    [AndroidRuntime] at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376)
    [AndroidRuntime] at android.os.Handler.dispatchMessage(Handler.java:99)
    [AndroidRuntime] at android.os.Looper.loop(Looper.java:176)
    [AndroidRuntime] at android.app.ActivityThread.main(ActivityThread.java:5419)
    [AndroidRuntime] at java.lang.reflect.Method.invokeNative(Native Method)
    [AndroidRuntime] at java.lang.reflect.Method.invoke(Method.java:525)
    [AndroidRuntime] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
    [AndroidRuntime] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
    [AndroidRuntime] at dalvik.system.NativeStart.main(Native Method)

    Currently I'm using the following xamarin configuration.

    Xamarin Studio Enterprise
    Version 6.1.2 (build 44)
    Installation UUID: a3da647d-db58-4b39-81af-bb6676db7247
    Runtime:
    Mono 4.6.2 (mono-4.6.0-branch/db69866) (64-bit)
    GTK+ 2.24.23 (Raleigh theme)

    Package version: 406020006

    NuGet
    Version: 3.4.3.0

    Xamarin.Profiler
    Not Installed

    Apple Developer Tools
    Xcode 8.0 (11246)
    Build 8A218a

    Xamarin.Mac
    Not Installed

    Xamarin.Android
    Version: 7.0.2.38 (Xamarin Enterprise)
    Android SDK: /Users/developer/Library/Android/sdk
    Supported Android versions:
    4.1 (API level 16)
    4.2 (API level 17)
    4.3 (API level 18)
    4.4 (API level 19)
    4.4.87 (API level 20)
    5.0 (API level 21)
    5.1 (API level 22)
    6.0 (API level 23)
    7.0 (API level 24)

    SDK Tools Version: 25.2.2
    SDK Platform Tools Version: 25
    SDK Build Tools Version: 24.0.3

    Java SDK: /usr
    java version "1.8.0_101"
    Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
    Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)

  • JonDouglasJonDouglas USXamarin Team, University, Developer Group Leader Xamurai

    Make sure your multidex.keep file has a definition for this item: mono.MonoPackageManager_Resources.

    Otherwise please read my two blogs on this topic:

    http://www.jon-douglas.com/2016/09/05/xamarin-android-multidex/

    http://www.jon-douglas.com/2016/09/23/xamarin-android-multidex-keep/

  • VarunRVarunR USUniversity ✭✭

    @JonDouglas

    The issue happens in MAC. In MAC the .bat is different i'm unable to find the definitions written in your post.
    Can you guide me on how to make it working on MAC. I have pasted the mainDexClasses.bat

    !/bin/bash

    #

    Copyright (C) 2013 The Android Open Source Project

    #

    Licensed under the Apache License, Version 2.0 (the "License");

    you may not use this file except in compliance with the License.

    You may obtain a copy of the License at

    #

    http://www.apache.org/licenses/LICENSE-2.0

    #

    Unless required by applicable law or agreed to in writing, software

    distributed under the License is distributed on an "AS IS" BASIS,

    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

    See the License for the specific language governing permissions and

    limitations under the License.

    function makeTempJar ()
    {
    local tempDir=/tmp
    if [ ! -e "${tempDir}" ]; then
    tempDir=.
    fi
    local tempfile="${tempDir}/mainDexClasses-$$.tmp.jar"
    if [ -e "${tempfile}" ]; then
    echo "Failed to create temporary file" >2
    exit 6
    fi
    echo "${tempfile}"
    }

    function cleanTmp ()
    {
    if [ -e "${tmpOut}" ] ; then
    rm "${tmpOut}"
    fi
    }

    Set up prog to be the path of this script, including following symlinks,

    and set up progdir to be the fully-qualified pathname of its directory.

    prog="$0"

    while [ -h "${prog}" ]; do
    newProg=/bin/ls -ld "${prog}"
    newProg=expr "${newProg}" : ".* -> \(.*\)$"
    if expr "x${newProg}" : 'x/' >/dev/null; then
    prog="${newProg}"
    else
    progdir=dirname "${prog}"
    prog="${progdir}/${newProg}"
    fi
    done
    oldwd=pwd
    progdir=dirname "${prog}"
    cd "${progdir}"
    progdir=pwd
    prog="${progdir}"/basename "${prog}"
    cd "${oldwd}"

    baserules="${progdir}"/mainDexClasses.rules
    if [ ! -r ${baserules} ]; then
    echo basename "$prog"": can't find mainDexClasses.rules" 1>&2
    exit 1
    fi

    jarfile=dx.jar
    libdir="$progdir"

    if [ ! -r "$libdir/$jarfile" ]; then
    # set dx.jar location for the SDK case
    libdir="$libdir/lib"
    fi

    if [ ! -r "$libdir/$jarfile" ]; then
    # set dx.jar location for the Android tree case
    libdir=dirname "$progdir"/framework
    fi

    if [ ! -r "$libdir/$jarfile" ]; then
    echo basename "$prog"": can't find $jarfile" 1>&2
    exit 1
    fi

    proguardExec="proguard.sh"
    proguard=${PROGUARD_HOME}/bin/${proguardExec}

    if [ ! -r "${proguard}" ]; then
    # set proguard location for the SDK case
    proguardBaseDir=dirname "$progdir"
    # "${progdir}"/../..
    proguardBaseDir=dirname "$proguardBaseDir"
    proguard="${proguardBaseDir}"/tools/proguard/bin/${proguardExec}
    fi

    if [ ! -r "${proguard}" ]; then
    # set proguard location for the Android tree case
    proguardBaseDir=dirname "$proguardBaseDir"
    # "${progdir}"/../../../..
    proguardBaseDir=dirname "$proguardBaseDir"
    proguard="${proguardBaseDir}"/external/proguard/bin/${proguardExec}
    fi

    if [ ! -r "${proguard}" ]; then
    proguard="which proguard"
    fi

    if [ -z "${proguard}" -o ! -r "${proguard}" ]; then
    proguard="which ${proguardExec}"
    fi

    if [ -z "${proguard}" -o ! -r "${proguard}" ]; then
    echo basename "$prog"": can't find ${proguardExec}" 1>&2
    exit 1
    fi

    shrinkedAndroidJar="${SHRINKED_ANDROID_JAR}"
    if [ -z "${shrinkedAndroidJar}" ]; then
    shrinkedAndroidJar=shrinkedAndroid.jar
    fi

    if [ ! -r "${shrinkedAndroidJar}" ]; then
    shrinkedAndroidJar=${libdir}/${shrinkedAndroidJar}
    fi

    if [ ! -r "${shrinkedAndroidJar}" ]; then
    echo basename "$prog"": can't find shrinkedAndroid.jar" 1>&2
    exit 1
    fi

    if [ "$OSTYPE" = "cygwin" ]; then
    # For Cygwin, convert the jarfile path into native Windows style.
    jarpath=cygpath -w "$libdir/$jarfile"
    proguard=cygpath -w "${proguard}"
    shrinkedAndroidJar=cygpath -w "${shrinkedAndroidJar}"
    else
    jarpath="$libdir/$jarfile"
    fi

    disableKeepAnnotated=

    while true; do
    if expr "x$1" : 'x--output' >/dev/null; then
    exec 1>$2
    shift 2
    elif expr "x$1" : 'x--disable-annotation-resolution-workaround' >/dev/null; then
    disableKeepAnnotated=$1
    shift 1
    else
    break
    fi
    done

    if [ $# -ne 1 ]; then
    echo "Usage : $0 [--output ] " 1>&2
    exit 2
    fi

    tmpOut=makeTempJar

    trap cleanTmp 0

    ${proguard} -injars ${@} -dontwarn -forceprocessing -outjars ${tmpOut} \
    -libraryjars "${shrinkedAndroidJar}" -dontoptimize -dontobfuscate -dontpreverify \
    -include "${baserules}" 1>/dev/null || exit 10

    java -cp "$jarpath" com.android.multidex.MainDexListBuilder ${disableKeepAnnotated} "${tmpOut}" ${@} || exit 11

  • JonDouglasJonDouglas USXamarin Team, University, Developer Group Leader Xamurai
    edited November 2016

    Mac does not have the bug inside and the multidex.keep file should be generated with a proper mainDexClassList.

  • FrancescoBorghiFrancescoBorghi USMember
    edited November 2016

    @JimBennett @JonDouglas

    I followed all the steps in

    http://www.jon-douglas.com/2016/09/05/xamarin-android-multidex/
    http://www.jon-douglas.com/2016/09/23/xamarin-android-multidex-keep/

    I modified the mainDexClasses.bat lines and then
    created the multidex.keep file (associated to the correct build action) with inside I put the list of classes generated in debug mode with multidex enable (about 500 classes).

    It seems that multidex is not creating the classes2.dex because I expected to found it in the release folder.

    My app crash with the following error:

    [MultiDex] VM with version 1.6.0 does not have multidex support
    [MultiDex] install
    [MultiDex] MultiDexExtractor.load(/data/app/com.ideolo.malpensa-1.apk, false)
    [MultiDex] Detected that extraction must be performed.
    [MultiDex] load found 0 secondary dex files
    [MultiDex] install done

    [libc] Fatal signal 11 (SIGSEGV) at 0x000000b4 (code=1), thread 2913 (my.package)

    Do I forget something to do with configuration?

    Here is my configuration.

    === Xamarin Studio Business ===

    Version 6.1.1 (build 15)
    Installation UUID: f157ad88-3c18-4328-a584-6f506e7f5973
    Runtime:
    Microsoft .NET 4.0.30319.42000
    GTK+ 2.24.26 (Light theme)
    GTK# 2.12.38

    === NuGet ===

    Version: 3.4.3.0

    === Xamarin.Profiler ===

    Not Installed

    === Xamarin.Android ===

    Version: 7.0.1.6 (Xamarin Business)
    Android SDK: D:\ANDROID\SDK
    Supported Android versions:
    2.3 (API level 10)
    4.0.3 (API level 15)
    4.1 (API level 16)
    4.4 (API level 19)
    4.4.87 (API level 20)
    5.0 (API level 21)
    5.1 (API level 22)
    6.0 (API level 23)

    SDK Tools Version: 25.2.2
    SDK Platform Tools Version: 25
    SDK Build Tools Version: 23.0.2

    Java SDK: C:\Program Files (x86)\Java\jdk1.7.0_79
    java version "1.7.0_79"
    Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
    Java HotSpot(TM) Client VM (build 24.79-b02, mixed mode, sharing)

    Android Designer EPL code available here:
    https://github.com/xamarin/AndroidDesigner.EPL

    === Xamarin Android Player ===

    Not Installed

    === Build Information ===

    Release ID: 601010015
    Git revision: fa52f02641726146e2589ed86ec4097fbe101888
    Build date: 2016-09-22 08:12:03-04
    Xamarin addins: 75d65712af93d54dc39ae4c42b21dfa574859fd6
    Build lane: monodevelop-windows-cycle8-sr0

    === Operating System ===

    Windows 6.1.7601.65536 (64-bit)

  • JonDouglasJonDouglas USXamarin Team, University, Developer Group Leader Xamurai

    @FrancescoBorghi Do you have enough references to actually need an extra classes2.dex? That would be my first guess. Use ClassyShark.jar to do this easily with your .dex file. My second question would be...If you are able to run your project without the multidex feature enabled. That would also determine if the reference limit is under the maximum.

  • @JonDouglas Thank you! ClassyShark.jar is a great tool and after refactoring my project I set multidex feature disable. And now it works again.

  • MaximAlexeyevMaximAlexeyev USMember ✭✭

    @JonDouglas , I followed instructions for modifying a.bat file, however it did nothing. Empty multidex.keep file was generated. Checked .bat file multiple times.

    Then I followed second advice, and included manually created mulridex.keep to my project with required Build action. It did the trick, but now I have problem with next dependency.

    Question, is there a way to identify all required classes, to not try them one by one? Or, maybe there is some new correction for first fix with params in bat file?

    Thanks.

  • MaximAlexeyevMaximAlexeyev USMember ✭✭

    Actually, it wasn't that bad, just 6 classes after all to be added to multidex.keep, and at seems to be running in 4.4. emulator.

  • DanielArayaDanielAraya DEMember ✭✭

    Be aware that right now, there's another bug (missing line breaks in the multidex.keep file) that will prevent this solution from working properly.
    Things started working again after I edited the multidex.keep file and added (Windows) line breaks after each ".class" in the file.

    The new bug is documented here: https://bugzilla.xamarin.com/show_bug.cgi?id=59036

Sign In or Register to comment.