Google Summer of Code - Week 11

After much experimentation I have decided to move on and integrate the library to the Fennec. First to integrate it in the Fennec I have added the following in the Gradle file.

dependencies {
    compile 'com.evernote:android-job:1.0.11'
}

After adding this in Gradle file will have the library added on all the Fennec Builds that are based on Gradle. But obviously the builds will not be succeeded when we build Fennec during mach builds. To add support for mach builds we have to manually add the library to the third-party directory in the Android source directory. Generally small and tiny independent libraries will be added to the third-party directories. So I added all the files to the source directory. This library had some other dependencies. The Android-Job library has a dependancy on another Logging library. So I have added all the related files manually to the third-party directory.

I created Bug 1291180 to push the code to the Fennec. The process of adding the third-party library in Fennec is not straight forward as the we do in normal applications. So as mentioned above I have added the source code of the library to the Fennec’s Third-party directory. After adding the source code in the tree, I have made a few changes to the configuration files to make sure the library is available and packed along with the build. I have added Receivers and Services that are required to be added in the Manifest file in the base directory of the android source tree. After adding the necessary configurations to the manifest file I have to make sure that the build system picks up the files from the Third-Party directory. For making the Mozilla Mach build system to pick up the files I had made a few changes to the moz.build file. We are packaging the java source files of the Third-Party Directory as a jar file.

gtjar = add_java_jar('gecko-thirdparty')

gtjar.sources += [ thirdparty_source_dir + f for f in [
...
#individual files.
...
] ]

The following files have been added to the Third-Party directory and the same list of files have been added in the moz.build file.

'com/evernote/android/job/gcm/JobProxyGcm.java',
'com/evernote/android/job/gcm/PlatformGcmService.java',
'com/evernote/android/job/Job.java',
'com/evernote/android/job/JobBootReceiver.java',
'com/evernote/android/job/JobCreator.java',
'com/evernote/android/job/JobCreatorHolder.java',
'com/evernote/android/job/JobExecutor.java',
'com/evernote/android/job/JobManager.java',
'com/evernote/android/job/JobProxy.java',
'com/evernote/android/job/JobRequest.java',
'com/evernote/android/job/JobStorage.java',
'com/evernote/android/job/util/Device.java',
'com/evernote/android/job/util/GcmAvailableHelper.java',
'com/evernote/android/job/util/JobApi.java',
'com/evernote/android/job/util/JobCat.java',
'com/evernote/android/job/util/JobPreconditions.java',
'com/evernote/android/job/util/JobUtil.java',
'com/evernote/android/job/util/support/FastXmlSerializer.java',
'com/evernote/android/job/util/support/PersistableBundleCompat.java',
'com/evernote/android/job/util/support/XmlUtils.java',
'com/evernote/android/job/v14/JobProxy14.java',
'com/evernote/android/job/v14/PlatformAlarmReceiver.java',
'com/evernote/android/job/v14/PlatformAlarmService.java',
'com/evernote/android/job/v21/JobProxy21.java',
'com/evernote/android/job/v21/PlatformJobService.java',
'net/vrallev/android/cat/Cat.java',
'net/vrallev/android/cat/CatGlobal.java',
'net/vrallev/android/cat/CatLog.java',
'net/vrallev/android/cat/CatUtil.java',
'net/vrallev/android/cat/instance/CatEmpty.java',
'net/vrallev/android/cat/instance/CatLazy.java',
'net/vrallev/android/cat/instance/CatSimple.java',
'net/vrallev/android/cat/instance/CatStaticClass.java',
'net/vrallev/android/cat/print/AndroidLog.java',
'net/vrallev/android/cat/print/CatPrinter.java'

After adding these files manually into the build now we can remove the Gradle configurations as the necessary files are made available locally. Now there is another issue that I had to address is, the Android-Job may also schedule the jobs with GcmNetworkManager. Now the library has another dependancy - Google Play Services. I took references from the previous bugs. Adjust SDK is not configured to include play-services-analytics, Upgrade Google Play Services dependencies from 8.1.0 to 8.4.0, Integrate the Adjust campaign tracking SDK into Firefox. I found that to add dependancy to the third party library I have to make a few changes to the moz.build file. Currently the file has an option to include the dependancies for the existing library.

gtjar.extra_jars = [
    CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
    CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
    CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
]

So I have added the following lines to include the Google play services as a dependancy for the existing library.

CONFIG['ANDROID_PLAY_SERVICES_GCM_AAR_LIB'],
CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_LIB']

But even after adding the dependancy there was a compilation error. There were few missing dependancies. I have also decompiled Google Play Services library to make sure that the necessary dependancies are included into the build. I found that the necessary files were found in

CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB']

Added those dependancies and the build had no errors and the mach build was successful. Now moving on to the Gradle build, I executed the following

./gradlew clean app:assembleLocalOldDebug

After executing the above command I encountered an Exception during build. The stacktrace is as follows.

Dex: Error converting bytecode to dex:
Cause: com.android.dex.DexIndexOverflowException: Cannot merge new index 65768 into a non-jumbo instruction!
    UNEXPECTED TOP-LEVEL EXCEPTION:
    com.android.dex.DexIndexOverflowException: Cannot merge new index 65768 into a non-jumbo instruction!
        at com.android.dx.merge.InstructionTransformer.jumboCheck(InstructionTransformer.java:111)
        at com.android.dx.merge.InstructionTransformer.access$800(InstructionTransformer.java:26)
        at com.android.dx.merge.InstructionTransformer$StringVisitor.visit(InstructionTransformer.java:74)
        at com.android.dx.io.CodeReader.callVisit(CodeReader.java:114)
        at com.android.dx.io.CodeReader.visitAll(CodeReader.java:89)
        at com.android.dx.merge.InstructionTransformer.transform(InstructionTransformer.java:50)
        at com.android.dx.merge.DexMerger.transformCode(DexMerger.java:826)
        at com.android.dx.merge.DexMerger.transformMethods(DexMerger.java:800)
        at com.android.dx.merge.DexMerger.transformClassData(DexMerger.java:773)
        at com.android.dx.merge.DexMerger.transformClassDef(DexMerger.java:669)
        at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:523)
        at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:164)
        at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)
        at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:504)
        at com.android.dx.command.dexer.Main.runMonoDex(Main.java:334)
        at com.android.dx.command.dexer.Main.run(Main.java:277)
        at com.android.dx.command.dexer.Main.main(Main.java:245)
        at com.android.dx.command.Main.main(Main.java:106)

The DexIndexOverflowException generally I encountered is for exceeding the number of method limits. That can be resolved by enabling the MultiDex in the application. But this is nothing related to the number of methods. This is different and as said in SoundCloud Blog and it is related to the number of strings that can be referenced in a DEX File. This can be resolved by enabling the Jumbo Mode. Adding the following in App Gradle file.

dexOptions {
    jumboMode true
}

So Gradle build using the gradlew tool is successful after enabling the jumbo instructions in the application. Now after adding the and enabling stuffs mentioned above I opened the Fennec code in Android Studio. There were errors in the Third-Party directory. Apparently the code in the Third-Party directory depends on the Google Play Services and I wrote the configurations for the mach builds and the Gradle Build in Android Studio needs the dependancy added in the Gradle file of the Third-Party Project. I added the dependancy by the following line.

provided "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"

So this finally adds the library to the Fennec Codebase and now all the Mach and Gradle based builds are successful. I have also started working on the implementing the JobManager and JobCreator for the Fennec.

Updated: