diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..bc53be3 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ '**' ] + +jobs: + build: + runs-on: ubuntu-latest + container: + image: mbgl/android-sdk:latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check code style + run: make checkstyle + + - name: Run Lint + run: ./gradlew lint + + - name: Run unit-test in Android libraries + run: make test + + - name: Upload reports + uses: actions/upload-artifact@v4 + with: + name: reports + path: app/build/reports + + - name: Upload test results + uses: actions/upload-artifact@v4 + with: + name: test-results + path: app/build/test-results \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d35f6f9..a7461e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog for the Mapbox Gestures for Android +## 0.9.2 - September 29, 2025 +* Fix concurrent modification exception for detectors + ## 0.9.1 - November 27, 2023 Minor release with internal fixes for publishing library diff --git a/build.gradle b/build.gradle index 568b306..0c5a5af 100644 --- a/build.gradle +++ b/build.gradle @@ -5,13 +5,6 @@ buildscript { mavenCentral() maven { url 'https://api.mapbox.com/downloads/v2/releases/maven' - authentication { - basic(BasicAuthentication) - } - credentials { - username = "mapbox" - password = System.getenv("SDK_REGISTRY_TOKEN") ?: project.property("SDK_REGISTRY_TOKEN") as String - } } } dependencies { @@ -28,13 +21,6 @@ allprojects { mavenCentral() maven { url 'https://api.mapbox.com/downloads/v2/releases/maven' - authentication { - basic(BasicAuthentication) - } - credentials { - username = "mapbox" - password = password = System.getenv("SDK_REGISTRY_TOKEN") ?: project.property("SDK_REGISTRY_TOKEN") as String - } } } } diff --git a/circle.yml b/circle.yml index faea1b7..3b47d03 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,6 @@ workflows: version: 2 default: jobs: - - build - release: filters: branches: @@ -13,39 +12,6 @@ workflows: only: /^v.*/ jobs: - build: - working_directory: ~/code - docker: - - image: mbgl/android-ndk-r21e:latest - environment: - JVM_OPTS: -Xmx3200m - steps: - - checkout - - restore_cache: - key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{ checksum "library/build.gradle" }}-{{ checksum "gradle/dependencies.gradle" }} - - run: - name: Download Dependencies - command: ./gradlew androidDependencies - - save_cache: - paths: - - ~/.gradle - key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{ checksum "library/build.gradle" }}-{{ checksum "gradle/dependencies.gradle" }} - - run: - name: Check code style - command: make checkstyle - - run: - name: Run Lint - command: ./gradlew lint - - run: - name: Run unit-test in Android libraries - command: make test - - store_artifacts: - path: app/build/reports - destination: reports - - store_test_results: - path: app/build/test-results - -# ------------------------------------------------------------------------------ release: docker: - image: mbgl/android-ndk-r21e:latest diff --git a/library/src/main/java/com/mapbox/android/gestures/AndroidGesturesManager.java b/library/src/main/java/com/mapbox/android/gestures/AndroidGesturesManager.java index fb99cc5..f9e9aca 100644 --- a/library/src/main/java/com/mapbox/android/gestures/AndroidGesturesManager.java +++ b/library/src/main/java/com/mapbox/android/gestures/AndroidGesturesManager.java @@ -12,6 +12,7 @@ import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; /** * Entry point for all of the detectors. Set listener for gestures you'd like to be notified about @@ -58,7 +59,7 @@ public class AndroidGesturesManager { public static final int GESTURE_TYPE_QUICK_SCALE = 15; private final List> mutuallyExclusiveGestures = new ArrayList<>(); - private final List detectors = new ArrayList<>(); + private final List detectors; private final StandardGestureDetector standardGestureDetector; private final StandardScaleGestureDetector standardScaleGestureDetector; @@ -128,13 +129,15 @@ public AndroidGesturesManager(Context context, List> exclusiveGestu moveGestureDetector = new MoveGestureDetector(context, this); standardGestureDetector = new StandardGestureDetector(context, this); - detectors.add(rotateGestureDetector); - detectors.add(standardScaleGestureDetector); - detectors.add(shoveGestureDetector); - detectors.add(sidewaysShoveGestureDetector); - detectors.add(multiFingerTapGestureDetector); - detectors.add(moveGestureDetector); - detectors.add(standardGestureDetector); + detectors = new CopyOnWriteArrayList(Arrays.asList( + rotateGestureDetector, + standardScaleGestureDetector, + shoveGestureDetector, + sidewaysShoveGestureDetector, + multiFingerTapGestureDetector, + moveGestureDetector, + standardGestureDetector + )); if (applyDefaultThresholds) { initDefaultThresholds(); diff --git a/library/src/test/java/com/mapbox/android/gestures/AndroidGesturesManagerTest.java b/library/src/test/java/com/mapbox/android/gestures/AndroidGesturesManagerTest.java index 2f14926..3d87a2d 100644 --- a/library/src/test/java/com/mapbox/android/gestures/AndroidGesturesManagerTest.java +++ b/library/src/test/java/com/mapbox/android/gestures/AndroidGesturesManagerTest.java @@ -1,5 +1,11 @@ package com.mapbox.android.gestures; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.view.MotionEvent; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -11,9 +17,6 @@ import java.util.List; import java.util.Set; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; - @RunWith(RobolectricTestRunner.class) public class AndroidGesturesManagerTest { private AndroidGesturesManager androidGesturesManager; @@ -44,9 +47,9 @@ public void setUp() throws Exception { mutuallyExclusivesList.add(set3); androidGesturesManager = - new AndroidGesturesManager( - RuntimeEnvironment.application.getApplicationContext(), - mutuallyExclusivesList, true); + new AndroidGesturesManager( + RuntimeEnvironment.application.getApplicationContext(), + mutuallyExclusivesList, true); } @Test @@ -69,4 +72,24 @@ public void setMutuallyExclusivesTest() throws Exception { androidGesturesManager.setMutuallyExclusiveGestures(mutuallyExclusivesList); assertEquals(androidGesturesManager.getMutuallyExclusiveGestures(), mutuallyExclusivesList); } + + @Test + public void onSingleTapModifyDetectorsTest() { + final StandardGestureDetector standardGestureDetector = new StandardGestureDetector( + RuntimeEnvironment.getApplication().getApplicationContext(), + androidGesturesManager + ); + + androidGesturesManager.setStandardGestureListener(new StandardGestureDetector.SimpleStandardOnGestureListener() { + @Override + public boolean onDown(MotionEvent e) { + androidGesturesManager.getDetectors().add(standardGestureDetector); + return true; + } + }); + + MotionEvent downEvent = TestUtils.INSTANCE.getMotionEvent(MotionEvent.ACTION_DOWN, 0, 0, null); + androidGesturesManager.onTouchEvent(downEvent); + assertTrue(androidGesturesManager.getDetectors().contains(standardGestureDetector)); + } }