From 69ea26e23134981f25b40c11d113645612956578 Mon Sep 17 00:00:00 2001 From: Kai Rasi Date: Thu, 22 Nov 2012 18:26:32 +0200 Subject: [PATCH 1/2] Replace emulator boolean arg with task target --- src/main/scala/AndroidHelpers.scala | 24 ++++++++++++++++++------ src/main/scala/AndroidInstall.scala | 16 ++++++++-------- src/main/scala/AndroidLaunch.scala | 8 ++++---- src/main/scala/AndroidTest.scala | 16 ++++++++-------- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/main/scala/AndroidHelpers.scala b/src/main/scala/AndroidHelpers.scala index 2e85f5e..81e4fed 100644 --- a/src/main/scala/AndroidHelpers.scala +++ b/src/main/scala/AndroidHelpers.scala @@ -24,8 +24,8 @@ object AndroidHelpers { def usesSdk(mpath: File, schema: String, key: String) = (manifest(mpath) \ "uses-sdk").head.attribute(schema, key).map(_.text.toInt) - def adbTask(dPath: String, emulator: Boolean, s: TaskStreams, action: String*) { - val (exit, out) = adbTaskWithOutput(dPath, emulator, s, action:_*) + def adbTask(dPath: String, taskTarget: AdbTaskTarget, s: TaskStreams, action: String*) { + val (exit, out) = adbTaskWithOutput(dPath, taskTarget, s, action:_*) if (exit != 0 || // adb doesn't bother returning a non-zero exit code on failure out.toString.contains("Failure")) { @@ -34,8 +34,8 @@ object AndroidHelpers { } else s.log.info(out.toString) } - def adbTaskWithOutput(dPath: String, emulator: Boolean, s: TaskStreams, action: String*) = { - val adb = Seq(dPath, if (emulator) "-e" else "-d") ++ action + def adbTaskWithOutput(dPath: String, taskTarget: AdbTaskTarget, s: TaskStreams, action: String*) = { + val adb = Seq(dPath, taskTarget.adbArgument) ++ action s.log.debug(adb.mkString(" ")) val out = new StringBuffer val exit = adb.run(new ProcessIO(input => (), @@ -46,11 +46,11 @@ object AndroidHelpers { (exit, out.toString) } - def startTask(emulator: Boolean) = + def startTask(taskTarget: AdbTaskTarget) = (dbPath, manifestSchema, manifestPackage, manifestPath, streams) map { (dp, schema, mPackage, amPath, s) => adbTask(dp.absolutePath, - emulator, s, + taskTarget, s, "shell", "am", "start", "-a", "android.intent.action.MAIN", "-n", mPackage+"/"+ launcherActivity(schema, amPath.head, mPackage)) @@ -74,3 +74,15 @@ object AndroidHelpers { def manifest(mpath: File) = xml.XML.loadFile(mpath) } + +abstract class AdbTaskTarget { + def adbArgument: String +} + +case object DeviceTaskTarget extends AdbTaskTarget { + def adbArgument = "-d" +} + +case object EmulatorTaskTarget extends AdbTaskTarget { + def adbArgument = "-e" +} \ No newline at end of file diff --git a/src/main/scala/AndroidInstall.scala b/src/main/scala/AndroidInstall.scala index b923667..1a5a49d 100644 --- a/src/main/scala/AndroidInstall.scala +++ b/src/main/scala/AndroidInstall.scala @@ -10,12 +10,12 @@ import java.io.{File => JFile} object AndroidInstall { - private def installTask(emulator: Boolean) = (dbPath, packageApkPath, streams) map { (dp, p, s) => - adbTask(dp.absolutePath, emulator, s, "install", "-r ", p.absolutePath) + private def installTask(taskTarget: AdbTaskTarget) = (dbPath, packageApkPath, streams) map { (dp, p, s) => + adbTask(dp.absolutePath, taskTarget, s, "install", "-r ", p.absolutePath) } - private def uninstallTask(emulator: Boolean) = (dbPath, manifestPackage, streams) map { (dp, m, s) => - adbTask(dp.absolutePath, emulator, s, "uninstall", m) + private def uninstallTask(taskTarget: AdbTaskTarget) = (dbPath, manifestPackage, streams) map { (dp, m, s) => + adbTask(dp.absolutePath, taskTarget, s, "uninstall", m) } private def aaptPackageTask: Project.Initialize[Task[File]] = @@ -170,13 +170,13 @@ object AndroidInstall { } lazy val installerTasks = Seq ( - installEmulator <<= installTask(emulator = true) dependsOn packageDebug, - installDevice <<= installTask(emulator = false) dependsOn packageDebug + installEmulator <<= installTask(taskTarget = EmulatorTaskTarget) dependsOn packageDebug, + installDevice <<= installTask(taskTarget = DeviceTaskTarget) dependsOn packageDebug ) lazy val settings: Seq[Setting[_]] = inConfig(Android) (installerTasks ++ Seq ( - uninstallEmulator <<= uninstallTask(emulator = true), - uninstallDevice <<= uninstallTask(emulator = false), + uninstallEmulator <<= uninstallTask(taskTarget = EmulatorTaskTarget), + uninstallDevice <<= uninstallTask(taskTarget = DeviceTaskTarget), makeAssetPath <<= directory(mainAssetsPath), diff --git a/src/main/scala/AndroidLaunch.scala b/src/main/scala/AndroidLaunch.scala index 0f23c3b..1e55edf 100644 --- a/src/main/scala/AndroidLaunch.scala +++ b/src/main/scala/AndroidLaunch.scala @@ -6,11 +6,11 @@ import AndroidHelpers._ object AndroidLaunch { - private def startTask(emulator: Boolean) = + private def startTask(taskTarget: AdbTaskTarget) = (dbPath, manifestSchema, manifestPackage, manifestPath, streams) map { (dp, schema, mPackage, amPath, s) => adbTask(dp.absolutePath, - emulator, s, + taskTarget, s, "shell", "am", "start", "-a", "android.intent.action.MAIN", "-n", mPackage+"/"+launcherActivity(schema, amPath.head, mPackage)) } @@ -33,8 +33,8 @@ object AndroidLaunch { lazy val settings: Seq[Setting[_]] = AndroidInstall.settings ++ inConfig(Android) (Seq ( - startDevice <<= startTask(false), - startEmulator <<= startTask(true), + startDevice <<= startTask(DeviceTaskTarget), + startEmulator <<= startTask(EmulatorTaskTarget), startDevice <<= startDevice dependsOn installDevice, startEmulator <<= startEmulator dependsOn installEmulator diff --git a/src/main/scala/AndroidTest.scala b/src/main/scala/AndroidTest.scala index e660f28..81ecf1d 100644 --- a/src/main/scala/AndroidTest.scala +++ b/src/main/scala/AndroidTest.scala @@ -20,20 +20,20 @@ object AndroidTest { } - def instrumentationTestAction(emulator: Boolean) = (dbPath, manifestPackage, testRunner, streams) map { + def instrumentationTestAction(taskTarget: AdbTaskTarget) = (dbPath, manifestPackage, testRunner, streams) map { (dbPath, manifestPackage, testRunner, s) => val action = Seq("shell", "am", "instrument", "-r", "-w", manifestPackage+"/"+testRunner) - val (exit, out) = adbTaskWithOutput(dbPath.absolutePath, emulator, s, action:_*) + val (exit, out) = adbTaskWithOutput(dbPath.absolutePath, taskTarget, s, action:_*) if (exit == 0) parseTests(out, manifestPackage, s.log) else sys.error("am instrument returned error %d\n\n%s".format(exit, out)) () } - def runSingleTest(emulator: Boolean) = (test: TaskKey[String]) => (test, dbPath, manifestPackage, testRunner, streams) map { + def runSingleTest(taskTarget: AdbTaskTarget) = (test: TaskKey[String]) => (test, dbPath, manifestPackage, testRunner, streams) map { (test, dbPath, manifestPackage, testRunner, s) => val action = Seq("shell", "am", "instrument", "-r", "-w", "-e", "class", test, manifestPackage+"/"+ testRunner) - val (exit, out) = adbTaskWithOutput(dbPath.absolutePath, emulator, s, action:_*) + val (exit, out) = adbTaskWithOutput(dbPath.absolutePath, taskTarget, s, action:_*) if (exit == 0) parseTests(out, manifestPackage, s.log) else sys.error("am instrument returned error %d\n\n%s".format(exit, out)) () @@ -70,13 +70,13 @@ object AndroidTest { AndroidInstall.settings ++ inConfig(Android) (Seq ( testRunner <<= detectTestRunnerTask, - testEmulator <<= instrumentationTestAction(true), - testDevice <<= instrumentationTestAction(false), + testEmulator <<= instrumentationTestAction(EmulatorTaskTarget), + testDevice <<= instrumentationTestAction(DeviceTaskTarget), testOnlyEmulator <<= InputTask(loadForParser(definedTestNames in Test)( (s, i) => testParser(s, i getOrElse Nil))) { test => - runSingleTest(true)(test) + runSingleTest(EmulatorTaskTarget)(test) }, testOnlyDevice <<= InputTask(loadForParser(definedTestNames in Test)( (s, i) => testParser(s, i getOrElse Nil))) { test => - runSingleTest(false)(test) + runSingleTest(DeviceTaskTarget)(test) } )) ++ Seq ( testEmulator <<= (testEmulator in Android), From 8c918fa2c08f1dbcb18e3d881c33fdfb090a811e Mon Sep 17 00:00:00 2001 From: Kai Rasi Date: Thu, 22 Nov 2012 18:28:36 +0200 Subject: [PATCH 2/2] Add install-all and uninstall-all tasks that install/uninstall APK to/from all devices and emulators that are listed by 'adb devices' --- src/main/scala/AndroidHelpers.scala | 12 ++++++++---- src/main/scala/AndroidInstall.scala | 30 ++++++++++++++++++++++++++++- src/main/scala/AndroidKeys.scala | 3 +++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/main/scala/AndroidHelpers.scala b/src/main/scala/AndroidHelpers.scala index 81e4fed..873d76b 100644 --- a/src/main/scala/AndroidHelpers.scala +++ b/src/main/scala/AndroidHelpers.scala @@ -35,7 +35,7 @@ object AndroidHelpers { } def adbTaskWithOutput(dPath: String, taskTarget: AdbTaskTarget, s: TaskStreams, action: String*) = { - val adb = Seq(dPath, taskTarget.adbArgument) ++ action + val adb = Seq(dPath) ++ taskTarget.adbArgument ++ action s.log.debug(adb.mkString(" ")) val out = new StringBuffer val exit = adb.run(new ProcessIO(input => (), @@ -76,13 +76,17 @@ object AndroidHelpers { } abstract class AdbTaskTarget { - def adbArgument: String + def adbArgument: Seq[String] } case object DeviceTaskTarget extends AdbTaskTarget { - def adbArgument = "-d" + def adbArgument = Seq("-d") } case object EmulatorTaskTarget extends AdbTaskTarget { - def adbArgument = "-e" + def adbArgument = Seq("-e") +} + +case class SerialTaskTarget(serial: String) extends AdbTaskTarget { + def adbArgument = Seq("-s", serial) } \ No newline at end of file diff --git a/src/main/scala/AndroidInstall.scala b/src/main/scala/AndroidInstall.scala index 1a5a49d..595a173 100644 --- a/src/main/scala/AndroidInstall.scala +++ b/src/main/scala/AndroidInstall.scala @@ -7,6 +7,7 @@ import AndroidKeys._ import AndroidHelpers._ import java.io.{File => JFile} +import util.matching.Regex object AndroidInstall { @@ -18,6 +19,31 @@ object AndroidInstall { adbTask(dp.absolutePath, taskTarget, s, "uninstall", m) } + private def installAllTask = (dbPath, packageApkPath, streams) map { (dp, p, s) => + withEachDeviceOrEmulator((serial: String) => { + s.log.info("Installing to " + serial) + adbTask(dp.absolutePath, SerialTaskTarget(serial), s, "install", "-r ", p.absolutePath) + }) + } + + private def unInstallAllTask = (dbPath, manifestPackage, streams) map { (dp, m, s) => + withEachDeviceOrEmulator((serial: String) => { + s.log.info("Uninstalling from " + serial) + adbTask(dp.absolutePath, SerialTaskTarget(serial), s, "uninstall", m) + }) + } + + private lazy val serialInAdbList: Regex = "([^\\s]+)".r + + private def withEachDeviceOrEmulator(doWithSerial: (String) => Unit) { + val adbDeviceList = "adb devices".lines_! + val allSerials = adbDeviceList.slice(1, adbDeviceList.size).map(serialInAdbList.findFirstIn(_)) + allSerials.foreach(_ match { + case Some(serial) => doWithSerial(serial) + case _ => + }) + } + private def aaptPackageTask: Project.Initialize[Task[File]] = (aaptPath, manifestPath, mainResPath, mainAssetsPath, jarPath, resourcesApkPath, extractApkLibDependencies, streams) map { (apPath, manPath, rPath, assetPath, jPath, resApkPath, apklibs, s) => @@ -171,12 +197,14 @@ object AndroidInstall { lazy val installerTasks = Seq ( installEmulator <<= installTask(taskTarget = EmulatorTaskTarget) dependsOn packageDebug, - installDevice <<= installTask(taskTarget = DeviceTaskTarget) dependsOn packageDebug + installDevice <<= installTask(taskTarget = DeviceTaskTarget) dependsOn packageDebug, + installAll <<= installAllTask dependsOn packageDebug ) lazy val settings: Seq[Setting[_]] = inConfig(Android) (installerTasks ++ Seq ( uninstallEmulator <<= uninstallTask(taskTarget = EmulatorTaskTarget), uninstallDevice <<= uninstallTask(taskTarget = DeviceTaskTarget), + uninstallAll <<= unInstallAllTask, makeAssetPath <<= directory(mainAssetsPath), diff --git a/src/main/scala/AndroidKeys.scala b/src/main/scala/AndroidKeys.scala index f8de3b5..63b7d46 100644 --- a/src/main/scala/AndroidKeys.scala +++ b/src/main/scala/AndroidKeys.scala @@ -119,6 +119,9 @@ object AndroidKeys { val installDevice = TaskKey[Unit]("install-device") val uninstallDevice = TaskKey[Unit]("uninstall-device") + val installAll = TaskKey[Unit]("install-all", "Install debug package to all devices and emulators that are listed by 'adb devices'.") + val uninstallAll = TaskKey[Unit]("uninstall-all", "Uninstall APK from all devices and emulators that are listed by 'adb devices'.") + val aaptPackage = TaskKey[File]("aapt-package", "Package resources and assets.") val packageDebug = TaskKey[File]("package-debug",