CI improvements (#695)

pull/697/head
Mattia Iavarone 5 years ago committed by GitHub
parent bb3b23e69a
commit 859904ec6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      .github/workflows/build.yml
  2. 6
      build.gradle
  3. 7
      cameraview/build.gradle
  4. 17
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/DoNotRunOnTravis.java
  5. 4
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera1IntegrationTest.java
  6. 5
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera2IntegrationTest.java
  7. 7
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/PinchGestureFinderTest.java
  8. 7
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/ScrollGestureFinderTest.java
  9. 6
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/TapGestureFinderTest.java
  10. 5
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/internal/utils/CamcorderProfilesTest.java
  11. 18
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/internal/utils/ImageHelperTest.java
  12. 103
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/markers/MarkerLayoutTest.java
  13. 18
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/runner/SdkExclude.java
  14. 46
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/runner/SdkExcludeFilter.java
  15. 2
      gradle/wrapper/gradle-wrapper.properties

@ -38,7 +38,9 @@ jobs:
runs-on: macOS-latest runs-on: macOS-latest
strategy: strategy:
matrix: matrix:
EMULATOR_API: [22] # TODO 29 fails due to Mockito issues, probably reproducible locally.
# 22, 23, 24, 25, 26, 27, 28 work - some of them, with SdkExclude restrictions.
EMULATOR_API: [22, 23, 24, 25, 26, 27, 28]
EMULATOR_ARCH: [x86_64] EMULATOR_ARCH: [x86_64]
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
@ -46,12 +48,12 @@ jobs:
with: with:
java-version: 1.8 java-version: 1.8
- name: Execute emulator tests - name: Execute emulator tests
uses: reactivecircus/android-emulator-runner@v1 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: ${{ matrix.EMULATOR_API }} api-level: ${{ matrix.EMULATOR_API }}
arch: ${{ matrix.EMULATOR_ARCH }} arch: ${{ matrix.EMULATOR_ARCH }}
disable-animations: true disable-animations: true
headless: true emulator-options: -no-snapshot -no-window -no-boot-anim -camera-back emulated -camera-front emulated -memory 2048
script: ./gradlew cameraview:connectedCheck script: ./gradlew cameraview:connectedCheck
- name: Upload emulator tests artifact - name: Upload emulator tests artifact
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1

@ -5,7 +5,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.4.2' classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
} }
@ -19,9 +19,9 @@ allprojects {
} }
ext { ext {
compileSdkVersion = 28 compileSdkVersion = 29
minSdkVersion = 15 minSdkVersion = 15
targetSdkVersion = 28 targetSdkVersion = 29
} }
task clean(type: Delete) { task clean(type: Delete) {

@ -8,8 +8,6 @@ group = 'com.otaliastudios'
//region android dependencies //region android dependencies
def isCI = System.getenv("TRAVIS")
android { android {
compileSdkVersion rootProject.ext.compileSdkVersion compileSdkVersion rootProject.ext.compileSdkVersion
@ -19,9 +17,7 @@ android {
versionCode 1 versionCode 1
versionName project.version versionName project.version
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
if (isCI) { testInstrumentationRunnerArgument "filter", "com.otaliastudios.cameraview.runner.SdkExcludeFilter"
testInstrumentationRunnerArgument "notAnnotation", "com.otaliastudios.cameraview.DoNotRunOnTravis"
}
} }
buildTypes { buildTypes {
@ -109,6 +105,7 @@ install {
def bintrayUser def bintrayUser
def bintrayKey def bintrayKey
def isCI = System.getenv("TRAVIS")
if (isCI) { if (isCI) {
bintrayUser = System.getenv("BINTRAY_USER") bintrayUser = System.getenv("BINTRAY_USER")
bintrayKey = System.getenv("BINTRAY_KEY") bintrayKey = System.getenv("BINTRAY_KEY")

@ -1,17 +0,0 @@
package com.otaliastudios.cameraview;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Thanks to a testInstrumentationRunnerArgument in our build file, we will not
* execute these tests on Travis CI.
* The {@link RetentionPolicy#RUNTIME} is needed!
*
* https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner
*
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface DoNotRunOnTravis {
String because() default "";
}

@ -1,6 +1,5 @@
package com.otaliastudios.cameraview.engine; package com.otaliastudios.cameraview.engine;
import com.otaliastudios.cameraview.DoNotRunOnTravis;
import com.otaliastudios.cameraview.controls.Engine; import com.otaliastudios.cameraview.controls.Engine;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -8,6 +7,7 @@ import org.junit.runner.RunWith;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest; import androidx.test.filters.LargeTest;
import androidx.test.filters.RequiresDevice;
/** /**
* These tests work great on real devices, and are the only way to test actual CameraEngine * These tests work great on real devices, and are the only way to test actual CameraEngine
@ -17,7 +17,7 @@ import androidx.test.filters.LargeTest;
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@LargeTest @LargeTest
@DoNotRunOnTravis(because = "These do work but fail on CI emulators, due to bugs in the Camera1 emulated devices.") @RequiresDevice
public class Camera1IntegrationTest extends CameraIntegrationTest { public class Camera1IntegrationTest extends CameraIntegrationTest {
@NonNull @NonNull

@ -3,17 +3,16 @@ package com.otaliastudios.cameraview.engine;
import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.TotalCaptureResult;
import com.otaliastudios.cameraview.DoNotRunOnTravis;
import com.otaliastudios.cameraview.controls.Engine; import com.otaliastudios.cameraview.controls.Engine;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
import com.otaliastudios.cameraview.engine.action.BaseAction; import com.otaliastudios.cameraview.engine.action.BaseAction;
import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest; import androidx.test.filters.LargeTest;
import androidx.test.filters.RequiresDevice;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -25,7 +24,7 @@ import java.util.concurrent.CountDownLatch;
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@LargeTest @LargeTest
@DoNotRunOnTravis(because = "These do work but fail on CI emulators.") @RequiresDevice
public class Camera2IntegrationTest extends CameraIntegrationTest { public class Camera2IntegrationTest extends CameraIntegrationTest {
@NonNull @NonNull

@ -6,6 +6,8 @@ import androidx.test.espresso.ViewAction;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.otaliastudios.cameraview.runner.SdkExclude;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -13,6 +15,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/**
* On API 26 these tests fail during Espresso's inRoot() - the window never gains focus.
* This might be due to a system popup or something similar.
*/
@SdkExclude(minSdkVersion = 26, maxSdkVersion = 26)
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class PinchGestureFinderTest extends GestureFinderTest<PinchGestureFinder> { public class PinchGestureFinderTest extends GestureFinderTest<PinchGestureFinder> {

@ -6,6 +6,8 @@ import androidx.test.espresso.ViewAction;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.otaliastudios.cameraview.runner.SdkExclude;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -17,6 +19,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/**
* On API 26 these tests fail during Espresso's inRoot() - the window never gains focus.
* This might be due to a system popup or something similar.
*/
@SdkExclude(minSdkVersion = 26, maxSdkVersion = 26)
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class ScrollGestureFinderTest extends GestureFinderTest<ScrollGestureFinder> { public class ScrollGestureFinderTest extends GestureFinderTest<ScrollGestureFinder> {

@ -11,6 +11,7 @@ import androidx.test.filters.SmallTest;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.otaliastudios.cameraview.runner.SdkExclude;
import com.otaliastudios.cameraview.size.Size; import com.otaliastudios.cameraview.size.Size;
import org.junit.Test; import org.junit.Test;
@ -19,6 +20,11 @@ import org.junit.runner.RunWith;
import static androidx.test.espresso.action.ViewActions.*; import static androidx.test.espresso.action.ViewActions.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/**
* On API 26 these tests fail during Espresso's inRoot() - the window never gains focus.
* This might be due to a system popup or something similar.
*/
@SdkExclude(minSdkVersion = 26, maxSdkVersion = 26)
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class TapGestureFinderTest extends GestureFinderTest<TapGestureFinder> { public class TapGestureFinderTest extends GestureFinderTest<TapGestureFinder> {

@ -8,6 +8,7 @@ import androidx.test.filters.SmallTest;
import com.otaliastudios.cameraview.BaseTest; import com.otaliastudios.cameraview.BaseTest;
import com.otaliastudios.cameraview.CameraUtils; import com.otaliastudios.cameraview.CameraUtils;
import com.otaliastudios.cameraview.runner.SdkExclude;
import com.otaliastudios.cameraview.size.Size; import com.otaliastudios.cameraview.size.Size;
import org.junit.Test; import org.junit.Test;
@ -34,6 +35,10 @@ public class CamcorderProfilesTest extends BaseTest {
assertEquals(lowest.videoFrameHeight, invalid.videoFrameHeight); assertEquals(lowest.videoFrameHeight, invalid.videoFrameHeight);
} }
/**
* For some reason this fails on emulator 26.
*/
@SdkExclude(minSdkVersion = 26, maxSdkVersion = 26)
@Test @Test
public void testGet() { public void testGet() {
String cameraId = getCameraId(); String cameraId = getCameraId();

@ -12,33 +12,31 @@ import android.graphics.Rect;
import android.graphics.YuvImage; import android.graphics.YuvImage;
import android.media.Image; import android.media.Image;
import android.media.ImageReader; import android.media.ImageReader;
import android.opengl.GLES20;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.otaliastudios.cameraview.BaseTest; import com.otaliastudios.cameraview.BaseTest;
import com.otaliastudios.cameraview.internal.egl.EglCore; import com.otaliastudios.cameraview.runner.SdkExclude;
import com.otaliastudios.cameraview.internal.egl.EglViewport;
import com.otaliastudios.cameraview.internal.egl.EglWindowSurface;
import com.otaliastudios.cameraview.size.AspectRatio;
import com.otaliastudios.cameraview.size.Size;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Starting from API 29, surface.lockCanvas() sets the surface format to RGBA_8888:
* https://github.com/aosp-mirror/platform_frameworks_base/blob/android10-release/core/jni/android_view_Surface.cpp#L215-L217 .
* For this reason, acquireLatestImage crashes because we requested a different format.
*/
@SdkExclude(minSdkVersion = 29)
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class ImageHelperTest extends BaseTest { public class ImageHelperTest extends BaseTest {

@ -9,6 +9,7 @@ import android.view.ViewGroup;
import com.otaliastudios.cameraview.BaseTest; import com.otaliastudios.cameraview.BaseTest;
import com.otaliastudios.cameraview.TestActivity; import com.otaliastudios.cameraview.TestActivity;
import com.otaliastudios.cameraview.runner.SdkExclude;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -17,19 +18,19 @@ import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.annotation.UiThreadTest;
import androidx.test.rule.ActivityTestRule; import androidx.test.rule.ActivityTestRule;
import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Not clear why, but for some reason on API 28 the UiThreadTests here crash for an internal NPE
* in FrameLayout.onMeasure.
*/
@SdkExclude(minSdkVersion = 28, maxSdkVersion = 28)
@TargetApi(17) @TargetApi(17)
public class MarkerLayoutTest extends BaseTest { public class MarkerLayoutTest extends BaseTest {
@ -54,58 +55,74 @@ public class MarkerLayoutTest extends BaseTest {
} }
@Test @Test
@UiThreadTest
public void testOnMarker_callsOnAttach() { public void testOnMarker_callsOnAttach() {
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); uiSync(new Runnable() {
Mockito.verify(autoFocusMarker, times(1)).onAttach( @Override
Mockito.any(Context.class), public void run() {
Mockito.eq(markerLayout)); markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker);
Mockito.verify(autoFocusMarker, times(1)).onAttach(
Mockito.any(Context.class),
Mockito.eq(markerLayout));
}
});
} }
@Test @Test
@UiThreadTest
public void testOnMarker_addsView() { public void testOnMarker_addsView() {
Assert.assertEquals(markerLayout.getChildCount(), 0); uiSync(new Runnable() {
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); @Override
Assert.assertEquals(markerLayout.getChildCount(), 1); public void run() {
Assert.assertEquals(markerLayout.getChildCount(), 0);
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker);
Assert.assertEquals(markerLayout.getChildCount(), 1);
}
});
} }
@Test @Test
@UiThreadTest
public void testOnMarker_removesView() { public void testOnMarker_removesView() {
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); uiSync(new Runnable() {
Assert.assertEquals(markerLayout.getChildCount(), 1); @Override
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); public void run() {
Assert.assertEquals(markerLayout.getChildCount(), 1); markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker);
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, null); Assert.assertEquals(markerLayout.getChildCount(), 1);
Assert.assertEquals(markerLayout.getChildCount(), 0); markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker);
Assert.assertEquals(markerLayout.getChildCount(), 1);
Mockito.verify(autoFocusMarker, times(2)).onAttach( markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, null);
Mockito.any(Context.class), Assert.assertEquals(markerLayout.getChildCount(), 0);
Mockito.eq(markerLayout));
Mockito.verify(autoFocusMarker, times(2)).onAttach(
Mockito.any(Context.class),
Mockito.eq(markerLayout));
}
});
} }
@Test @Test
@UiThreadTest
public void testOnEvent() { public void testOnEvent() {
final View mockView = spy(new View(getContext())); uiSync(new Runnable() {
// These fail, however it's not really needed.
// when(mockView.getWidth()).thenReturn(50);
// when(mockView.getHeight()).thenReturn(50);
AutoFocusMarker mockMarker = new AutoFocusMarker() {
public void onAutoFocusStart(@NonNull AutoFocusTrigger trigger, @NonNull PointF point) { }
public void onAutoFocusEnd(@NonNull AutoFocusTrigger trigger, boolean successful, @NonNull PointF point) { }
@Override @Override
public View onAttach(@NonNull Context context, @NonNull ViewGroup container) { public void run() {
return mockView; final View mockView = spy(new View(getContext()));
// These fail, however it's not really needed.
// when(mockView.getWidth()).thenReturn(50);
// when(mockView.getHeight()).thenReturn(50);
AutoFocusMarker mockMarker = new AutoFocusMarker() {
public void onAutoFocusStart(@NonNull AutoFocusTrigger trigger, @NonNull PointF point) { }
public void onAutoFocusEnd(@NonNull AutoFocusTrigger trigger, boolean successful, @NonNull PointF point) { }
@Override
public View onAttach(@NonNull Context context, @NonNull ViewGroup container) {
return mockView;
}
};
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, mockMarker);
reset(mockView);
markerLayout.onEvent(MarkerLayout.TYPE_AUTOFOCUS, new PointF[]{new PointF(0, 0)});
verify(mockView, times(1)).clearAnimation();
verify(mockView, times(1)).setTranslationX(anyFloat());
verify(mockView, times(1)).setTranslationY(anyFloat());
} }
}; });
markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, mockMarker);
reset(mockView);
markerLayout.onEvent(MarkerLayout.TYPE_AUTOFOCUS, new PointF[]{new PointF(0, 0)});
verify(mockView, times(1)).clearAnimation();
verify(mockView, times(1)).setTranslationX(anyFloat());
verify(mockView, times(1)).setTranslationY(anyFloat());
} }
} }

@ -0,0 +1,18 @@
package com.otaliastudios.cameraview.runner;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Like {@link androidx.test.filters.SdkSuppress}, but negative.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface SdkExclude {
/** The minimum API level to drop (inclusive) */
int minSdkVersion() default 1;
/** The maximum API level to drop (inclusive) */
int maxSdkVersion() default Integer.MAX_VALUE;
}

@ -0,0 +1,46 @@
package com.otaliastudios.cameraview.runner;
import android.os.Build;
import androidx.annotation.Nullable;
import androidx.test.internal.runner.filters.ParentFilter;
import org.junit.runner.Description;
/**
* Filter for {@link SdkExclude}, based on
* {@link androidx.test.internal.runner.TestRequestBuilder}'s SdkSuppressFilter.
*/
public class SdkExcludeFilter extends ParentFilter {
protected boolean evaluateTest(Description description) {
final SdkExclude sdkSuppress = getAnnotationForTest(description);
if (sdkSuppress != null) {
if (Build.VERSION.SDK_INT >= sdkSuppress.minSdkVersion()
&& Build.VERSION.SDK_INT <= sdkSuppress.maxSdkVersion()) {
return false; // exclude the test
}
return true; // run the test
}
return true; // no annotation, run the test
}
@Nullable
private SdkExclude getAnnotationForTest(Description description) {
final SdkExclude s = description.getAnnotation(SdkExclude.class);
if (s != null) {
return s;
}
final Class<?> testClass = description.getTestClass();
if (testClass != null) {
return testClass.getAnnotation(SdkExclude.class);
}
return null;
}
@Override
public String describe() {
return "Skip tests annotated with SdkExclude";
}
}

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

Loading…
Cancel
Save