Skip to content
This repository has been archived by the owner on Feb 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #88 from novoda/refactoring/avoid_rereading_devices
Browse files Browse the repository at this point in the history
Move activity detection, add memoization
  • Loading branch information
stefanhoth committed Nov 5, 2015
2 parents 09a4b29 + 7a23efd commit 6734076
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.novoda.gradle.command

import groovy.transform.Memoized


public class AdbTask extends org.gradle.api.DefaultTask {

Expand All @@ -13,6 +15,7 @@ public class AdbTask extends org.gradle.api.DefaultTask {

def deviceId

@Memoized
def getDeviceId() {
if (deviceId instanceof Closure)
deviceId = deviceId.call()
Expand All @@ -31,55 +34,6 @@ public class AdbTask extends org.gradle.api.DefaultTask {
}
}

def getLaunchableActivity() {
def output = readApkProperty('launchable-activity')
if (output) {
def matcher = output.readLines()[0] =~ /name='(.*?)'/
if (matcher) {
matcher[0][1]
}
} else {
// Fall back to manually parsing aapt's pseudo-XML output to support activity aliases, see
// https://code.google.com/p/android/issues/detail?id=157150
logger.info 'no launchable-activity found, falling back to parsing the manifest'

output = [pluginEx.aapt, 'dump', 'xmltree', apkPath, 'AndroidManifest.xml'].execute().text

def it = output.readLines().iterator()
def nextLine = null

// Look for activity alias definitions.
while (it.hasNext()) {
def line = nextLine ?: it.next()
nextLine = null

def matcher = line =~ /(\s+)(E: activity-alias)(.*)/
if (matcher) {
def intentation = matcher[0][1] + ' '
def name = null, main = false, launcher = false, disabled = false

// Parse the indented block for the current activity alias.
while (it.hasNext() && (nextLine = it.next()).startsWith(intentation)) {
matcher = nextLine =~ /A: android:name.*="([^"]+)"/
if (matcher && !name) {
name = matcher[0][1]
}
main = main || nextLine.contains('android.intent.action.MAIN')
launcher = launcher || nextLine.contains('android.intent.category.LAUNCHER')

// Exclude disabled entries.
disabled = disabled || nextLine ==~ /^(\s+)A: android:enabled.*=.*0x0$/
}

if (name && main && launcher && !disabled) {
// Return the first enabled activity-alias launcher.
return name
}
}
}
}
}

protected handleCommandOutput(def text) {
logger.info text
}
Expand All @@ -95,22 +49,22 @@ public class AdbTask extends org.gradle.api.DefaultTask {
handleCommandOutput(command.execute().text)
}

private void printDeviceInfo() {
Device device = pluginEx.devices().find { device -> device.id == getDeviceId() }
private printDeviceInfo(device) {
println '=========================='
println device.toString()
println '=========================='
}

protected void assertDeviceConnected() {
def id = getDeviceId()
if (!pluginEx.deviceIds().contains(id))
throw new IllegalStateException("Device with ID $id not found")
printDeviceInfo()
Device device = pluginEx.devices().find { device -> device.id == id }
if (!device)
throw new IllegalStateException("No device with ID $id found.")
printDeviceInfo(device)
}

private String readApkProperty(String propertyKey) {
if (apkPath == null) {
protected final readApkProperty(String propertyKey) {
if (!apkPath) {
throw new IllegalStateException("No APK found for the '$name' task")
}
String output = [pluginEx.aapt, 'dump', 'badging', apkPath].execute().text.readLines().find {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package com.novoda.gradle.command

import groovy.transform.Memoized
import org.gradle.api.Project

public class AndroidCommandPluginExtension {
Expand Down Expand Up @@ -57,6 +59,7 @@ public class AndroidCommandPluginExtension {
}

// prefer system property over direct setting to enable commandline arguments
@Memoized
def getDeviceId() {
if (System.properties['deviceId'])
return System.properties['deviceId']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,55 @@ class Run extends AdbTask {
def line = ['shell', 'am', 'start', '-a', 'android.intent.action.MAIN', '-c', 'android.intent.category.LAUNCHER', "$packageName/$launchableActivity"]
assertDeviceAndRunCommand(line)
}

def getLaunchableActivity() {
def output = readApkProperty('launchable-activity')
if (output) {
def matcher = output.readLines()[0] =~ /name='(.*?)'/
if (matcher) {
matcher[0][1]
}
} else {
// Fall back to manually parsing aapt's pseudo-XML output to support activity aliases, see
// https://code.google.com/p/android/issues/detail?id=157150
logger.info 'no launchable-activity found, falling back to parsing the manifest'

output = [pluginEx.aapt, 'dump', 'xmltree', apkPath, 'AndroidManifest.xml'].execute().text

def it = output.readLines().iterator()
def nextLine = null

// Look for activity alias definitions.
while (it.hasNext()) {
def line = nextLine ?: it.next()
nextLine = null

def matcher = line =~ /(\s+)(E: activity-alias)(.*)/
if (matcher) {
def intentation = matcher[0][1] + ' '
def name = null, main = false, launcher = false, disabled = false

// Parse the indented block for the current activity alias.
while (it.hasNext() && (nextLine = it.next()).startsWith(intentation)) {
matcher = nextLine =~ /A: android:name.*="([^"]+)"/
if (matcher && !name) {
name = matcher[0][1]
}
main = main || nextLine.contains('android.intent.action.MAIN')
launcher = launcher || nextLine.contains('android.intent.category.LAUNCHER')

// Exclude disabled entries.
disabled = disabled || nextLine ==~ /^(\s+)A: android:enabled.*=.*0x0$/
}

if (name && main && launcher && !disabled) {
// Return the first enabled activity-alias launcher.
return name
}
}
}
}
}


}

0 comments on commit 6734076

Please sign in to comment.