PermaLink Automating Android OrmLite Configuration Generation w/ Gradle02/17/2014 05:32 PM
OrmLite provides a standard ORM data mapping layer for Android, but if you want to avoid the performance hit from reflections (it uses annotations), you have to run a generator to make a configuration file that can be loaded at runtime.  Unfortunately, there haven't been any examples of how to do this and the OrmLite documention just mentions it's Advanced usage :-P

The reflection garbage collection issue causing most of this slowness has been fixed as of Android 4.1, but generating the config at compile time will still help your application startup time.  Thankfully, we can do this easily w/ Gradle.

OrmLite's config generator basically wants to compile your DAO/beans so it can do the reflection at compile time. Because of this, you really don't want to do generation of this inside your Android application directory because your code will call the DAOs which won't work properly if you haven't run config generation on them yet. The simplest way to automate the config generation is in another directory/project and then copy the config file back into your project.

First, create an ormlite-gen directory at the same level as your app directory. Create a simple AndroidManifest.xml in case your DAOs use any Android APIs. Replace "yourpackage" with your app's package root (e.g., com.mycompany.myapp):

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="yourpackage"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <application>
    </application>
</manifest>

Then, for the build.gradle in the ormlite.gen directory, you can do use this (the ormlitedaopath is the one you put your OrmLite DAOs/beans in and the ormlitedbpath is where you put the DatabaseConfigUtil for OrmLite which is usually in your app's db subdirectory):

import org.apache.tools.ant.taskdefs.condition.Os

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.8.+'
    }
}

apply plugin: 'android'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.j256.ormlite:ormlite-android:4.48'
    compile 'com.google.code.gson:gson:2.2.+'
}

// change paths for android plugin
android {
    compileSdkVersion 19
    buildToolsVersion '19.0.1'
    sourceSets {
        main {
            manifest {
                srcFile 'AndroidManifest.xml'
            }
            java {
                srcDir 'src'
                srcDir '../app/src/main/java/ormlitedaopath'
                srcDir '../app/src/main/java/ormlitedbpath'
                exclude 'DbOpenHelper.java'
            }
            resources {
                srcDir 'src/resources'
            }
        }
    }
}

ext.CfgFileName = 'ormlite_config.txt'
ext.SrcCfgPath = '../app/src/main/res/raw/'
ext.GenCfgPath = 'build/classes/debug/app/src/main/res/raw/'

task copyConfigHereTask(type: Copy) {
    from SrcCfgPath+CfgFileName
    into GenCfgPath
}

task copyConfigBackTask(type: Copy) {
    from GenCfgPath+CfgFileName
    into SrcCfgPath
}

task runOrmGenTask(type: Exec) {
    workingDir './build/classes/debug'
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        commandLine 'cmd', '/c', 'java',
          '-cp', '../../../libs/*;.',
          'yourpackage.db.DatabaseConfigUtil'
    } else {
        commandLine 'java',
          '-cp', '../../../libs/*:.',
          'yourpackage.db.DatabaseConfigUtil'
    }
}

task genOrmCfg(dependsOn: ['clean', 'assembleDebug',
 'copyConfigHereTask', 'runOrmGenTask', 'copyConfigBackTask']) {
    println "Generating OrmLite Config..."
    assembleDebug.mustRunAfter clean
    copyConfigHereTask.mustRunAfter assembleDebug
    runOrmGenTask.mustRunAfter copyConfigHereTask
    copyConfigBackTask.mustRunAfter runOrmGenTask
}

The magic happens in the genOrmCfg which does the copy/gen/copy to update our app's config file for OrmLite. You can also add a src subdirectory and add any files needed to get your DAOs to build in this environment.

Finally, you can add this to your Android app subdirectory's build.gradle to run this external project automatically each time you build (it's very quick so it doesn't affect your compile times enough to leave it out). This will add the external gradle call to every Android assemble task and take care of the typical "Debug" and "Release" variants:

task runOrmGenTask(type: GradleBuild) {
    buildFile = '../ormlite-gen/build.gradle'
    tasks = ['genOrmCfg']
}
android.applicationVariants.all { variant ->
    ext.variantname = "assemble" + variant.name.capitalize()
    //println "Looking for variant ${variantname}"
    def targetTask = project.tasks.findByName("${variantname}")
    if (targetTask != null) {
        println "Adding dependency to ${variant.name}"
        targetTask.dependsOn("runOrmGenTask")
        targetTask.mustRunAfter("runOrmGenTask")
    }
}

Comments :v
No comments.

Start Pages
RSS News Feed RSS Comments Feed CoComment Integrated
The BlogRoll
Calendar
July 2014
Su
Mo
Tu
We
Th
Fr
Sa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Search
Contact Me
About Ken
Full-stack developer (consultant) working with .Net, Java, Android, Javascript (jQuery, Meteor.js, AngularJS), Lotus Domino