Created
May 6, 2012 17:32
-
-
Save jbrechtel/2623426 to your computer and use it in GitHub Desktop.
Scala Android project with Proguard and ActionBarSherlock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.xml.{Node => XmlNode} | |
import scala.xml._ | |
import java.io.FileWriter | |
import sbt._ | |
import Keys._ | |
import AndroidKeys._ | |
object General { | |
val settings = Defaults.defaultSettings ++ Seq ( | |
name := "FooProject", | |
version := "0.1", | |
scalacOptions += "-deprecation", | |
scalaVersion := "2.9.1", | |
platformName in Android := "android-15" | |
) | |
val pgOptions = Seq("-keep class android.support.v4.app.** { *; }", | |
"-keep interface android.support.v4.app.** { *; }", | |
"-keep class com.actionbarsherlock.** { *; }", | |
"-keep interface com.actionbarsherlock.** { *; }", | |
"-keepattributes *Annotation*").mkString(" ") | |
lazy val fullAndroidSettings = | |
General.settings ++ | |
AndroidProject.androidSettings ++ | |
TypedResources.settings ++ | |
AndroidMarketPublish.settings ++ Seq ( | |
proguardOption in Android := pgOptions, | |
keyalias in Android := "FooProject", | |
keystorePath in Android := file("../key/key.keystore"), | |
libraryDependencies ++= Seq("org.specs2" %% "specs2" % "1.8.2" % "test", | |
"com.actionbarsherlock" % "library" % "4.0.2" artifacts(Artifact("library", "apklib", "apklib"))) | |
) | |
} | |
object AndroidBuild extends Build with AndroidScalaLibs { | |
def buildWithoutProguard = Command.command("build-without-proguard") { state => | |
val extracted = Project.extract(state) | |
import extracted._ | |
val transformed = session.mergeSettings :+ (useProguard in Android := false) | |
val newStructure = Load.reapply(transformed, structure) | |
val newState = Project.setProject(session, newStructure, state) | |
Project.evaluateTask(buildAndRun, newState) | |
state | |
} | |
def addScalaLibToManifestTask = (manifestPath in Android) map { manPath => | |
addScalaLibToManifest(manPath.head) | |
} | |
def removeScalaLibFromManifestTask = (manifestPath in Android) map { manPath => | |
removeScalaLibFromManifest(manPath.head) | |
} | |
val buildAndRun = TaskKey[Unit]("build-and-run", "Builds and runs the app on a device") | |
val removeScalaLib = TaskKey[Unit]("remove-scala-uses", "Removes Scala uses-library from AndroidManifest.xml") | |
val addScalaLib = TaskKey[Unit]("add-scala-uses", "Adds Scala uses-library to AndroidManifest.xml") | |
lazy val main = Project ( | |
"main", | |
file("."), | |
settings = General.fullAndroidSettings ++ Seq( | |
useProguard in Android := true | |
) | |
) | |
lazy val dev = Project ( | |
"dev", | |
file("."), | |
settings = General.fullAndroidSettings ++ Seq( | |
name := "FooProject-dev", | |
removeScalaLib <<= removeScalaLibFromManifestTask, | |
addScalaLib <<= addScalaLibToManifestTask, | |
buildAndRun <<= removeScalaLibFromManifestTask, | |
buildAndRun <<= buildAndRun dependsOn (startDevice in Android), | |
buildAndRun <<= buildAndRun dependsOn (packageDebug in Android), | |
buildAndRun <<= buildAndRun dependsOn addScalaLib, | |
useProguard in Android := false | |
) | |
) | |
} | |
trait AndroidScalaLibs { | |
def pp = new PrettyPrinter(150, 5) | |
def addScalaLibToManifest(manifest: File) { | |
val xml = XML.load(manifest.absolutePath) | |
val appNode = (xml \ "application").head | |
val appNodeWithScala = addChildren(appNode, scalaNodes) | |
val newRootChildren = xml.child.filterNot(appNode.equals) ++ appNodeWithScala | |
val newXml = Elem(xml.prefix, xml.label, xml.attributes, xml.scope, newRootChildren:_*) | |
writeToFile(manifest.absolutePath, pp.format(newXml)) | |
} | |
def removeScalaLibFromManifest(manifest: File) { | |
val xml = XML.load(manifest.absolutePath) | |
val appNode = (xml \ "application").head | |
val newAppChildren = appNode.child.filterNot(scalaNodes.contains) | |
val appNodeWithoutScala = Elem(appNode.prefix, appNode.label, appNode.attributes, appNode.scope, newAppChildren:_*) | |
val newRootChildren = xml.child.filterNot(appNode.equals) ++ appNodeWithoutScala | |
val newXml = Elem(xml.prefix, xml.label, xml.attributes, xml.scope, newRootChildren:_*) | |
writeToFile(manifest.absolutePath, pp.format(newXml)) | |
} | |
def addChildren(n: XmlNode, newChildren: Seq[XmlNode]) = n match { | |
case Elem(prefix, label, attribs, scope, child @ _*) => | |
Elem(prefix, label, attribs, scope, child ++ newChildren : _*) | |
case _ => sys.error("Can only add children to elements!") | |
} | |
lazy val scalaNodes = { | |
Seq(<uses-library android:name="scala_actors-2.9.1"/>, | |
<uses-library android:name="scala_collection-2.9.1"/>, | |
<uses-library android:name="scala_immutable-2.9.1"/>, | |
<uses-library android:name="scala_library-2.9.1"/>, | |
<uses-library android:name="scala_mutable-2.9.1"/>) | |
} | |
def writeToFile(path: String, data: String) { | |
val f = new FileWriter(path) | |
f.write(data) | |
f.close() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment