Skip to content
This repository was archived by the owner on Apr 19, 2018. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ Version 1.5.0 *(In Development)*
--------------------------------

* New: Support for the 1.5.x Android plugin.
* New: SDK Tools will be updated if version is older than defined with sdkManager.minSdkToolsVersion
in build.gradle:
sdkManager {
minSdkToolsVersion '24.3.4'
}
* New: Download r24.2 Android SDK.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package com.jakewharton.sdkmanager;
class SdkManagerExtension {
String emulatorVersion
String emulatorArchitecture
String minSdkToolsVersion
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ interface AndroidCommand {

def result = ''
output.split('----------').each {
if (it.contains(filter)) {
if (it.contains("\"$filter\"")) {
result += it
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import static com.android.SdkConstants.FD_PLATFORMS
import static com.android.SdkConstants.FD_ADDONS
import static com.android.SdkConstants.FD_PLATFORM_TOOLS
import static com.android.SdkConstants.FD_SYSTEM_IMAGES
import static com.android.SdkConstants.FD_TOOLS

class PackageResolver {
static void resolve(Project project, File sdk) {
Expand Down Expand Up @@ -58,6 +59,7 @@ class PackageResolver {
}

def resolve() {
resolveSdkTools()
resolveBuildTools()
resolvePlatformTools()
resolveCompileVersion()
Expand All @@ -66,6 +68,56 @@ class PackageResolver {
resolveEmulator()
}

def resolveSdkTools() {
def minSdkToolsVersion = project.sdkManager.minSdkToolsVersion
if (minSdkToolsVersion == null) {
log.debug 'No minSdkToolsVersion defined'
return
}
log.debug "Found minSdkToolsVersion: $minSdkToolsVersion"

def sdkToolsDir = new File(sdk, FD_TOOLS)
def sdkToolsVersion = getPackageRevision(sdkToolsDir)
log.debug "Found sdkToolsVersion: $sdkToolsVersion"

def minSdkToolsRevision = VersionMatcher.parse(minSdkToolsVersion)
def sdkToolsRevision = VersionMatcher.parse(sdkToolsVersion)
def needsDownload = sdkToolsRevision < minSdkToolsRevision

if (!needsDownload) {
log.debug "SDK tools are up to date."
return
}

def sdkToolsPackage = "tools"
def currentSdkToolsInfo = androidCommand.list sdkToolsPackage
if (currentSdkToolsInfo == null || currentSdkToolsInfo.isEmpty()) {
throw new StopExecutionException('Could not get the current SDK tools revision.')
}

def matcher = Pattern.compile("revision\\ (.+)").matcher(currentSdkToolsInfo)
if (!matcher.find()) {
throw new StopExecutionException("Could not find the current SDK tools revision." +
" currentSdkToolsInfo: $currentSdkToolsInfo")
}

def currentSdkToolsVersion = matcher.group(1)
log.debug "currentSdkToolsVersion: $currentSdkToolsVersion"

def currentSdkToolsRevision = VersionMatcher.parse(currentSdkToolsVersion)
if (currentSdkToolsRevision < minSdkToolsRevision) {
throw new StopExecutionException("Currently available SDK tools version($currentSdkToolsVersion)" +
" is smaller than defined in minSdkToolsVersion: $minSdkToolsVersion")
}

log.lifecycle "SDK tools $sdkToolsVersion outdated. Downloading update..."

def code = androidCommand.update sdkToolsPackage
if (code != 0) {
throw new StopExecutionException("SDK tools download failed with code $code.")
}
}

def resolveBuildTools() {
def buildToolsRevision = project.android.buildToolsRevision
log.debug "Build tools version: $buildToolsRevision"
Expand Down Expand Up @@ -222,21 +274,7 @@ class PackageResolver {
needsDownload = true
log.lifecycle "Emulator $emulatorVersion $emulatorArchitecture missing. Downloading..."
} else {
def emulatorPropertiesFile = new File(emulatorDir, 'source.properties')
if (!emulatorPropertiesFile.canRead()) {
emulatorPropertiesFile = new File(alternativeEmulatorDir, 'source.properties')
if (!emulatorPropertiesFile.canRead()) {
throw new StopExecutionException('Could not read ' + emulatorPropertiesFile.absolutePath)
}
}

def emulatorProperties = new Properties()
emulatorProperties.load(new FileInputStream(emulatorPropertiesFile))
def emulatorRevision = emulatorProperties.getProperty('Pkg.Revision')
if (emulatorRevision == null) {
throw new StopExecutionException('Could not get the installed emulator revision for ' +
emulatorPackage)
}
def emulatorRevision = getPackageRevision(emulatorDir, alternativeEmulatorDir)

def currentEmulatorInfo = androidCommand.list emulatorPackage
if (currentEmulatorInfo == null || currentEmulatorInfo.isEmpty()) {
Expand Down Expand Up @@ -265,6 +303,24 @@ class PackageResolver {
}
}

def getPackageRevision(File[] packageDirs) {
def propertiesFileName = 'source.properties'
def propertiesFile = packageDirs.collect { new File(it, propertiesFileName) }.find { it.canRead() }
if (propertiesFile == null) {
throw new StopExecutionException("Could not read '$propertiesFileName' from: $packageDirs")
}

def properties = new Properties()
properties.load(new FileInputStream(propertiesFile))
def revision = properties.getProperty('Pkg.Revision')
if (revision == null) {
throw new StopExecutionException("Could not read the revision from: ${propertiesFile.absolutePath}")
}

log.debug "Found revision for package ${propertiesFile.absolutePath}: $revision"
return revision
}

def findDependenciesWithGroup(String group) {
def deps = []
for (Configuration configuration : project.configurations) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.jakewharton.sdkmanager.internal

import org.gradle.api.tasks.StopExecutionException

import java.util.regex.Pattern

class VersionMatcher implements Comparable<VersionMatcher> {
private final int major
private final int minor
private final int micro
private final int preview

private static final Pattern VERSION_PATTERN =
Pattern.compile("\\s*([0-9]+)(?:\\.([0-9]+)(?:\\.([0-9]+))?)?\\s*(?:rc([0-9]+))?\\s*")

public VersionMatcher(int major, int minor, int micro, int preview) {
this.major = major
this.minor = minor
this.micro = micro
this.preview = preview
}

public static VersionMatcher parse(String version) {
def m = VERSION_PATTERN.matcher(version)
if (m == null || !m.matches()) {
throw new StopExecutionException('Version string mismatched')
}

int major = Integer.parseInt(m.group(1))
String s = m.group(2)
int minor = s == null ? 0 : Integer.parseInt(s)
s = m.group(3)
int micro = s == null ? 0 : Integer.parseInt(s)
s = m.group(4)
// Something that isn't a release candidate is newer than something that is
// e.g. "18.0.0 rc1" < "18.0.0"
int preview = s == null ? Integer.MAX_VALUE : Integer.parseInt(s)

return new VersionMatcher(major, minor, micro, preview)
}

@Override
public int compareTo(VersionMatcher rhs) {
int delta = major - rhs.major
if (delta != 0) {
return delta
}

delta = minor - rhs.minor
if (delta != 0) {
return delta
}

delta = micro - rhs.micro;
if (delta != 0) {
return delta
}

delta = preview - rhs.preview;
return delta
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### Android Tool: Source of this archive.
#Thu Sep 24 18:29:52 EEST 2015
Archive.HostOs=macosx
Pkg.License=To get started with the Android SDK, you must agree to the following terms and conditions.\n
Pkg.LicenseRef=android-sdk-license
Pkg.Revision=22.6
Pkg.SourceUrl=https\://dl-ssl.google.com/android/repository/repository-10.xml
Platform.MinPlatformToolsRev=20
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.example.sdkmanager"
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### Android Tool: Source of this archive.
#Thu Sep 24 18:29:52 EEST 2015
Archive.HostOs=macosx
Pkg.License=To get started with the Android SDK, you must agree to the following terms and conditions.\n
Pkg.LicenseRef=android-sdk-license
Pkg.Revision=24.3.4
Pkg.SourceUrl=https\://dl-ssl.google.com/android/repository/repository-10.xml
Platform.MinPlatformToolsRev=20
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.example.sdkmanager"
/>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.jakewharton.sdkmanager.SdkManagerExtension
import com.jakewharton.sdkmanager.TemporaryFixture
import com.jakewharton.sdkmanager.util.RecordingAndroidCommand
import org.gradle.api.Project
import org.gradle.api.tasks.StopExecutionException
import org.gradle.testfixtures.ProjectBuilder
import org.junit.Before
import org.junit.Rule
Expand All @@ -13,6 +14,7 @@ import org.junit.Test
import static com.android.SdkConstants.FN_LOCAL_PROPERTIES
import static com.android.SdkConstants.SDK_DIR_PROPERTY
import static org.fest.assertions.api.Assertions.assertThat
import static org.fest.assertions.api.Assertions.failBecauseExceptionWasNotThrown

class PackageResolverTest {
@Rule public TemporaryFixture fixture = new TemporaryFixture();
Expand Down Expand Up @@ -339,4 +341,48 @@ class PackageResolverTest {
packageResolver.resolveEmulator()
assertThat(androidCommand).contains('update sys-img-armeabi-v7a-android-19')
}

@FixtureName("up-to-date-sdk-tools")
@Test public void upToDateSdkToolsRecognized() {
project.apply plugin: 'com.android.application'
project.extensions.create("sdkManager", SdkManagerExtension)
project.sdkManager {
minSdkToolsVersion '24.3.4'
}

packageResolver.resolveSdkTools()
assertThat(androidCommand).doesNotContain('update tools')
}

@FixtureName("outdated-sdk-tools")
@Test public void outdatedSdkToolsDownloaded() {
project.apply plugin: 'com.android.application'
project.extensions.create("sdkManager", SdkManagerExtension)
project.sdkManager {
minSdkToolsVersion '24.3.4'
}

packageResolver.resolveSdkTools()
assertThat(androidCommand).contains('update tools')
}

@FixtureName("up-to-date-sdk-tools")
@Test public void sdkToolsUnavailable() {
def tooBigMinSdkToolsVersion = '100500'

project.apply plugin: 'com.android.application'
project.extensions.create("sdkManager", SdkManagerExtension)
project.sdkManager {
minSdkToolsVersion tooBigMinSdkToolsVersion
}

try {
packageResolver.resolveSdkTools()
failBecauseExceptionWasNotThrown(StopExecutionException.class);
} catch (Exception e) {
assertThat(e)
.isInstanceOf(StopExecutionException.class)
.hasMessageEndingWith(tooBigMinSdkToolsVersion)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ final class RecordingAndroidCommand extends ArrayList<String> implements Android

@Override String list(String filter) {
add("list -a -e" as String)
return "id: 55 or \"sys-img-armeabi-v7a-android-19\"\n" +
" Type: SystemImage\n" +
" Desc: Android SDK Platform 4.4.2\n" +
" Revision 2\n" +
" Requires SDK Platform Android API 19\n"
return "id: 1 or \"tools\"\n" +
" Type: Tool\n" +
" Desc: Android SDK Tools, revision 24.3.4\n" +
"id: 55 or \"sys-img-armeabi-v7a-android-19\"\n" +
" Type: SystemImage\n" +
" Desc: Android SDK Platform 4.4.2\n" +
" Revision 2\n" +
" Requires SDK Platform Android API 19\n"
}
}