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?
Are you building on Windows? If so this is an issue with the android build tools. Details on the fix here:
https://www.jimbobbennett.io/fixing-issues-with-multidex-on-pre-lollipop-devices-on-windows/
http://www.jon-douglas.com/2016/09/05/xamarin-android-multidex/
Answers
Are you building on Windows? If so this is an issue with the android build tools. Details on the fix here:
https://www.jimbobbennett.io/fixing-issues-with-multidex-on-pre-lollipop-devices-on-windows/
http://www.jon-douglas.com/2016/09/05/xamarin-android-multidex/
Thanks! Indeed I was building on Windows. Adjusting the .bat script solved the issue for me!
Awesome! Happy to help (although all credit to @JonDouglas for finding the fix in the first place)
@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)
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/
@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>&2exit 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"
/frameworkfi
if [ ! -r "$libdir/$jarfile" ]; then
echo
basename "$prog"
": can't find $jarfile" 1>&2exit 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>&2exit 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>&2exit 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
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
Mac does not have the bug inside and the
multidex.keep
file should be generated with a propermainDexClassList
.@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 thencreated 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
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)
@FrancescoBorghi Do you have enough references to actually need an extra
classes2.dex
? That would be my first guess. UseClassyShark.jar
to do this easily with your.dex
file. My second question would be...If you are able to run your project without themultidex
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 setmultidex
feature disable. And now it works again.@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.
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.
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