From afa7cea4c04f65c79829b4b2bf57e5c2882fd65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Thu, 11 Jul 2019 12:21:59 +0200 Subject: [android] ensure location shadow's gradient is greater than 0 --- .../java/com/mapbox/mapboxsdk/location/Utils.java | 38 +++++++++++++++++++++- .../location/LocationLayerControllerTest.kt | 18 +++++++--- .../drawable/mapbox_user_icon_shadow_0px_test.xml | 19 +++++++++++ 3 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/mapbox_user_icon_shadow_0px_test.xml (limited to 'platform') diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java index b352dc9190..178183ca09 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java @@ -3,11 +3,15 @@ package com.mapbox.mapboxsdk.location; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; import android.location.Location; +import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.Projection; @@ -15,6 +19,8 @@ import static com.mapbox.mapboxsdk.location.LocationComponentConstants.INSTANT_L public final class Utils { + private static final String TAG = "Mbgl-com.mapbox.mapboxsdk.location.Utils"; + private Utils() { // Class should not be initialized } @@ -52,12 +58,42 @@ public final class Utils { Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); + try { + drawable.draw(canvas); + } catch (IllegalArgumentException ex) { + if (ex.getMessage().equals("radius must be > 0") && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + Logger.w(TAG, + "Location's shadow gradient drawable has a radius <= 0px, resetting to 1px in order to avoid crashing"); + ensureShadowGradientRadius(drawable); + return generateShadow(drawable, elevation); + } else { + throw ex; + } + } bitmap = Bitmap.createScaledBitmap(bitmap, toEven(width + elevation), toEven(height + elevation), false); return bitmap; } + /** + * We need to ensure that the radius of any {@link GradientDrawable} is greater than 0 for API levels < 21. + * + * @see mapbox-gl-native-#15026 + */ + private static void ensureShadowGradientRadius(Drawable drawable) { + if (drawable instanceof GradientDrawable) { + ((GradientDrawable) drawable).setGradientRadius(1); + } else if (drawable instanceof LayerDrawable) { + LayerDrawable layerDrawable = (LayerDrawable) drawable; + for (int i = 0; i < layerDrawable.getNumberOfLayers(); i++) { + Drawable layers = layerDrawable.getDrawable(i); + if (layers instanceof GradientDrawable) { + ((GradientDrawable) layers).setGradientRadius(1); + } + } + } + } + static float calculateZoomLevelRadius(@NonNull MapboxMap mapboxMap, @Nullable Location location) { if (location == null) { return 0; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt index 110d879bf3..c2d95d0e80 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt @@ -1,9 +1,9 @@ package com.mapbox.mapboxsdk.location import android.Manifest -import android.R import android.content.Context import android.location.Location +import android.support.test.annotation.UiThreadTest import android.support.test.espresso.Espresso.onView import android.support.test.espresso.IdlingRegistry import android.support.test.espresso.UiController @@ -23,8 +23,10 @@ import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.pushSour import com.mapbox.mapboxsdk.maps.MapboxMap import com.mapbox.mapboxsdk.maps.Style import com.mapbox.mapboxsdk.style.sources.GeoJsonSource +import com.mapbox.mapboxsdk.testapp.R import com.mapbox.mapboxsdk.testapp.activity.EspressoTest import com.mapbox.mapboxsdk.testapp.utils.TestingAsyncUtils +import com.mapbox.mapboxsdk.utils.BitmapUtils import org.hamcrest.CoreMatchers.`is` import org.hamcrest.CoreMatchers.notNullValue import org.hamcrest.Matchers.equalTo @@ -368,7 +370,7 @@ class LocationLayerControllerTest : EspressoTest() { executeComponentTest(componentAction) // Waiting for style to finish loading while pushing updates - onView(withId(R.id.content)).check(matches(isDisplayed())) + onView(withId(android.R.id.content)).check(matches(isDisplayed())) } @Test @@ -399,7 +401,7 @@ class LocationLayerControllerTest : EspressoTest() { executeComponentTest(componentAction) // Waiting for style to finish loading while pushing updates - onView(withId(R.id.content)).check(matches(isDisplayed())) + onView(withId(android.R.id.content)).check(matches(isDisplayed())) } @Test @@ -534,6 +536,14 @@ class LocationLayerControllerTest : EspressoTest() { executeComponentTest(componentAction) } + @Test + @UiThreadTest + fun test_15026_missingShadowGradientRadius() { + // test for https://github.com/mapbox/mapbox-gl-native/issues/15026 + val shadowDrawable = BitmapUtils.getDrawableFromRes(context, R.drawable.mapbox_user_icon_shadow_0px_test) + Utils.generateShadow(shadowDrawable, 0f) + } + @After override fun afterTest() { super.afterTest() @@ -541,6 +551,6 @@ class LocationLayerControllerTest : EspressoTest() { } private fun executeComponentTest(listener: LocationComponentAction.OnPerformLocationComponentAction) { - onView(withId(R.id.content)).perform(LocationComponentAction(mapboxMap, listener)) + onView(withId(android.R.id.content)).perform(LocationComponentAction(mapboxMap, listener)) } } \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/mapbox_user_icon_shadow_0px_test.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/mapbox_user_icon_shadow_0px_test.xml new file mode 100644 index 0000000000..13864f499c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/mapbox_user_icon_shadow_0px_test.xml @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file -- cgit v1.2.1