Current Stories
PermaLink Reproducible Cooking w/ Anova's Sous Vide Circulator01/17/2015
After adding a sous-vide circulator to my cooking tools last year, I realized how much of a similarity this had w/ some of the Jenkins build automation work I've done.  Restaurants use sous-vide to provide almost an idiot-proof consistency to their dishes as well as create dishes that weren't possible with control of temperatures and cooking time.  Consistency in cooking is as important as it is in the software build process.



(0)

PermaLink Book Review: Learning AngularJS for .Net Developers11/05/2014 10:11 PM
Learning AngularJS for .Net Developers, written by Alex Pop and published by PACKT, provides a good introduction to single page applications with the AngularJS framework using Visual Studio 2013 as your development environment.  There is a lot of information available online for AngularJS, so the topics I'd like to see covered include in such a book include: how AngularJS is used on the client side, what support is provided by Visual Studio, how to write a .Net backend to support AngularJS, how authentication/security works in a client side application, how localization works, how the site is tested, and how the site can handle desktop web and mobile clients (aka Cordova/PhoneGap).  Most of these topics are covered sufficiently in this book except the last topic of using PhoneGap.


(0)

PermaLink Android's Horrid 64K DEX Method Limit08/17/2014
One of the worst design decisions in the Android Dalvik virtual machine is the 64K method limit (this limit includes all methods in your application and all libraries you link in; note that this is not the same as Facebook's 64K Dalvik Runtime issue.  The cryptic compile time error you'll get during a build of your project is:
  java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536

This problem will manifest easily if you hook in a few libraries that have a lot of methods, including notably the Google Play Services Library  which can suck up 1/3 of this limit.  Other libraries that are huge include the Amazon Web Services library and Guava and Protobufs (which you can substitute with Square's Wire to reduce the method count).  You can analyze the method count using dex-method-counts.

Note: Google's official workaround is multidex support.



(2)

PermaLink Jenkins Automated Build/Unit Testing for iOS/Android08/10/2014 03:25 PM
When I started at Mustbin, I decided to spend a few days setting up Jenkins so that we could have a good Continuous Integration/Build server (a subset of the area known as "DevOps" nowadays).  As long as engineers put in a decent amount of lint/unit/integration tests, this is a great way to make sure no one checks out a build that is so broken that they have to spin their wheels until someone fixes the build from their bad check in of code.  It also provides a single consistent build source that you can release code from.  This initial setup has evolved a bit since then, so I'll cover what I've done to the iOS/Android builds on Jenkins and the thinking behind it; a future post will cover what I did to test the backend Django server using Vagrant on Jenkins.


(0)

PermaLink 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.


(0)

PermaLink Eclipse Importing Android Libraries as Gradle Projects12/12/2013 04:20 PM
If you ever have problems importing an Android library into Eclipse because Eclipse keeps importing the library as Gradle project (not useful for adding to your Android project), be sure the ".gradle" and ".settings" subdirectories are removed from the project before import.  The ".classpath" and ".project" files are also not needed.

(0)

PermaLink Surviving MS' "free" Window 8.1 Upgrade and LucidLogix Virtu Conflict11/23/2013
What should have been a simple Windows 8.1 upgrade ended up being a few hours of fiddling w/ Windows to get rid of a boot crash in the igdkmd64.sys (Intel Graphics Kernel Mode Driver).  Uninstalling the Intel HD video driver in Device Manager by booting into Safe Mode got rid of this crash but Windows then booted up into a blank screen that you couldn't do anything with.

But to get into Safe Mode, you have to boot off a Windows 8 install disk, or to get the old F8 key on boot functionality back, you have to boot into a Windows 8 install disk and execute:
  bcdedit /set {default} bootmenupolicy legacy
But in Safe Mode, you can no longer uninstall programs unless you install SafeMSI.

It's best that you do these two steps before you install the Windows 8.1 update.  It's also a good idea to grab the latest Windows 8.1 drivers for your motherboard so you can install them after you install Windows 8.1.  Uninstall LucidLogix Virtu and the Intel HD drivers before you do the update and you should be able to avoid this pain :-P

And after the update, the Windows and Program Files directories become uncompressed.  If you still want to compress them to save space, boot off a rescue CD/USB boot setup and recompress everything with "compact /s /c /a /i *"

If you're using VirtualBox with a bridged adapter, you'll also have to uninstall/reinstall it or it won't be able to find your system's network adapter to bridge to.  Doing a repair on the installation does not work.


(0)

PermaLink Gradle Dynamic Dependencies Also Use Ivy Syntax10/05/2013
Most build.gradle dependencies I've seen specify them using the standard "+" Gradle syntax:
  compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.+'
But if you use the maven-plugin that can generate pom.xml files and upload your project to a Maven repository, this breaks Maven builds because the "1.7.+" is not Maven syntax.  You can use this instead:
  compile "org.slf4j:slf4j-api:[1.7,1.8)"
This mathematical set range notation does effectively the same thing.  It includes all 1.7 versions but stops at 1.8.  If you wanted it to include any version above 1.7 (including 2.0, etc.), you'd specify:
  compile "org.slf4j:slf4j-api:[1.7,)"
There's a bit more info on the Maven/Ivy dynamic version syntax on Maestro's blog.


(0)

Start Pages
RSS News Feed RSS Comments Feed CoComment Integrated
The BlogRoll
Calendar
March 2015
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