Search Unity

Multidex Support on Android

Discussion in 'Android' started by Claytonious, May 12, 2015.

  1. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    Is there any news on when MultiDex builds might be an option? This limitation has truly passed critical mass already for many projects.
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Could you build as an android project (e.g: not as APK) and then perform the final build into an APK to support this ?
     
    Last edited: Sep 5, 2016
  3. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    So the biggest reason we have not added support for this in Unity is because it doesn't work. Or rather it usually creates more problems than it solves. Unless you are targeting only modern versions of Android I would suggest you do everything in your power including stripping and proguarding your code before you take the route of multi-dex.

    If you don't believe me just checkout the _known_ limitations of the multi-dex library at Googles developer page:
    https://developer.android.com/tools/building/multidex.html#limitations

    If you have a project where you really need more than 64k references I would suggest exporting to Android Studio and build the project there.
     
    liortal likes this.
  4. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    But you cannot export to Android Studio, either. When you try to export to Android Studio, Unity still bombs out with the error "Error building Player: CommandInvokationFailure: Unable to convert classes into dex format. See the Console for details." And in the details for the console, you find:

    stderr[
    trouble writing output: Too many method references: 66241; max is 65536.
    You may try using --multi-dex option.
    References by package:
    6 android.accessibilityservice

    etc.

    In other words, you cannot use this solution - you can't even make it to Android Studio project in the first place!
     
    Stranger-Games and LucRyan_ like this.
  5. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    I'm totally willing to try, but Unity won't export such a project in the first place. Are you saying that I should do some dance like:

    1. Manually remove jars and android library projects from /Assets/Plugins/Android so that Unity will build the player successfully
    2. Export to Android Studio
    3. Satisfy those dependencies myself from Android studio

    In other words, I have to give up all of the automated building that Android plugins do for a Unity project in order to do this?
     
    LucRyan_ likes this.
  6. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    The root cause of all of this is things like a publisher insisting that you use a particular set of SDK's. The combination of several Ad networks' SDK's plus Google Play services (yes, even a manually stripped down version of gms at that!) still puts even a trivial Unity game over the method limit.

    Granted, yes, those Ads SDK's are fat bastards! But such is life.
     
  7. psydent

    psydent

    Joined:
    Feb 11, 2013
    Posts:
    12
    @bitter As Claytonious pointed out, what is the solution for not being able to export to Android Studio because of the Unity dexing step?

    @Claytonious, have you figured out a solution?
     
  8. LucktasticWill

    LucktasticWill

    Joined:
    May 27, 2015
    Posts:
    10
    @bitter, are there any updates? As @Claytonious and @psydent pointed out, exporting to Android Studio does not work either because the dexing occurs on export as well as on build.
     
  9. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    Oh! I thought I fixed that. Do you mind filing a bug on the issue so it doesn't get lost (again)?
     
  10. LucktasticWill

    LucktasticWill

    Joined:
    May 27, 2015
    Posts:
    10
  11. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    @LucktasticWill thanks! Just to be clear, the fix I was referring to as fixed was exporting to Android Studio. As for multidex I still don't think that's a good idea. I assume you are aware of all the problems that comes with a mutidex application?

    The first android version to natively support multidex is Android 5. Meaning any versions prior to that may experience problems when you have more than one dex file. And Android 2.3 is more or less completely out of the question. One possibility would be to add support for multidex if minSdkVersion is set to Android 5. Would that be okay?
     
    sudounity likes this.
  12. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    Another option would be to add support for stripping the java code using proguard in Unity. However, due to the complexity of code obfuscation / stripping I think this is something better done in Android Studio. What do you think?
     
  13. LucktasticWill

    LucktasticWill

    Joined:
    May 27, 2015
    Posts:
    10
    @bitter, Ideally I'd like to be able to build and run the project in Unity, and be able to take advantage of Unity Cloud Build, but I understand that the fix you had referred to was to be able to export the project to Android Studio only.
     
  14. noyeti

    noyeti

    Joined:
    Apr 25, 2014
    Posts:
    18
  15. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    I haven't actually checked, but I would imagine those are just regular dependencies. Instead of one big AAR/JAR with everything, it's split into multiple files.
     
  16. noyeti

    noyeti

    Joined:
    Apr 25, 2014
    Posts:
    18
    @bitter from what I have read, this is the support that google have offered to deal with the large number of function inside the google play services (>20k) to allow user to use more of the 64k limit

    *edit*
    ok penny dropped - you still need to use ProGuard to make sure the the other libs an't included :/
     
    Last edited: Nov 20, 2015
  17. harryd31

    harryd31

    Joined:
    Oct 16, 2015
    Posts:
    3
    @bitter it is true that multidex causes issues in older devices however for developers such as myself who are targeting only modern ones we shouldn't have that limit. Multidex should be optional when targeting API 14 and up http://developer.android.com/about/dashboards/index.html which is now more then 95% of the market. In our specific case we are trying to port 12M users to unity but our multidex issues continuously get in the way
     
    Last edited: Dec 29, 2015
  18. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    We released a fix for the export issue. It should be available as of Unity 4.6.9p4 and 5.3.1.

    @harryd31 even on ICS multi-dex can cause issues.

    The plan forward right now is to add support for ProGuard first. And the next step would be to add support for the API-21 multi-dex setup. Possibly with the option to deploy for lower APIs but with a large disclaimer telling you it may crash ;-)
     
  19. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    Awesome news. Thank you - eager and ready to try it out.
     
  20. infosekr

    infosekr

    Joined:
    Jul 12, 2013
    Posts:
    46
    Hi guys, I ran into the ref count limitation so I built a Android Studio project with 5.3.1. I am unable to build an APK though because I run into this error signing the APK: "Error:Android Packager: java.io.IOException: Keystore was tampered with, or password was incorrect".

    I'm using the same keystore file that works in Unity with the same password. If I enter an invalid keystore or key password Android Studio even prompts me before the build that they are incorrect.

    Has anyone encountered this problem? Found a work around?

    Thanks.
     
  21. Martin______

    Martin______

    Joined:
    Feb 1, 2016
    Posts:
    4
    @bitter Heya, I was wondering about the status of ProGuard support during the Unity build process? And will these fixes be available in 5.2.x ? Thanks!
     
  22. noyeti

    noyeti

    Joined:
    Apr 25, 2014
    Posts:
    18
    I had many errors when exporting the project, in the end I used a utility called JarJar to reduce the size of the google play services - was the path of least resistance.
     
  23. Martin______

    Martin______

    Joined:
    Feb 1, 2016
    Posts:
    4
    @noyeti How did you determine what to strip and what to keep? Or did you already have it exported into and Android project and had dependencies determined?
     
  24. noyeti

    noyeti

    Joined:
    Apr 25, 2014
    Posts:
    18
    guess work ;)

    I had:
    keep com.google.android.gms.analytics.*
    keep com.google.android.gms.auth.*
    keep com.google.android.gms.common.*
    keep com.google.android.gms.ads.*
    keep com.google.ads.*

    I think I only required the advertisers id from GPS, I could have stripped more but wasn't inclined to re-test all the features to make sure nothing was broken. I am sure I could have opened the exported android project and used proguard but the number of errors I was getting and the time fixing that meant I decided to strip the play services instead.

    (downside is you would need re-visit this setup if you were to add some new functionality such as google maps, probably need to re-strip it when targeting later versions of the android platform)

    More fun was getting the launchMode set to "standard" (instead of singleTask) without using the exported android project but that's another story.
     
  25. Gizmoi

    Gizmoi

    Joined:
    Jan 9, 2013
    Posts:
    327
    Is there a way to find out what parts are used?
    I tried to remove google.android.nearby, but apparently GPGS uses that during login.

    I'm having to dig into the .jar files and remove classes that sound like they probably aren't used by me.
    Is there a better way?
     
  26. Martin______

    Martin______

    Joined:
    Feb 1, 2016
    Posts:
    4
    Unfortunately, we haven't really found a better way then just manually stripping the files. We mainly stripped third party libraries, were we where sure that the stripped classes were not used.

    What you can also try is to "repackage" your libraries, i.e. moving them all to a common namespace as described in point (4) in:
    https://androidthoughts.wordpress.c...version-to-dalvik-format-failed-with-error-2/

    That worked for a couple of libraries for us (but not all).
     
  27. Lszt

    Lszt

    Joined:
    Sep 28, 2015
    Posts:
    38
    I tried to generate an Android Project but I get some issue during the process :/.
    I need to do this cause I have the 65k references issues with my apk due to a huge plugins number -_- (thx to the customer)
    I mean I generate the "Android Project" but after this I can't generate an APK nor a direct runtime build on a device cause I always have issues with my plugins.

    My hierarchy is this one :
    Plugins/Android/{list_plugins_folders}

    but when I build the Android Project, I didn't know if I must open the project generate from the root which contains all plugins folder and build folder or if I must open only the build folder then associate each plugin with a dependancie.

    Another thing is : Do I must convert all the project to a gradle one ? It seems to be the best way but I don't really know if it's really much more effective ?

    Any ETA for the proguard support directly in Unity android build ? :)
     
  28. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    @bitter is there any update on proguard support? Thanks!
     
  29. MrPhil

    MrPhil

    Joined:
    Sep 22, 2010
    Posts:
    40
    I too am very interesting in any details and resources on how this works!
     
  30. jonestictoc

    jonestictoc

    Joined:
    Jun 24, 2013
    Posts:
    7
    Any updates on this? I need the DEX limit fixed for Unity. Thanks.
     
  31. Lszt

    Lszt

    Joined:
    Sep 28, 2015
    Posts:
    38
    what kind of plugins have you in your project ?
    I succeed to solve this issue by limiting the number of Google Play Services plugins integrated in my project. So do you use Google Play Services ?
     
  32. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Mirroring my reply from this thread: http://forum.unity3d.com/threads/too-many-method-references-max-is-65536.327064/page-2#post-2777571

     
  33. jonestictoc

    jonestictoc

    Joined:
    Jun 24, 2013
    Posts:
    7
    Any updates on this? This post is pretty quiet. Is proguard or multi-dex supported in any new versions of Unity? I am in the planning stages for a new project and the client wants a ton of ad networks, so I need to know what my options are. Thanks.
     
  34. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Unity 5.5 supports Gradle, so you should be able to set up proguard eventually.
    I've deliberately mentioned "eventually", since setting it up can oftentimes be a difficult and long game of trial & error, and also because last time i checked, you can't provide a custom gradle build file of your own (it uses a single default one from the Unity installation folder), so customizing this process is a bit hacky at the moment.

    Should be probably made better soon in an update / patch release.
     
  35. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    Actually, now that this new option is in 5.5, we're pretty much there because building to a Gradle project respects the [PostProcessBuild] attribute, so you can monkey with the generated build.gradle file yourself before invoking gradle to build the APK:

    Code (CSharp):
    1. [PostProcessBuild]
    2. public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject)
    3. {
    4.     if (buildTarget == BuildTarget.Android)
    5.     {
    6.         string productName = PlayerSettings.productName;
    7.         string gradleFilename = PathExtensions.Combine(pathToBuiltProject, productName, "build.gradle");
    8.         Debug.Log("Processing build.gradle at [" + gradleFilename + "]");
    9.         // Do stuff to build.gradle, like turn on Multidex, etc.
    10.     }
    11. }
    12.  
    Then you can just invoke gradle yourself to build the APK as part of your pipeline. Works pretty nicely now. We were able to delete a ton of custom code that did this ourselves previously.

    Code (CSharp):
    1.  
    2. EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;
    3. EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
    4. BuildPipeline.BuildPlayer(...your scenes, etc....)
    5. // Invoke Gradle with System.Diagnostics.Process...
    6.  
     
    JohnTube likes this.
  36. Loomabox

    Loomabox

    Joined:
    Nov 4, 2015
    Posts:
    47
    Can you give more details on that?
     
  37. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    What details are you looking for?
     
  38. Loomabox

    Loomabox

    Joined:
    Nov 4, 2015
    Posts:
    47
    I have solved the problem. Thank you.
     
  39. palrahul

    palrahul

    Joined:
    Mar 26, 2014
    Posts:
    1
    @Loomabox How did you end up solving the problem.
    Or what exactly did you solve, can we specify the Multidex gradle attribute from within Unity, without having to export into Android Studio.
     
  40. rsodre

    rsodre

    Joined:
    May 9, 2012
    Posts:
    229
    First option: Build with Gradle.
    You'll probably have to fix a lot of conflicts to make it work.
    If Gradle fails with DexIndexOverflowException (same problem), follow this.
     
  41. lorux

    lorux

    Joined:
    Feb 9, 2017
    Posts:
    31
    On newer versions of Unity this is fixed.
    You have to change the Build System from File->Build Settings to Gradle.
    Then you have to add a file named: mainTemplate.gradle in your Assets/Plugins/Android/ folder. This file should look like this:
    Code (CSharp):
    1. // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN
    2. buildscript {
    3.     repositories {
    4.         jcenter()
    5.     }
    6.  
    7.     dependencies {
    8.         classpath 'com.android.tools.build:gradle:2.1.0'
    9.     }
    10. }
    11.  
    12. allprojects {
    13.    repositories {
    14.       flatDir {
    15.         dirs 'libs'
    16.       }
    17.    }
    18. }
    19.  
    20. apply plugin: 'com.android.application'
    21.  
    22. dependencies {
    23.     compile fileTree(dir: 'libs', include: ['*.jar'])
    24. **DEPS**}
    25.  
    26. android {
    27.     compileSdkVersion **APIVERSION**
    28.     buildToolsVersion '**BUILDTOOLS**'
    29.  
    30.     defaultConfig {
    31.         targetSdkVersion **TARGETSDKVERSION**
    32.         applicationId '**APPLICATIONID**'
    33.     }
    34.  
    35.     lintOptions {
    36.         abortOnError false
    37.     }
    38. **SIGN**
    39.     buildTypes {
    40.         debug {
    41.             jniDebuggable true
    42.             multiDexEnabled true
    43.         }
    44.         release {
    45.             minifyEnabled false
    46.             multiDexEnabled true
    47.             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'
    48.             **SIGNCONFIG**
    49.         }
    50.     }
    51.  
    52. }
    As you can see multiDexEnabled true on debug and release build types.

    Then, on the AndroidManifest.xml, (Assets/Plugins/Android/) you have to add multidex to application tag:
    Code (CSharp):
    1. <application
    2.     android:theme="@style/UnityThemeSelector"
    3.     android:icon="@drawable/app_icon"
    4.     android:label="@string/app_name"
    5.     android:debuggable="true"
    6.     android:name="android.support.multidex.MultiDexApplication">
    7. ...
    8. </application>
     
    Last edited: Oct 5, 2017
    yuliyF, SweatyChair and Deleted User like this.
  42. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    If your game supports Android versions older than 5.0, i think this will not work, since the MultiDexApplication was not available to those OS versions.

    You can check out this link for reference: https://developer.android.com/studio/build/multidex.html
    Specifically, check out the section named 'Multidex support prior to Android 5.0'
     
    lifeisfunxyz likes this.
  43. Claytonious

    Claytonious

    Joined:
    Feb 16, 2009
    Posts:
    903
    Yes but if you use your own custom Application subclass compiled from Java, you can support pre 5.0 devices, too.
     
  44. Deleted User

    Deleted User

    Guest

    Why not use Gradle in unity , and enable multidexing it fixed the problem and i didn't have to export the project anymore also i didn't use pro guard. Gradle it self reduces the method reference count.
     
  45. leite2

    leite2

    Joined:
    Dec 31, 2017
    Posts:
    1
    Hello,
    @nicolas_lorusso I followed your instructions, but i got this error

    CommandInvokationFailure: Gradle build failed.
    C:/Program Files/Java/jdk1.8.0_31\bin\java.exe -classpath "C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\gradle\lib\gradle-launcher-2.14.jar" org.gradle.launcher.GradleMain "assembleDebug"

    stderr[
    C:\Users\Public\Documents\Unity Projects\MyGame\Temp\gradleOut\src\main\AndroidManifest.xml:17:3-79 Error:
    Element uses-permission#android.permission.WRITE_EXTERNAL_STORAGE at AndroidManifest.xml:17:3-79 duplicated with element declared at AndroidManifest.xml:12:3-106
    C:\Users\Public\Documents\Unity Projects\My Game\Temp\gradleOut\src\main\AndroidManifest.xml Error:
    Validation failed, exiting

    FAILURE: Build failed with an exception.

    * What went wrong:
    Execution failed for task ':processDebugManifest'.
    > Manifest merger failed with multiple errors, see logs


    I have the facebook, everyplay, google ads sdk in the test game

    Did you have an idea, how to solve it?

    Thanks
     
  46. warmanw

    warmanw

    Joined:
    Feb 2, 2015
    Posts:
    32
    Hi guys, our project was doing well in version 5.3.5, after upgrading to 5.4.6 it started to throwing an error about DEX limitation 65k. what happened?

    I know I can solve it with gradle, multidex or stripping some code. I dont look for solution just curious why it happened after upgrading the unity?
     
    Last edited: Feb 26, 2018
    rkamalya likes this.
  47. kiwipxl

    kiwipxl

    Joined:
    Jun 9, 2015
    Posts:
    11
    @warmanw If you drag your old apk into Android Studio (or go to Build -> Analyze APK), assuming you have Android Studio >= 3.0.1, you can click on classes.dex and it'll show you how large your dex count is and where exactly most of the methods/references are coming from.

    I'm guessing your old apk was only just under the dex count (65536) and upgrading to the newer Unity just pushed it over the edge a little bit.

    I think when you go over the limit Unity will post some dex count details in the console where you can see how much over your dex count is. If it's only over by a very small amount and you don't plan to add more libraries to your game, I'd suggest stripping as much as you can to get it under the limit.

    Otherwise multidex, proguard or downgrading your unity are the next options.
     
  48. kiwipxl

    kiwipxl

    Joined:
    Jun 9, 2015
    Posts:
    11
    @leite2 this stuff is always fun. You could try experiment with android manifest merging with the tools:replace tool, but you might not have much luck with that. Try look into all your android manifests in your project and see if there is a duplicate WRITE_EXTERNAL_STORAGE tag. If there isn't, then it's somewhere in your libraries. One option is to extract your libraries, modify the AndroidManifest, and compress it back. I'd suggest exporting to an Android Studio project while doing this as it lets you trial and error a lot faster.
     
  49. warmanw

    warmanw

    Joined:
    Feb 2, 2015
    Posts:
    32
    @kiwipxl we dont use android studio, just build from unity with gradle, Thanks for the response, The limit is exceeded twice 13k . So there is no know thing that unity 2017 uses special method to build which exceeds the method calls. we actually have fixed it with gradle + proguard. however I was curious why after upgrading from 5.3.5.
     
  50. psycodex

    psycodex

    Joined:
    Oct 11, 2016
    Posts:
    2
    Claytonious likes this.