Monday, 17. February 2014
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's no documented automated way of doing this. We were evaluating OrmLite for Mustbin's Android application and I ended up automating the generation of this file.02/17/2014
At the top level of your project, create an ormlite-gen directory. You'll typically have beans w/ annotations in a beans or DB directory in your own application. These beans might use classes that are Android based (e.g. Parceable), so the ormlite-gen directory has to include Android libraries to compile your beans. You'll need a simple AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mustbin.mustbin"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application >
</application>
</manifest>
Then you also need a build.gradle in the ormlite-gen directory:
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.+'
}
android {
compileSdkVersion 19
buildToolsVersion '19.0.1'
sourceSets {
main {
manifest {
srcFile 'AndroidManifest.xml'
}
java {
srcDir 'src'
srcDir '../app/src/main/java/com/mustbin/mustbin/api/beans'
srcDir '../app/src/main/java/com/mustbin/mustbin/db'
exclude 'MustbinOpenHelper.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/*:.', 'com.mustbin.mustbin.db.DatabaseConfigUtil'
} else {
//commandLine 'pwd'
commandLine 'java', '-cp', '../../../libs/*:.', 'com.mustbin.mustbin.db.DatabaseConfigUtil'
}
}
task genOrmCfg(dependsOn: ['clean', 'assembleDebug', 'copyConfigHereTask', 'runOrmGenTask', 'copyConfigBackTask']) {
println "Generating OrmLite Config..."
// the following locks the order of execution
assembleDebug.mustRunAfter clean
copyConfigHereTask.mustRunAfter assembleDebug
runOrmGenTask.mustRunAfter copyConfigHereTask
copyConfigBackTask.mustRunAfter runOrmGenTask
}
The main task is named genOrmCfg and copies over the OrmLite DatabaseConfigUtil to do the compile of the beans that are referenced by the srcDir parameters. Once that is done, it copies the ormlite_config.txt back to the appropriate place in your app's project.
Lastly, you have to modify your app's build.gradle to run this genOrmCfg task:
//// This section generates the config file for OrmLite and copies it to the right place
task runOrmGenTask(type: Exec) {
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")
}
}
This will run the OrmLite generator every time you compile to make sure everything is up-to-date. If you want to cut down your compile times, you can run the "runOrmGenTask" manually instead, but you might run into a situation where your classes are newer than the ormlite_config.txt file.