Monday, May 4, 2015

Multidex issue in Android Development

Times Now Android App is one of the most feature-rich apps available for Android.
With features like Push Notifications, News Feed, Recording Videos and Uploading, Linking with Google(Plus), Twitter and Facebook and an embedded version of Times Now Newshour (a complete app in its own right) all working together in real-time, the complexity and volume of code creates technical challenges that few, if any, other Android developers face--especially on older versions of the platform.

One of these challenges is related to the way Android's runtime engine, the Dalvik Virtual Machine, handles Java methods.
This App caused the number of Java methods drastically increase.

As we were testing we faced a bug related to over 65k Methods (Too many methods issue) .


After a bit of panic, we realized that we could work around this problem by breaking our app into multiple dex files, using the technique described here,  which focuses on using secondary dex files for extension modules, not core parts of the app.

However, there was no way we could break our app up this way--too many of our classes are accessed directly by the Android framework and different SDKs .
This wasn't normally possible, but we examined the Android source code and used Java reflection to directly modify some of its internal structures.
We were certainly glad and grateful that Android is open source—otherwise, this change wouldn’t have been possible.

We tried various techniques to reclaim space, including aggressive use of ProGuard/MinifyEnabled and source code transformations to reduce our method count.
Nothing we tried had a significant impact, and we still needed to write many more methods to support all of the rich content types in our new and improved news feed and timeline.

As it stood with our code, It was not easy to release our App TimesNow version 1.0.0.
It seemed like we would have to choose between cutting significant features from the app.
Nothing seemed acceptable. We needed a better solution.

Then we decided having multiple dex files in our APK,
We tried a lot solutions but were not getting success. And finally after a lot work we got the solution..
We built code and ran it on device, it ran successfully, this gave a smile on our face and self confidence that we handled a big problem which was not handled by many developers till now.

So Here we are giving tips/instructions to handle this problem if you will ever face it.

1. Create a text file (with name multidex.keep) in app module of project at the level of src and libs.
    Copy and paste these lines of code in your this created text file

Level of multidex.keep file in your project

android/support/multidex/BuildConfig/class
android/support/multidex/MultiDex$V14/class
android/support/multidex/MultiDex$V19/class
android/support/multidex/MultiDex$V4/class
android/support/multidex/MultiDex/class
android/support/multidex/MultiDexApplication/class
android/support/multidex/MultiDexExtractor$1/class
android/support/multidex/MultiDexExtractor/class
android/support/multidex/ZipUtil$CentralDirectory/class
android/support/multidex/ZipUtil/class

2. Edit your build.gradle file and add following blue bold lines

android {
    minSdkVersion 16
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "your.package.name"
        ..........    }

    buildTypes {
        release {
         .............................
        }
    }
// Inside android part of build.gradle
    dexOptions {
        preDexLibraries = false
    }

}
.............
............

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
     ..................

// Inside dependencies part of build.gradle
    compile 'com.android.support:multidex:1.0.1'
    ..............
}


// Outside android part of build.gradle
afterEvaluate {
    tasks.matching {
        it.name.startsWith('dex')
    }.each { dx ->
        if (dx.additionalParameters == null) {
            dx.additionalParameters = []
        }
        dx.additionalParameters += '--multi-dex'
        dx.additionalParameters += "--main-dex-list=$projectDir/multidex.keep".toString()
    }

     ........
     .......
}

3.  Edit your Application class and add following blue bold lines

public class MyApp extends MultiDexApplication {
  ....
  ....
}


And Now You are done with this issue.
Refer developer website here to read more about this issue and handling it.

Thanks a lot for this much patience.

No comments:

Post a Comment