Merge pull request #7 from maptiler/mme-removal

Mapbox mobile events and telemetry removal
This commit is contained in:
Petr Pokorny
2021-01-26 11:26:29 +01:00
committed by GitHub
378 changed files with 3609 additions and 3821 deletions

View File

@@ -6,7 +6,7 @@ on:
tags-ignore:
- '**'
paths-ignore:
- "parform/ios/**"
- "platform/ios/**"
- ".github/**"
- "README.md"
branches:

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@
/platform/android/x86_64
/.idea
/cmake-build-debug
/platform/android/.idea

6
.gitmodules vendored
View File

@@ -46,15 +46,9 @@
[submodule "platform/android/vendor/mapbox-gestures-android"]
path = platform/android/vendor/mapbox-gestures-android
url = https://github.com/mapbox/mapbox-gestures-android.git
[submodule "platform/ios/platform/ios/vendor/mapbox-events-ios"]
path = platform/ios/platform/ios/vendor/mapbox-events-ios
url = https://github.com/mapbox/mapbox-events-ios.git
[submodule "platform/ios/platform/darwin/docs/theme"]
path = platform/ios/platform/darwin/docs/theme
url = https://github.com/mapbox/jazzy-theme.git
[submodule "platform/android/vendor/mapbox-events-android"]
path = platform/android/vendor/mapbox-events-android
url = https://github.com/mapbox/mapbox-events-android.git
[submodule "maplibre-gl-js"]
path = maplibre-gl-js
url = https://github.com/maplibre/maplibre-gl-js.git

View File

@@ -1,14 +1,15 @@
package android.app;
import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Assert;
import org.junit.runner.RunWith;
import android.util.Log;
@LargeTest
@RunWith(AndroidJUnit4.class)

View File

@@ -190,12 +190,6 @@ License: [BSD](https://opensource.org/licenses/BSD-2-Clause)
===========================================================================
Mapbox GL uses portions of Mapbox Android Telemetry Library.
URL: [https://github.com/mapbox/mapbox-events-android](https://github.com/mapbox/mapbox-events-android)
License: [The MIT License](https://opensource.org/licenses/MIT)
===========================================================================
Mapbox GL uses portions of Mapbox Java SDK.
URL: [https://github.com/mapbox/mapbox-java](https://github.com/mapbox/mapbox-java)
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)

View File

@@ -6,20 +6,23 @@ apply plugin: 'com.mapbox.android.sdk.versions'
dependencies {
lintChecks project(":MapboxGLAndroidSDKLint")
api dependenciesList.mapboxAndroidTelemetry
api dependenciesList.mapboxJavaGeoJSON
api dependenciesList.mapboxAndroidGestures
api dependenciesList.mapboxAndroidAccounts
implementation dependenciesList.mapboxJavaTurf
implementation dependenciesList.supportAnnotations
implementation dependenciesList.supportFragmentV4
implementation dependenciesList.okhttp3
implementation dependenciesList.gmsLocation
testImplementation dependenciesList.junit
testImplementation dependenciesList.mockito
testImplementation dependenciesList.mockk
testImplementation dependenciesList.robolectric
testImplementation dependenciesList.kotlinLib
testImplementation dependenciesList.commonsIO
testImplementation dependenciesList.assertjcore
}
android {

View File

@@ -16,7 +16,7 @@
-dontnote com.mapbox.mapboxsdk.maps.MapboxMap
-dontnote com.mapbox.mapboxsdk.maps.MapboxMapOptions
-dontnote com.mapbox.mapboxsdk.log.LoggerDefinition
-dontnote com.mapbox.android.core.location.LocationEnginePriority
-dontnote com.mapbox.mapboxsdk.location.engine.LocationEnginePriority
# config for okhttp 3.11.0, https://github.com/square/okhttp/pull/3354
-dontwarn javax.annotation.**
@@ -27,9 +27,6 @@
-keep class com.mapbox.geojson.** { *; }
-dontwarn com.google.auto.value.**
# config for telemetry events
-keep class com.mapbox.mapboxsdk.module.telemetry.** { *; }
# config for additional notes
-dontnote org.robolectric.Robolectric
-dontnote libcore.io.Memory

View File

@@ -4,17 +4,16 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.text.format.DateUtils;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.mapbox.android.accounts.v1.MapboxAccounts;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.log.Logger;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.KEY_PREFERENCE_SKU_TOKEN;
/**
* REMOVAL OR MODIFICATION OF THE FOLLOWING CODE VIOLATES THE MAPBOX TERMS
* OF SERVICE
@@ -39,45 +38,19 @@ class AccountsManager {
private SharedPreferences sharedPreferences;
private String userId;
private String skuToken;
private long timestamp;
private boolean isManaged;
AccountsManager() {
isManaged = isSkuTokenManaged();
initialize();
}
@VisibleForTesting
AccountsManager(SharedPreferences sharedPreferences, boolean isManaged) {
AccountsManager(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
this.isManaged = isManaged;
initialize();
}
private void initialize() {
retrieveSkuTokenAndTimestamp();
if (isManaged) {
validateRotation();
}
}
private boolean isSkuTokenManaged() {
boolean value = MapboxConstants.DEFAULT_MANAGE_SKU_TOKEN;
try {
// Try getting a custom value from the app Manifest
ApplicationInfo appInfo = retrieveApplicationInfo();
if (appInfo.metaData != null) {
value = appInfo.metaData.getBoolean(
MapboxConstants.KEY_META_DATA_MANAGE_SKU_TOKEN,
MapboxConstants.DEFAULT_MANAGE_SKU_TOKEN
);
}
} catch (Exception exception) {
Logger.e(TAG, "Failed to read the package metadata: ", exception);
}
return value;
}
private ApplicationInfo retrieveApplicationInfo() throws PackageManager.NameNotFoundException {
@@ -86,33 +59,6 @@ class AccountsManager {
PackageManager.GET_META_DATA);
}
private void retrieveSkuTokenAndTimestamp() {
SharedPreferences sharedPreferences = getSharedPreferences();
skuToken = sharedPreferences.getString(KEY_PREFERENCE_SKU_TOKEN, "");
timestamp = sharedPreferences.getLong(PREFERENCE_TIMESTAMP, 0L);
}
private void validateRotation() {
if (TextUtils.isEmpty(skuToken) || timestamp == 0L) {
skuToken = generateSkuToken(getUserId());
timestamp = persistRotation(skuToken);
}
}
String getSkuToken() {
if (isManaged) {
if (isExpired()) {
skuToken = generateSkuToken(getUserId());
timestamp = persistRotation(skuToken);
}
} else {
SharedPreferences sharedPreferences = getSharedPreferences();
String notManagedSkuToken = sharedPreferences.getString(KEY_PREFERENCE_SKU_TOKEN, "");
skuToken = notManagedSkuToken;
}
return skuToken;
}
private boolean isExpired() {
return isExpired(getNow(), timestamp);
}
@@ -121,15 +67,6 @@ class AccountsManager {
return ((now - then) > DateUtils.HOUR_IN_MILLIS);
}
private long persistRotation(String skuToken) {
long now = getNow();
SharedPreferences.Editor editor = getSharedPreferences().edit();
editor.putLong(PREFERENCE_TIMESTAMP, now);
editor.putString(KEY_PREFERENCE_SKU_TOKEN, skuToken);
editor.apply();
return now;
}
@NonNull
private SharedPreferences getSharedPreferences() {
if (sharedPreferences == null) {
@@ -167,9 +104,4 @@ class AccountsManager {
private String generateUserId() {
return MapboxAccounts.obtainEndUserId();
}
@NonNull
private String generateSkuToken(String userId) {
return MapboxAccounts.obtainMapsSkuUserToken(userId);
}
}

View File

@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.AssetManager;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -10,8 +11,6 @@ import androidx.annotation.UiThread;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.utils.ThreadUtils;
@@ -37,8 +36,6 @@ public final class Mapbox {
@Nullable
private String accessToken;
@Nullable
private TelemetryDefinition telemetry;
@Nullable
private AccountsManager accounts;
/**
@@ -61,7 +58,6 @@ public final class Mapbox {
FileSource.initializeFileDirsPaths(appContext);
INSTANCE = new Mapbox(appContext, accessToken);
if (isAccessTokenValid(accessToken)) {
initializeTelemetry();
INSTANCE.accounts = new AccountsManager();
}
ConnectivityReceiver.instance(appContext);
@@ -92,15 +88,8 @@ public final class Mapbox {
validateMapbox();
INSTANCE.accessToken = accessToken;
// cleanup telemetry which is dependent on an access token
if (INSTANCE.telemetry != null) {
INSTANCE.telemetry.disableTelemetrySession();
INSTANCE.telemetry = null;
}
// initialize components dependent on a token
if (isAccessTokenValid(accessToken)) {
initializeTelemetry();
INSTANCE.accounts = new AccountsManager();
} else {
INSTANCE.accounts = null;
@@ -108,23 +97,6 @@ public final class Mapbox {
FileSource.getInstance(getApplicationContext()).setAccessToken(accessToken);
}
/**
* Returns a SKU token, refreshed if necessary. This method is meant for internal SDK
* usage only.
*
* @return the SKU token
*/
public static String getSkuToken() {
if (!hasInstance() || INSTANCE.accounts == null) {
throw new MapboxConfigurationException(
"A valid access token parameter is required when using a Mapbox service."
+ "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
+ "Currently provided token is: " + INSTANCE.accessToken);
}
return INSTANCE.accounts.getSkuToken();
}
/**
* Application context
*
@@ -159,29 +131,6 @@ public final class Mapbox {
return ConnectivityReceiver.instance(INSTANCE.context).isConnected();
}
/**
* Initializes telemetry
*/
private static void initializeTelemetry() {
try {
INSTANCE.telemetry = getModuleProvider().obtainTelemetry();
} catch (Exception exception) {
String message = "Error occurred while initializing telemetry";
Logger.e(TAG, message, exception);
MapStrictMode.strictModeViolation(message, exception);
}
}
/**
* Get an instance of Telemetry if initialised
*
* @return instance of telemetry
*/
@Nullable
public static TelemetryDefinition getTelemetry() {
return hasInstance() ? INSTANCE.telemetry : null;
}
/**
* Get the module provider
*

View File

@@ -1,9 +1,8 @@
package com.mapbox.mapboxsdk;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.http.HttpRequest;
import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
/**
* Injects concrete instances of configurable abstractions
@@ -18,15 +17,6 @@ public interface ModuleProvider {
@NonNull
HttpRequest createHttpRequest();
/**
* Get the concrete implementation of TelemetryDefinition
*
* @return a single instance of Telemetry
*/
@Nullable
TelemetryDefinition obtainTelemetry();
/**
* Get the concrete implementation of LibraryLoaderProvider
*

View File

@@ -1,12 +1,10 @@
package com.mapbox.mapboxsdk;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.http.HttpRequest;
import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
import com.mapbox.mapboxsdk.module.http.HttpRequestImpl;
import com.mapbox.mapboxsdk.module.loader.LibraryLoaderProviderImpl;
import com.mapbox.mapboxsdk.module.telemetry.TelemetryImpl;
public class ModuleProviderImpl implements ModuleProvider {
@@ -16,12 +14,6 @@ public class ModuleProviderImpl implements ModuleProvider {
return new HttpRequestImpl();
}
@Override
@Nullable
public TelemetryDefinition obtainTelemetry() {
return new TelemetryImpl();
}
@NonNull
@Override
public LibraryLoaderProvider createLibraryLoaderProvider() {

View File

@@ -1,7 +1,6 @@
package com.mapbox.mapboxsdk.annotations;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.maps.MapView;

View File

@@ -1,8 +1,8 @@
package com.mapbox.mapboxsdk.annotations;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.geometry.LatLng;
import java.util.ArrayList;

View File

@@ -8,6 +8,7 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
@Deprecated

View File

@@ -5,11 +5,12 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.R;
/**

View File

@@ -3,10 +3,11 @@ package com.mapbox.mapboxsdk.annotations;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import androidx.annotation.NonNull;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.R;
@Deprecated

View File

@@ -1,9 +1,10 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Bitmap;
import android.util.DisplayMetrics;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.DisplayMetrics;
import java.nio.ByteBuffer;

View File

@@ -7,11 +7,12 @@ import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.exceptions.TooManyIconsException;

View File

@@ -3,9 +3,6 @@ package com.mapbox.mapboxsdk.annotations;
import android.content.res.Resources;
import android.graphics.PointF;
import android.os.Build;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -13,6 +10,10 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.TextView;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;

View File

@@ -1,9 +1,10 @@
package com.mapbox.mapboxsdk.annotations;
import android.view.View;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.geometry.LatLng;

View File

@@ -6,6 +6,7 @@ import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.exceptions.InvalidMarkerPositionException;
import com.mapbox.mapboxsdk.geometry.LatLng;

View File

@@ -1,9 +1,10 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Color;
import androidx.annotation.Keep;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;

View File

@@ -6,6 +6,7 @@ import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.geometry.LatLng;
import java.util.ArrayList;

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Color;
import androidx.annotation.Keep;
import com.mapbox.mapboxsdk.maps.MapboxMap;

View File

@@ -5,6 +5,7 @@ import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.geometry.LatLng;
import java.util.ArrayList;

View File

@@ -9,9 +9,7 @@ public class Attribution {
private static final String OPENSTREETMAP = "OpenStreetMap";
private static final String OPENSTREETMAP_ABBR = "OSM";
static final String TELEMETRY = "Telemetry Settings";
static final String MAPBOX_URL = "https://www.mapbox.com/about/maps/";
static final String TELEMETRY_URL = "https://www.mapbox.com/telemetry/";
static final List<String> IMPROVE_MAP_URLS = new ArrayList<>();
static {

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.attribution;
import android.graphics.Bitmap;
import android.graphics.PointF;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

View File

@@ -2,9 +2,10 @@ package com.mapbox.mapboxsdk.attribution;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.widget.TextView;
import java.util.Arrays;
import java.util.List;

View File

@@ -1,12 +1,12 @@
package com.mapbox.mapboxsdk.attribution;
import android.content.Context;
import androidx.annotation.NonNull;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.URLSpan;
import com.mapbox.mapboxsdk.R;
import androidx.annotation.NonNull;
import java.lang.ref.WeakReference;
import java.util.LinkedHashSet;
@@ -21,22 +21,19 @@ import java.util.Set;
*/
public class AttributionParser {
private static final String IMPROVE_THIS_MAP = "Improve this map";
private final WeakReference<Context> context;
private final Set<Attribution> attributions = new LinkedHashSet<>();
private final String attributionData;
private final boolean withImproveMap;
private final boolean withCopyrightSign;
private final boolean withTelemetryAttribution;
private final boolean withMapboxAttribution;
AttributionParser(WeakReference<Context> context, String attributionData, boolean withImproveMap,
boolean withCopyrightSign, boolean withTelemetryAttribution, boolean withMapboxAttribution) {
boolean withCopyrightSign, boolean withMapboxAttribution) {
this.context = context;
this.attributionData = attributionData;
this.withImproveMap = withImproveMap;
this.withCopyrightSign = withCopyrightSign;
this.withTelemetryAttribution = withTelemetryAttribution;
this.withMapboxAttribution = withMapboxAttribution;
}
@@ -85,7 +82,6 @@ public class AttributionParser {
*/
protected void parse() {
parseAttributions();
addAdditionalAttributions();
}
/**
@@ -109,9 +105,6 @@ public class AttributionParser {
String url = urlSpan.getURL();
if (isUrlValid(url)) {
String anchor = parseAnchorValue(htmlBuilder, urlSpan);
if (isImproveThisMapAnchor(anchor)) {
anchor = translateImproveThisMapAnchor(anchor);
}
attributions.add(new Attribution(anchor, url));
}
}
@@ -126,30 +119,6 @@ public class AttributionParser {
return isValidForImproveThisMap(url) && isValidForMapbox(url);
}
/**
* Invoked to validate if an anchor is equal to Improve this map coming from tilesets.
*
* @param anchor the anchor to be validated
* @return if the url is valid
*/
private boolean isImproveThisMapAnchor(String anchor) {
return anchor.equals(IMPROVE_THIS_MAP);
}
/**
* Invoked to replace the english Improve this map with localized variant.
*
* @param anchor the anchor to be translated
* @return the translated anchor
*/
private String translateImproveThisMapAnchor(String anchor) {
Context context = this.context.get();
if (context != null) {
anchor = context.getString(R.string.mapbox_telemetryImproveMap);
}
return anchor;
}
/**
* Invoked to validate if an url is valid for the improve map configuration.
*
@@ -201,21 +170,6 @@ public class AttributionParser {
return anchor;
}
/**
* Invoked to manually add attributions
*/
private void addAdditionalAttributions() {
if (withTelemetryAttribution) {
Context context = this.context.get();
attributions.add(
new Attribution(
context != null ? context.getString(R.string.mapbox_telemetrySettings) : Attribution.TELEMETRY,
Attribution.TELEMETRY_URL
)
);
}
}
/**
* Convert a string to a spanned html representation.
*
@@ -236,15 +190,14 @@ public class AttributionParser {
* Builder to configure using an AttributionParser.
* <p>
* AttributionData, set with {@link #withAttributionData(String...)}, is the only required property to build
* the underlying AttributionParser. Other properties include trimming the copyright sign, adding telemetry
* attribution or hiding attribution as improve this map and Mapbox.
* the underlying AttributionParser. Other properties include trimming the copyright sign, hiding
* attribution as improve this map and Mapbox.
* </p>
*/
public static class Options {
private final WeakReference<Context> context;
private boolean withImproveMap = true;
private boolean withCopyrightSign = true;
private boolean withTelemetryAttribution = false;
private boolean withMapboxAttribution = true;
private String[] attributionDataStringArray;
@@ -270,12 +223,6 @@ public class AttributionParser {
return this;
}
@NonNull
public Options withTelemetryAttribution(boolean withTelemetryAttribution) {
this.withTelemetryAttribution = withTelemetryAttribution;
return this;
}
@NonNull
public Options withMapboxAttribution(boolean withMapboxAttribution) {
this.withMapboxAttribution = withMapboxAttribution;
@@ -294,7 +241,6 @@ public class AttributionParser {
fullAttributionString,
withImproveMap,
withCopyrightSign,
withTelemetryAttribution,
withMapboxAttribution
);
attributionParser.parse();

View File

@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.camera;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.FloatRange;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.camera;
import android.graphics.Point;
import android.graphics.PointF;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

View File

@@ -37,12 +37,6 @@ public class MapboxConstants {
*/
public static final boolean DEFAULT_MEASURE_TILE_DOWNLOAD_ON = false;
public static final String KEY_PREFERENCE_SKU_TOKEN = "com.mapbox.mapboxsdk.accounts.skutoken";
public static final String KEY_META_DATA_MANAGE_SKU_TOKEN = "com.mapbox.ManageSkuToken";
public static final boolean DEFAULT_MANAGE_SKU_TOKEN = true;
/**
* Default value for font fallback for local ideograph fonts
*/

View File

@@ -1,14 +0,0 @@
package com.mapbox.mapboxsdk.constants;
@Deprecated
public class TelemetryConstants {
public static final String TWO_FINGER_TAP = "TwoFingerTap";
public static final String DOUBLE_TAP = "DoubleTap";
public static final String SINGLE_TAP = "SingleTap";
public static final String PAN = "Pan";
public static final String PINCH = "Pinch";
public static final String ROTATION = "Rotation";
public static final String PITCH = "Pitch";
}

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.exceptions;
import android.content.Context;
import androidx.annotation.NonNull;
/**

View File

@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.geometry;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.FloatRange;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;

View File

@@ -2,10 +2,12 @@ package com.mapbox.mapboxsdk.geometry;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.FloatRange;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.constants.GeometryConstants;
import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException;

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.geometry;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.geometry;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
/**

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.geometry;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.geometry;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
/**

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.http;
import android.content.Context;
import android.content.pm.PackageInfo;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.MapStrictMode;

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.http;
import android.util.Log;
import com.mapbox.mapboxsdk.log.Logger;
import static com.mapbox.mapboxsdk.http.HttpRequest.CONNECTION_ERROR;

View File

@@ -2,8 +2,6 @@ package com.mapbox.mapboxsdk.http;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.Mapbox;
public class HttpRequestUrl {
private HttpRequestUrl() {
@@ -31,8 +29,6 @@ public class HttpRequestUrl {
// Only add SKU token to requests not tagged as "offline" usage.
if (offline) {
resourceUrl = resourceUrl + "offline=true";
} else {
resourceUrl = resourceUrl + "sku=" + Mapbox.getSkuToken();
}
}
return resourceUrl;

View File

@@ -5,6 +5,7 @@ import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.log.Logger;

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.http;
import androidx.annotation.Keep;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.Mapbox;
import java.util.concurrent.locks.ReentrantLock;

View File

@@ -2,6 +2,8 @@ package com.mapbox.mapboxsdk.location;
import android.graphics.Bitmap;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.maps.Style;
@@ -10,8 +12,6 @@ import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
import com.mapbox.mapboxsdk.utils.ColorUtils;
import androidx.annotation.Nullable;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_ICON;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_STALE_ICON;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BEARING_ICON;

View File

@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.location;
import android.animation.TypeEvaluator;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.geometry.LatLng;
class LatLngEvaluator implements TypeEvaluator<LatLng> {

View File

@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.location;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;

View File

@@ -14,18 +14,18 @@ import androidx.annotation.RequiresPermission;
import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineCallback;
import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.android.core.location.LocationEngineRequest;
import com.mapbox.android.core.location.LocationEngineResult;
import com.mapbox.android.core.permissions.PermissionsManager;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdate;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.engine.LocationEngine;
import com.mapbox.mapboxsdk.location.engine.LocationEngineCallback;
import com.mapbox.mapboxsdk.location.engine.LocationEngineProvider;
import com.mapbox.mapboxsdk.location.engine.LocationEngineRequest;
import com.mapbox.mapboxsdk.location.engine.LocationEngineResult;
import com.mapbox.mapboxsdk.location.modes.CameraMode;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.location.permissions.PermissionsManager;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -77,10 +77,10 @@ import static com.mapbox.mapboxsdk.location.LocationComponentConstants.TRANSITIO
* <p>
* This component offers a default, built-in {@link LocationEngine} with some of the activation methods.
* This engine will be obtained by {@link LocationEngineProvider#getBestLocationEngine(Context, boolean)} which defaults
* to the {@link com.mapbox.android.core.location.MapboxFusedLocationEngineImpl}. If you'd like to utilize Google
* to the {@link com.mapbox.mapboxsdk.location.engine.MapboxFusedLocationEngineImpl}. If you'd like to utilize Google
* Play Services
* for more precise location updates, simply add the Google Play Location Services dependency in your build script.
* This will make the default engine the {@link com.mapbox.android.core.location.GoogleLocationEngineImpl} instead.
* This will make the default engine the {@link com.mapbox.mapboxsdk.location.engine.GoogleLocationEngineImpl} instead.
* After a custom engine is passed to the component, or the built-in is initialized,
* the location updates are going to be requested with the {@link LocationEngineRequest}, either a default one,
* or the one passed during the activation.

View File

@@ -5,8 +5,8 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineRequest;
import com.mapbox.mapboxsdk.location.engine.LocationEngine;
import com.mapbox.mapboxsdk.location.engine.LocationEngineRequest;
import com.mapbox.mapboxsdk.maps.Style;
/**

View File

@@ -5,11 +5,12 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.SystemClock;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.log.Logger;
import java.util.ArrayList;

View File

@@ -5,17 +5,13 @@ package com.mapbox.mapboxsdk.location;
import androidx.annotation.ColorInt;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
/**
*

View File

@@ -5,13 +5,13 @@ package com.mapbox.mapboxsdk.location;
import androidx.annotation.ColorInt;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.types.Formatted;
import static com.mapbox.mapboxsdk.utils.ColorUtils.colorToRgbaString;
import com.mapbox.mapboxsdk.style.layers.LayoutPropertyValue;
import com.mapbox.mapboxsdk.style.layers.PaintPropertyValue;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import static com.mapbox.mapboxsdk.utils.ColorUtils.colorToRgbaString;
/**
* Constructs paint/layout properties for Layers
*

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.location;
import android.os.Handler;
import android.os.Message;
import androidx.annotation.NonNull;
import java.lang.ref.WeakReference;

View File

@@ -7,6 +7,7 @@ import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.location.Location;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

View File

@@ -0,0 +1,175 @@
package com.mapbox.mapboxsdk.location.engine;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
/**
* A location engine that uses core android.location and has no external dependencies
* https://developer.android.com/guide/topics/location/strategies.html
*/
class AndroidLocationEngineImpl implements LocationEngineImpl<LocationListener> {
private static final String TAG = "AndroidLocationEngine";
final LocationManager locationManager;
String currentProvider = LocationManager.PASSIVE_PROVIDER;
AndroidLocationEngineImpl(@NonNull Context context) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}
@NonNull
@Override
public LocationListener createListener(LocationEngineCallback<LocationEngineResult> callback) {
return new AndroidLocationEngineCallbackTransport(callback);
}
@Override
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback)
throws SecurityException {
Location lastLocation = getLastLocationFor(currentProvider);
if (lastLocation != null) {
callback.onSuccess(LocationEngineResult.create(lastLocation));
return;
}
for (String provider : locationManager.getAllProviders()) {
lastLocation = getLastLocationFor(provider);
if (lastLocation != null) {
callback.onSuccess(LocationEngineResult.create(lastLocation));
return;
}
}
callback.onFailure(new Exception("Last location unavailable"));
}
@SuppressLint("MissingPermission")
Location getLastLocationFor(String provider) throws SecurityException {
Location location = null;
try {
location = locationManager.getLastKnownLocation(provider);
} catch (IllegalArgumentException iae) {
Log.e(TAG, iae.toString());
}
return location;
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationListener listener,
@Nullable Looper looper) throws SecurityException {
// Pick best provider only if user has not explicitly chosen passive mode
currentProvider = getBestProvider(request.getPriority());
locationManager.requestLocationUpdates(currentProvider, request.getInterval(), request.getDisplacement(),
listener, looper);
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull PendingIntent pendingIntent) throws SecurityException {
// Pick best provider only if user has not explicitly chosen passive mode
currentProvider = getBestProvider(request.getPriority());
locationManager.requestLocationUpdates(currentProvider, request.getInterval(),
request.getDisplacement(), pendingIntent);
}
@SuppressLint("MissingPermission")
@Override
public void removeLocationUpdates(@NonNull LocationListener listener) {
if (listener != null) {
locationManager.removeUpdates(listener);
}
}
@Override
public void removeLocationUpdates(PendingIntent pendingIntent) {
if (pendingIntent != null) {
locationManager.removeUpdates(pendingIntent);
}
}
private String getBestProvider(int priority) {
String provider = null;
// Pick best provider only if user has not explicitly chosen passive mode
if (priority != LocationEngineRequest.PRIORITY_NO_POWER) {
provider = locationManager.getBestProvider(getCriteria(priority), true);
}
return provider != null ? provider : LocationManager.PASSIVE_PROVIDER;
}
@VisibleForTesting
static Criteria getCriteria(int priority) {
Criteria criteria = new Criteria();
criteria.setAccuracy(priorityToAccuracy(priority));
criteria.setCostAllowed(true);
criteria.setPowerRequirement(priorityToPowerRequirement(priority));
return criteria;
}
private static int priorityToAccuracy(int priority) {
switch (priority) {
case LocationEngineRequest.PRIORITY_HIGH_ACCURACY:
case LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY:
return Criteria.ACCURACY_FINE;
case LocationEngineRequest.PRIORITY_LOW_POWER:
case LocationEngineRequest.PRIORITY_NO_POWER:
default:
return Criteria.ACCURACY_COARSE;
}
}
private static int priorityToPowerRequirement(int priority) {
switch (priority) {
case LocationEngineRequest.PRIORITY_HIGH_ACCURACY:
return Criteria.POWER_HIGH;
case LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY:
return Criteria.POWER_MEDIUM;
case LocationEngineRequest.PRIORITY_LOW_POWER:
case LocationEngineRequest.PRIORITY_NO_POWER:
default:
return Criteria.POWER_LOW;
}
}
@VisibleForTesting
static final class AndroidLocationEngineCallbackTransport implements LocationListener {
private final LocationEngineCallback<LocationEngineResult> callback;
AndroidLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}
@Override
public void onLocationChanged(Location location) {
callback.onSuccess(LocationEngineResult.create(location));
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
// noop
}
@Override
public void onProviderEnabled(String s) {
// noop
}
@Override
public void onProviderDisabled(String s) {
callback.onFailure(new Exception("Current provider disabled"));
}
}
}

View File

@@ -0,0 +1,146 @@
package com.mapbox.mapboxsdk.location.engine;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.location.Location;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.Collections;
import java.util.List;
/**
* Wraps implementation of Fused Location Provider
*/
class GoogleLocationEngineImpl implements LocationEngineImpl<LocationCallback> {
private final FusedLocationProviderClient fusedLocationProviderClient;
@VisibleForTesting
GoogleLocationEngineImpl(FusedLocationProviderClient fusedLocationProviderClient) {
this.fusedLocationProviderClient = fusedLocationProviderClient;
}
GoogleLocationEngineImpl(@NonNull Context context) {
this.fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
}
@NonNull
@Override
public LocationCallback createListener(LocationEngineCallback<LocationEngineResult> callback) {
return new GoogleLocationEngineCallbackTransport(callback);
}
@SuppressLint("MissingPermission")
@Override
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback)
throws SecurityException {
GoogleLastLocationEngineCallbackTransport transport =
new GoogleLastLocationEngineCallbackTransport(callback);
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(transport).addOnFailureListener(transport);
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationCallback listener,
@Nullable Looper looper) throws SecurityException {
fusedLocationProviderClient.requestLocationUpdates(toGMSLocationRequest(request), listener, looper);
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull PendingIntent pendingIntent) throws SecurityException {
fusedLocationProviderClient.requestLocationUpdates(toGMSLocationRequest(request), pendingIntent);
}
@Override
public void removeLocationUpdates(@NonNull LocationCallback listener) {
if (listener != null) {
fusedLocationProviderClient.removeLocationUpdates(listener);
}
}
@Override
public void removeLocationUpdates(PendingIntent pendingIntent) {
if (pendingIntent != null) {
fusedLocationProviderClient.removeLocationUpdates(pendingIntent);
}
}
private static LocationRequest toGMSLocationRequest(LocationEngineRequest request) {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setInterval(request.getInterval());
locationRequest.setFastestInterval(request.getFastestInterval());
locationRequest.setSmallestDisplacement(request.getDisplacement());
locationRequest.setMaxWaitTime(request.getMaxWaitTime());
locationRequest.setPriority(toGMSLocationPriority(request.getPriority()));
return locationRequest;
}
private static int toGMSLocationPriority(int enginePriority) {
switch (enginePriority) {
case LocationEngineRequest.PRIORITY_HIGH_ACCURACY:
return LocationRequest.PRIORITY_HIGH_ACCURACY;
case LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY:
return LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
case LocationEngineRequest.PRIORITY_LOW_POWER:
return LocationRequest.PRIORITY_LOW_POWER;
case LocationEngineRequest.PRIORITY_NO_POWER:
default:
return LocationRequest.PRIORITY_NO_POWER;
}
}
private static final class GoogleLocationEngineCallbackTransport extends LocationCallback {
private final LocationEngineCallback<LocationEngineResult> callback;
GoogleLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
List<Location> locations = locationResult.getLocations();
if (!locations.isEmpty()) {
callback.onSuccess(LocationEngineResult.create(locations));
} else {
callback.onFailure(new Exception("Unavailable location"));
}
}
}
@VisibleForTesting
static final class GoogleLastLocationEngineCallbackTransport
implements OnSuccessListener<Location>, OnFailureListener {
private final LocationEngineCallback<LocationEngineResult> callback;
GoogleLastLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}
@Override
public void onSuccess(Location location) {
callback.onSuccess(location != null ? LocationEngineResult.create(location) :
LocationEngineResult.create(Collections.<Location>emptyList()));
}
@Override
public void onFailure(@NonNull Exception e) {
callback.onFailure(e);
}
}
}

View File

@@ -0,0 +1,82 @@
package com.mapbox.mapboxsdk.location.engine;
import android.app.PendingIntent;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresPermission;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
/**
* Generic location engine interface wrapper for the location providers.
* Default providers bundled with Mapbox location library:
* Android location provider and Google Play Services fused location provider
*
* @since 1.0.0
*/
public interface LocationEngine {
/**
* Returns the most recent location currently available.
* <p>
* If a location is not available, which should happen very rarely, null will be returned.
*
* @param callback {@link LocationEngineCallback} for the location result {@link LocationEngineResult}.
* @throws SecurityException if permission is not granted to access location services.
* @since 1.0.0
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback) throws SecurityException;
/**
* Requests location updates with a callback on the specified Looper thread.
*
* @param request {@link LocationEngineRequest} for the updates.
* @param callback {@link LocationEngineCallback} for the location result {@link LocationEngineResult}.
* @param looper The Looper object whose message queue will be used to implement the callback mechanism,
* or null to invoke callbacks on the main thread.
* @throws SecurityException if permission is not granted to access location services.
* @since 1.0.0
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationEngineCallback<LocationEngineResult> callback,
@Nullable Looper looper) throws SecurityException;
/**
* Requests location updates with callback on the specified PendingIntent.
*
* @param request {@link LocationEngineRequest} for the updates.
* @param pendingIntent {@link PendingIntent} for the location result {@link LocationEngineResult}.
* @throws SecurityException if permission is not granted to access location services.
* @since 1.1.0
*/
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
void requestLocationUpdates(@NonNull LocationEngineRequest request,
PendingIntent pendingIntent) throws SecurityException;
/**
* Removes location updates for the given location engine callback.
* <p>
* It is recommended to remove location requests when the activity is in a paused or
* stopped state, doing so helps battery performance.
*
* @param callback {@link LocationEngineCallback} to remove.
* @since 1.0.0
*/
void removeLocationUpdates(@NonNull LocationEngineCallback<LocationEngineResult> callback);
/**
* Removes location updates for the given pending intent.
* <p>
* It is recommended to remove location requests when the activity is in a paused or
* stopped state, doing so helps battery performance.
*
* @param pendingIntent {@link PendingIntent} to remove.
* @since 1.1.0
*/
void removeLocationUpdates(PendingIntent pendingIntent);
}

View File

@@ -0,0 +1,25 @@
package com.mapbox.mapboxsdk.location.engine;
import androidx.annotation.NonNull;
/**
* Invoked for asynchronous notifications when new data
* from engine becomes available.
*
* @param <T> Successful updated data type
*/
public interface LocationEngineCallback<T> {
/**
* Invoked when new data available.
*
* @param result updated data.
*/
void onSuccess(T result);
/**
* Invoked when engine exception occurs.
*
* @param exception {@link Exception}
*/
void onFailure(@NonNull Exception exception);
}

View File

@@ -0,0 +1,29 @@
package com.mapbox.mapboxsdk.location.engine;
import android.app.PendingIntent;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* Internal location engine implementation interface.
*
* @param <T> location listener object type
*/
interface LocationEngineImpl<T> {
@NonNull
T createListener(LocationEngineCallback<LocationEngineResult> callback);
void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback) throws SecurityException;
void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull T listener, @Nullable Looper looper) throws SecurityException;
void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull PendingIntent pendingIntent) throws SecurityException;
void removeLocationUpdates(T listener);
void removeLocationUpdates(PendingIntent pendingIntent);
}

View File

@@ -0,0 +1,62 @@
package com.mapbox.mapboxsdk.location.engine;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import static com.mapbox.mapboxsdk.location.engine.Utils.checkNotNull;
import static com.mapbox.mapboxsdk.location.engine.Utils.isOnClasspath;
/**
* The main entry point for location engine integration.
*/
public final class LocationEngineProvider {
private static final String GOOGLE_LOCATION_SERVICES = "com.google.android.gms.location.LocationServices";
private static final String GOOGLE_API_AVAILABILITY = "com.google.android.gms.common.GoogleApiAvailability";
private LocationEngineProvider() {
// prevent instantiation
}
/**
* Returns instance to the best location engine, given the included libraries.
*
* @param context {@link Context}.
* @param background true if background optimized engine is desired (note: parameter deprecated)
* @return a unique instance of {@link LocationEngine} every time method is called.
* @since 1.0.0
*/
@NonNull
@Deprecated
public static LocationEngine getBestLocationEngine(@NonNull Context context, boolean background) {
return getBestLocationEngine(context);
}
/**
* Returns instance to the best location engine, given the included libraries.
*
* @param context {@link Context}.
* @return a unique instance of {@link LocationEngine} every time method is called.
* @since 1.1.0
*/
@NonNull
public static LocationEngine getBestLocationEngine(@NonNull Context context) {
checkNotNull(context, "context == null");
boolean hasGoogleLocationServices = isOnClasspath(GOOGLE_LOCATION_SERVICES);
if (isOnClasspath(GOOGLE_API_AVAILABILITY)) {
// Check Google Play services APK is available and up-to-date on this device
hasGoogleLocationServices &= GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
== ConnectionResult.SUCCESS;
}
return getLocationEngine(context, hasGoogleLocationServices);
}
private static LocationEngine getLocationEngine(Context context, boolean isGoogle) {
return isGoogle ? new LocationEngineProxy<>(new GoogleLocationEngineImpl(context.getApplicationContext())) :
new LocationEngineProxy<>(new MapboxFusedLocationEngineImpl(context.getApplicationContext()));
}
}

View File

@@ -0,0 +1,80 @@
package com.mapbox.mapboxsdk.location.engine;
import android.app.PendingIntent;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.mapbox.mapboxsdk.location.engine.Utils.checkNotNull;
class LocationEngineProxy<T> implements LocationEngine {
private final LocationEngineImpl<T> locationEngineImpl;
private Map<LocationEngineCallback<LocationEngineResult>, T> listeners;
LocationEngineProxy(LocationEngineImpl<T> locationEngineImpl) {
this.locationEngineImpl = locationEngineImpl;
}
@Override
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback) throws SecurityException {
checkNotNull(callback, "callback == null");
locationEngineImpl.getLastLocation(callback);
}
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationEngineCallback<LocationEngineResult> callback,
@Nullable Looper looper) throws SecurityException {
checkNotNull(request, "request == null");
checkNotNull(callback, "callback == null");
locationEngineImpl.requestLocationUpdates(request, getListener(callback),
looper == null ? Looper.getMainLooper() : looper);
}
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
PendingIntent pendingIntent) throws SecurityException {
checkNotNull(request, "request == null");
locationEngineImpl.requestLocationUpdates(request, pendingIntent);
}
@Override
public void removeLocationUpdates(@NonNull LocationEngineCallback<LocationEngineResult> callback) {
checkNotNull(callback, "callback == null");
locationEngineImpl.removeLocationUpdates(removeListener(callback));
}
@Override
public void removeLocationUpdates(PendingIntent pendingIntent) {
locationEngineImpl.removeLocationUpdates(pendingIntent);
}
@VisibleForTesting
int getListenersCount() {
return listeners != null ? listeners.size() : 0;
}
@VisibleForTesting
T getListener(@NonNull LocationEngineCallback<LocationEngineResult> callback) {
if (listeners == null) {
listeners = new ConcurrentHashMap<>();
}
T listener = listeners.get(callback);
if (listener == null) {
listener = locationEngineImpl.createListener(callback);
}
listeners.put(callback, listener);
return listener;
}
@VisibleForTesting
T removeListener(@NonNull LocationEngineCallback<LocationEngineResult> callback) {
return listeners != null ? listeners.remove(callback) : null;
}
}

View File

@@ -0,0 +1,242 @@
package com.mapbox.mapboxsdk.location.engine;
/**
* Data model that contains parameters for location
* engine requests.
*
* @since 1.0.0
*/
public class LocationEngineRequest {
/**
* Used with {@link Builder#setPriority(int)} to request
* the most accurate location.
*
* @since 1.0.0
*/
public static final int PRIORITY_HIGH_ACCURACY = 0;
/**
* Used with {@link Builder#setPriority(int)} to request
* coarse location that is battery optimized.
*
* @since 1.0.0
*/
public static final int PRIORITY_BALANCED_POWER_ACCURACY = 1;
/**
* Used with {@link Builder#setPriority(int)} to request
* coarse ~ 10 km accuracy location.
*
* @since 1.0.0
*/
public static final int PRIORITY_LOW_POWER = 2;
/**
* Used with {@link Builder#setPriority(int)} to request
* passive location: no locations will be returned unless a different client
* has requested location updates.
*
* @since 1.0.0
*/
public static final int PRIORITY_NO_POWER = 3;
private final long interval;
private final int priority;
private final float displacement;
private final long maxWaitTime;
private final long fastestInterval;
private LocationEngineRequest(Builder builder) {
this.interval = builder.interval;
this.priority = builder.priority;
this.displacement = builder.displacement;
this.maxWaitTime = builder.maxWaitTime;
this.fastestInterval = builder.fastestInterval;
}
/**
* Returns desired interval between location updates
* in milliseconds.
*
* @return desired interval in milliseconds.
* @since 1.0.0
*/
public long getInterval() {
return interval;
}
/**
* Returns desired quality of the request.
*
* @return accuracy constant.
* @since 1.0.0
*/
public int getPriority() {
return priority;
}
/**
* Returns distance between location updates.
*
* @return distance between location updates in meters.
* @since 1.0.0
*/
public float getDisplacement() {
return displacement;
}
/**
* Returns maximum wait time in milliseconds for location updates.
*
* @return maximum wait time in milliseconds.
* @since 1.0.0
*/
public long getMaxWaitTime() {
return maxWaitTime;
}
/**
* Returns fastest interval in milliseconds for location updates.
*
* @return fastest interval in milliseconds.
* @since 1.0.0
*/
public long getFastestInterval() {
return fastestInterval;
}
/**
* Compares this LocationEngineRequest to the specified object.
*
* @param o locationEngineRequest to compare to.
* @return true when the type and values are equal, false otherwise.
* @since 3.1.1
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LocationEngineRequest that = (LocationEngineRequest) o;
if (interval != that.interval) {
return false;
}
if (priority != that.priority) {
return false;
}
if (Float.compare(that.displacement, displacement) != 0) {
return false;
}
if (maxWaitTime != that.maxWaitTime) {
return false;
}
return fastestInterval == that.fastestInterval;
}
/**
* Returns a hash code for this object.
*
* @return integer hash of the values.
* @since 3.1.1
*/
@Override
public int hashCode() {
int result = (int) (interval ^ (interval >>> 32));
result = 31 * result + priority;
result = 31 * result + (displacement != +0.0f ? Float.floatToIntBits(displacement) : 0);
result = 31 * result + (int) (maxWaitTime ^ (maxWaitTime >>> 32));
result = 31 * result + (int) (fastestInterval ^ (fastestInterval >>> 32));
return result;
}
public static final class Builder {
private final long interval;
private int priority;
private float displacement;
private long maxWaitTime;
private long fastestInterval;
/**
* Default builder constructor.
*
* @param interval default interval between location updates
* @since 1.0.0
*/
public Builder(long interval) {
this.interval = interval;
this.priority = PRIORITY_HIGH_ACCURACY;
this.displacement = 0.0f;
this.maxWaitTime = 0L;
this.fastestInterval = 0L;
}
/**
* Set priority for request.
* Use priority constant: {@link #PRIORITY_HIGH_ACCURACY}
*
* @param priority constant
* @return reference to builder
* @since 1.0.0
*/
public Builder setPriority(int priority) {
this.priority = priority;
return this;
}
/**
* Set distance between location updates.
*
* @param displacement distance between locations in meters.
* @return reference to builder
* @since 1.0.0
*/
public Builder setDisplacement(float displacement) {
this.displacement = displacement;
return this;
}
/**
* Sets the maximum wait time in milliseconds for location updates.
* <p>
* Locations determined at intervals but delivered in batch based on
* wait time. Batching is not supported by all engines.
*
* @param maxWaitTime wait time in milliseconds.
* @return reference to builder
* @since 1.0.0
*/
public Builder setMaxWaitTime(long maxWaitTime) {
this.maxWaitTime = maxWaitTime;
return this;
}
/**
* Sets the fastest interval in milliseconds for location updates.
*
* @param interval fastest interval in milliseconds.
* @return reference to builder
* @since 1.0.0
*/
public Builder setFastestInterval(long interval) {
this.fastestInterval = interval;
return this;
}
/**
* Builds request object.
*
* @return instance of location request.
* @since 1.0.0
*/
public LocationEngineRequest build() {
return new LocationEngineRequest(this);
}
}
}

View File

@@ -0,0 +1,119 @@
package com.mapbox.mapboxsdk.location.engine;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.location.LocationResult;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.mapbox.mapboxsdk.location.engine.Utils.isOnClasspath;
/**
* A wrapper class representing location result from the location engine.
* <p>
* TODO: Override default equals(), hashCode() and toString()
*
* @since 1.0.0
*/
public final class LocationEngineResult {
private static final String GOOGLE_PLAY_LOCATION_RESULT = "com.google.android.gms.location.LocationResult";
private final List<Location> locations;
private LocationEngineResult(List<Location> locations) {
this.locations = Collections.unmodifiableList(locations);
}
/**
* Creates {@link LocationEngineResult} instance for location.
*
* @param location default location added to the result.
* @return instance of the new location result.
* @since 1.0.0
*/
@NonNull
public static LocationEngineResult create(@Nullable Location location) {
List<Location> locations = new ArrayList<>();
if (location != null) {
locations.add(location);
}
return new LocationEngineResult(locations);
}
/**
* Creates {@link LocationEngineResult} instance for given list of locations.
*
* @param locations list of locations.
* @return instance of the new location result.
* @since 1.0.0
*/
@NonNull
public static LocationEngineResult create(@Nullable List<Location> locations) {
if (locations != null) {
List<Location> locationsList = new ArrayList<>(locations);
locationsList.removeAll(Collections.singleton(null));
return new LocationEngineResult(locationsList);
}
return new LocationEngineResult(Collections.<Location>emptyList());
}
/**
* Returns most recent location available in this result.
*
* @return the most recent location {@link Location} or null.
* @since 1.0.0
*/
@Nullable
public Location getLastLocation() {
return locations.isEmpty() ? null : locations.get(0);
}
/**
* Returns locations computed, ordered from oldest to newest.
*
* @return ordered list of locations.
* @since 1.0.0
*/
public List<Location> getLocations() {
return Collections.unmodifiableList(locations);
}
/**
* Extracts location result from intent object
*
* @param intent valid intent object
* @return location result.
* @since 1.1.0
*/
@Nullable
public static LocationEngineResult extractResult(Intent intent) {
LocationEngineResult result = null;
if (isOnClasspath(GOOGLE_PLAY_LOCATION_RESULT)) {
result = extractGooglePlayResult(intent);
}
return result == null ? extractAndroidResult(intent) : result;
}
private static LocationEngineResult extractGooglePlayResult(Intent intent) {
LocationResult result = LocationResult.extractResult(intent);
return result != null ? LocationEngineResult.create(result.getLocations()) : null;
}
private static LocationEngineResult extractAndroidResult(Intent intent) {
return !hasResult(intent) ? null :
LocationEngineResult.create((Location) intent.getExtras()
.getParcelable(LocationManager.KEY_LOCATION_CHANGED));
}
private static boolean hasResult(Intent intent) {
return intent != null && intent.hasExtra(LocationManager.KEY_LOCATION_CHANGED);
}
}

View File

@@ -0,0 +1,137 @@
package com.mapbox.mapboxsdk.location.engine;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import static com.mapbox.mapboxsdk.location.engine.Utils.isBetterLocation;
/**
* Mapbox replacement for Google Play Services Fused Location Client
* <p>
* Note: fusion will not work in background mode.
*/
class MapboxFusedLocationEngineImpl extends AndroidLocationEngineImpl {
private static final String TAG = "MapboxLocationEngine";
MapboxFusedLocationEngineImpl(@NonNull Context context) {
super(context);
}
@NonNull
@Override
public LocationListener createListener(LocationEngineCallback<LocationEngineResult> callback) {
return new MapboxLocationEngineCallbackTransport(callback);
}
@Override
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback) throws SecurityException {
Location bestLastLocation = getBestLastLocation();
if (bestLastLocation != null) {
callback.onSuccess(LocationEngineResult.create(bestLastLocation));
} else {
callback.onFailure(new Exception("Last location unavailable"));
}
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationListener listener,
@Nullable Looper looper) throws SecurityException {
super.requestLocationUpdates(request, listener, looper);
// Start network provider along with gps
if (shouldStartNetworkProvider(request.getPriority())) {
try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
request.getInterval(), request.getDisplacement(),
listener, looper);
} catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
}
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull PendingIntent pendingIntent) throws SecurityException {
super.requestLocationUpdates(request, pendingIntent);
// Start network provider along with gps
if (shouldStartNetworkProvider(request.getPriority())) {
try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, request.getInterval(),
request.getDisplacement(), pendingIntent);
} catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
}
}
private Location getBestLastLocation() {
Location bestLastLocation = null;
for (String provider : locationManager.getAllProviders()) {
Location location = getLastLocationFor(provider);
if (location == null) {
continue;
}
if (isBetterLocation(location, bestLastLocation)) {
bestLastLocation = location;
}
}
return bestLastLocation;
}
private boolean shouldStartNetworkProvider(int priority) {
return (priority == LocationEngineRequest.PRIORITY_HIGH_ACCURACY
|| priority == LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY)
&& currentProvider.equals(LocationManager.GPS_PROVIDER);
}
private static final class MapboxLocationEngineCallbackTransport implements LocationListener {
private final LocationEngineCallback<LocationEngineResult> callback;
private Location currentBestLocation;
MapboxLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}
@Override
public void onLocationChanged(Location location) {
if (isBetterLocation(location, currentBestLocation)) {
currentBestLocation = location;
}
if (callback != null) {
callback.onSuccess(LocationEngineResult.create(currentBestLocation));
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "onProviderDisabled: " + provider);
}
}
}

View File

@@ -0,0 +1,106 @@
package com.mapbox.mapboxsdk.location.engine;
import android.location.Location;
import androidx.annotation.Nullable;
final class Utils {
private static final int TWO_MINUTES = 1000 * 60 * 2;
private static final int ACCURACY_THRESHOLD_METERS = 200;
private Utils() {
// Prevent instantiation
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference object reference.
* @param message exception message to use if check fails.
* @param <T> object type.
* @return validated non-null reference.
*/
static <T> T checkNotNull(@Nullable T reference, String message) {
if (reference == null) {
throw new NullPointerException(message);
}
return reference;
}
/**
* Checks if class is on class path
* @param className of the class to check.
* @return true if class in on class path, false otherwise.
*/
static boolean isOnClasspath(String className) {
boolean isOnClassPath = true;
try {
Class.forName(className);
} catch (ClassNotFoundException exception) {
isOnClassPath = false;
}
return isOnClassPath;
}
/**
* Determines whether one Location reading is better than the current Location fix
* <p>
* (c) https://developer.android.com/guide/topics/location/strategies
*
* @param location The new Location that you want to evaluate
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
static boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > ACCURACY_THRESHOLD_METERS;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/**
* Checks whether two providers are the same
* <p>
* (c) https://developer.android.com/guide/topics/location/strategies
*/
private static boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
}

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.location.modes;
import android.location.Location;
import androidx.annotation.IntDef;
import com.mapbox.mapboxsdk.location.LocationComponent;

View File

@@ -0,0 +1,14 @@
package com.mapbox.mapboxsdk.location.permissions;
import java.util.List;
/**
* Callback used in PermissionsManager
*/
public interface PermissionsListener {
void onExplanationNeeded(List<String> permissionsToExplain);
void onPermissionResult(boolean granted);
}

View File

@@ -0,0 +1,152 @@
package com.mapbox.mapboxsdk.location.permissions;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Helps request permissions at runtime.
*/
public class PermissionsManager {
private static final String LOG_TAG = "PermissionsManager";
private static final String COARSE_LOCATION_PERMISSION = Manifest.permission.ACCESS_COARSE_LOCATION;
private static final String FINE_LOCATION_PERMISSION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String BACKGROUND_LOCATION_PERMISSION = "android.permission.ACCESS_BACKGROUND_LOCATION";
private final int REQUEST_PERMISSIONS_CODE = 0;
private PermissionsListener listener;
public PermissionsManager(PermissionsListener listener) {
this.listener = listener;
}
public PermissionsListener getListener() {
return listener;
}
public void setListener(PermissionsListener listener) {
this.listener = listener;
}
private static boolean isPermissionGranted(Context context, String permission) {
return ContextCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED;
}
private static boolean isCoarseLocationPermissionGranted(Context context) {
return isPermissionGranted(context, COARSE_LOCATION_PERMISSION);
}
private static boolean isFineLocationPermissionGranted(Context context) {
return isPermissionGranted(context, FINE_LOCATION_PERMISSION);
}
public static boolean isBackgroundLocationPermissionGranted(Context context) {
if (Build.VERSION.SDK_INT >= 29) {
return isPermissionGranted(context, BACKGROUND_LOCATION_PERMISSION);
}
return areLocationPermissionsGranted(context);
}
public static boolean areLocationPermissionsGranted(Context context) {
return isCoarseLocationPermissionGranted(context)
|| isFineLocationPermissionGranted(context);
}
public static boolean areRuntimePermissionsRequired() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
public void requestLocationPermissions(Activity activity) {
try {
PackageInfo packageInfo = activity.getPackageManager().getPackageInfo(
activity.getPackageName(), PackageManager.GET_PERMISSIONS);
String[] requestedPermissions = packageInfo.requestedPermissions;
if (requestedPermissions != null) {
List<String> permissionList = Arrays.asList(requestedPermissions);
boolean fineLocPermission = permissionList.contains(FINE_LOCATION_PERMISSION);
boolean coarseLocPermission = permissionList.contains(COARSE_LOCATION_PERMISSION);
boolean backgroundLocPermission = permissionList.contains(BACKGROUND_LOCATION_PERMISSION);
// Request location permissions
if (fineLocPermission) {
requestLocationPermissions(activity, true, backgroundLocPermission);
} else if (coarseLocPermission) {
requestLocationPermissions(activity, false, backgroundLocPermission);
} else {
Log.w(LOG_TAG, "Location permissions are missing");
}
}
} catch (Exception exception) {
Log.w(LOG_TAG, exception.getMessage());
}
}
private void requestLocationPermissions(Activity activity, boolean requestFineLocation,
boolean requestBackgroundLocation) {
List<String> permissions = new ArrayList<>();
if (requestFineLocation) {
permissions.add(FINE_LOCATION_PERMISSION);
} else {
permissions.add(COARSE_LOCATION_PERMISSION);
}
if (Build.VERSION.SDK_INT >= 29 && requestBackgroundLocation) {
permissions.add(BACKGROUND_LOCATION_PERMISSION);
}
requestPermissions(activity, permissions.toArray(new String[permissions.size()]));
}
private void requestPermissions(Activity activity, String[] permissions) {
ArrayList<String> permissionsToExplain = new ArrayList<>();
for (String permission : permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
permissionsToExplain.add(permission);
}
}
if (listener != null && permissionsToExplain.size() > 0) {
// The developer should show an explanation to the user asynchronously
listener.onExplanationNeeded(permissionsToExplain);
}
ActivityCompat.requestPermissions(activity, permissions, REQUEST_PERMISSIONS_CODE);
}
/**
* You should call this method from your activity onRequestPermissionsResult.
*
* @param requestCode The request code passed in requestPermissions(android.app.Activity, String[], int)
* @param permissions The requested permissions. Never null.
* @param grantResults The grant results for the corresponding permissions which is either
* PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
*/
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSIONS_CODE:
if (listener != null) {
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
listener.onPermissionResult(granted);
}
break;
default:
// Ignored
}
}
}

View File

@@ -1,8 +1,9 @@
package com.mapbox.mapboxsdk.log;
import android.util.Log;
import androidx.annotation.IntDef;
import androidx.annotation.Keep;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

View File

@@ -4,10 +4,12 @@ import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.LongSparseArray;
import android.view.View;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;

View File

@@ -7,11 +7,13 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.R;
@@ -34,7 +36,6 @@ import java.util.regex.Pattern;
* <p>
* When the user clicks the attribution icon, {@link AttributionDialogManager#onClick(View)} will be invoked.
* An attribution dialog will be shown to the user with contents based on the attributions found in the map style.
* Additionally an telemetry option item is shown to configure telemetry settings.
* </p>
*/
public class AttributionDialogManager implements View.OnClickListener, DialogInterface.OnClickListener {
@@ -87,14 +88,10 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
return titles.toArray(new String[titles.size()]);
}
// Called when someone selects an attribution or telemetry settings from the dialog
// Called when someone selects an attribution from the dialog
@Override
public void onClick(DialogInterface dialog, int which) {
if (isLatestEntry(which)) {
showTelemetryDialog();
} else {
showMapAttributionWebPage(which);
}
showMapAttributionWebPage(which);
}
public void onStop() {
@@ -107,40 +104,6 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
return attributionKeyIndex == getAttributionTitles().length - 1;
}
private void showTelemetryDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.mapbox_attributionTelemetryTitle);
builder.setMessage(R.string.mapbox_attributionTelemetryMessage);
builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() {
@Override
public void onClick(@NonNull DialogInterface dialog, int which) {
TelemetryDefinition telemetry = Mapbox.getTelemetry();
if (telemetry != null) {
telemetry.setUserTelemetryRequestState(true);
}
dialog.cancel();
}
});
builder.setNeutralButton(R.string.mapbox_attributionTelemetryNeutral, new DialogInterface.OnClickListener() {
@Override
public void onClick(@NonNull DialogInterface dialog, int which) {
showWebPage(context.getResources().getString(R.string.mapbox_telemetryLink));
dialog.cancel();
}
});
builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() {
@Override
public void onClick(@NonNull DialogInterface dialog, int which) {
TelemetryDefinition telemetry = Mapbox.getTelemetry();
if (telemetry != null) {
telemetry.setUserTelemetryRequestState(false);
}
dialog.cancel();
}
});
builder.show();
}
private void showMapAttributionWebPage(int which) {
Attribution[] attributions = attributionSet.toArray(new Attribution[attributionSet.size()]);
String url = attributions[which].getUrl();
@@ -236,7 +199,6 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
return new AttributionParser.Options(context)
.withCopyrightSign(true)
.withImproveMap(true)
.withTelemetryAttribution(true)
.withAttributionData(attributions.toArray(new String[attributions.size()]))
.build().getAttributions();
}

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.maps;
import android.os.Handler;
import android.os.Message;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;

View File

@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.maps;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;

View File

@@ -1,8 +1,9 @@
package com.mapbox.mapboxsdk.maps;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;

View File

@@ -3,13 +3,14 @@ package com.mapbox.mapboxsdk.maps;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
import java.util.ArrayList;

View File

@@ -7,14 +7,13 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.PointF;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.MultiFingerTapGestureDetector;

View File

@@ -3,12 +3,13 @@ package com.mapbox.mapboxsdk.maps;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* Manages key events on a MapView.
* <p>

View File

@@ -297,12 +297,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
*/
@UiThread
public void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState == null) {
TelemetryDefinition telemetry = Mapbox.getTelemetry();
if (telemetry != null) {
telemetry.onAppUserTurnstileEvent();
}
} else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
if (savedInstanceState != null && savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
this.savedInstanceState = savedInstanceState;
}
}

View File

@@ -8,6 +8,13 @@ import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.FloatRange;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import androidx.annotation.UiThread;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -38,13 +45,6 @@ import com.mapbox.mapboxsdk.style.expressions.Expression;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.FloatRange;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Size;
import androidx.annotation.UiThread;
/**
* The general class to interact with in the Android Mapbox SDK. It exposes the entry point for all
* methods related to the MapView. You cannot instantiate {@link MapboxMap} object directly, rather,

View File

@@ -7,6 +7,9 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
@@ -15,10 +18,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.content.res.ResourcesCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.maps;
import android.graphics.RectF;
import androidx.annotation.NonNull;
import androidx.collection.LongSparseArray;

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.maps;
import android.graphics.RectF;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;

View File

@@ -4,6 +4,10 @@ import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.Geometry;
import com.mapbox.mapboxsdk.annotations.Marker;
@@ -21,10 +25,6 @@ import com.mapbox.mapboxsdk.style.sources.Source;
import java.util.List;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
interface NativeMap {
//

View File

@@ -7,6 +7,11 @@ import android.graphics.RectF;
import android.os.Handler;
import android.text.TextUtils;
import androidx.annotation.IntRange;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.Geometry;
import com.mapbox.mapboxsdk.LibraryLoader;
@@ -36,11 +41,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import androidx.annotation.IntRange;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
// Class that wraps the native methods for convenience
final class NativeMapView implements NativeMap {

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.maps;
import android.graphics.PointF;
import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.maps;
import android.graphics.RectF;
import androidx.annotation.NonNull;
import androidx.collection.LongSparseArray;

View File

@@ -6,6 +6,11 @@ import android.os.AsyncTask;
import android.util.DisplayMetrics;
import android.util.Pair;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringDef;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
@@ -23,11 +28,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringDef;
/**
* The proxy object for current map style.
* <p>

View File

@@ -2,14 +2,15 @@ package com.mapbox.mapboxsdk.maps;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
import java.util.ArrayList;

View File

@@ -1,66 +0,0 @@
package com.mapbox.mapboxsdk.maps;
import android.os.Bundle;
import com.mapbox.mapboxsdk.offline.OfflineRegionDefinition;
/**
* Definition of TelemetryImpl collection.
* Use{@link TelemetryDefinition} for posting the event.
*/
public interface TelemetryDefinition {
/**
* Register the app user turnstile event
*/
void onAppUserTurnstileEvent();
/**
* Register an end-user gesture interaction event.
*
* @param eventType type of gesture event occurred
* @param latitude the latitude value of the gesture focal point
* @param longitude the longitude value of the gesture focal point
* @param zoom current zoom of the map
* @deprecated since 7.5.0, this event is no longer supported
*/
@Deprecated
void onGestureInteraction(String eventType, double latitude, double longitude, double zoom);
/**
* Set the end-user selected state to participate or opt-out in telemetry collection.
*/
void setUserTelemetryRequestState(boolean enabled);
/**
* Disables a started telemetry service for this session only.
*/
void disableTelemetrySession();
/**
* Set the end-user selected state to participate or opt-out in telemetry collection.
*/
void setDebugLoggingEnabled(boolean debugLoggingEnabled);
/**
* Set the telemetry rotation session id interval
*
* @param interval the selected session interval
* @return true if rotation session id was updated
*/
boolean setSessionIdRotationInterval(int interval);
/**
* Register an end-user offline download event.
*
* @param offlineDefinition the offline region definition
*/
void onCreateOfflineRegion(OfflineRegionDefinition offlineDefinition);
/**
* Register a performance event.
*
* @param data performance event data
*/
void onPerformanceEvent(Bundle data);
}

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.maps;
import android.graphics.PointF;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.maps.renderer;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;

View File

@@ -8,14 +8,14 @@ import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.log.Logger;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import static com.mapbox.mapboxsdk.utils.Compare.compare;
import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_MASK_SIZE;
import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE;

View File

@@ -1,9 +1,10 @@
package com.mapbox.mapboxsdk.maps.renderer.textureview;
import android.content.Context;
import androidx.annotation.NonNull;
import android.view.TextureView;
import androidx.annotation.NonNull;
import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import javax.microedition.khronos.egl.EGLConfig;

View File

@@ -1,13 +1,12 @@
package com.mapbox.mapboxsdk.maps.renderer.textureview;
import android.graphics.SurfaceTexture;
import android.view.TextureView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import android.view.TextureView;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.maps.renderer.egl.EGLConfigChooser;

View File

@@ -2,15 +2,16 @@ package com.mapbox.mapboxsdk.maps.widgets;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.core.view.ViewPropertyAnimatorCompat;
import androidx.core.view.ViewPropertyAnimatorListenerAdapter;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.mapbox.mapboxsdk.maps.MapboxMap;

View File

@@ -4,6 +4,10 @@ import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.http.HttpIdentifier;
@@ -21,9 +25,6 @@ import java.net.UnknownHostException;
import javax.net.ssl.SSLException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;

View File

@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.module.http;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import okhttp3.OkHttpClient;
import okio.Buffer;

View File

@@ -1,39 +0,0 @@
package com.mapbox.mapboxsdk.module.telemetry;
import android.annotation.SuppressLint;
import android.os.Parcel;
import com.mapbox.android.telemetry.Event;
/**
* Base event class for telemetry events.
*/
@SuppressLint("ParcelCreator")
abstract class MapBaseEvent extends Event {
private final String event;
private final String created;
MapBaseEvent(PhoneState phoneState) {
this.event = getEventName();
this.created = phoneState.getCreated();
}
abstract String getEventName();
String getEvent() {
return event;
}
String getCreated() {
return created;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
}

View File

@@ -1,57 +0,0 @@
package com.mapbox.mapboxsdk.module.telemetry;
import android.os.Bundle;
import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;
import com.mapbox.android.telemetry.TelemetryUtils;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.offline.OfflineRegion;
class MapEventFactory {
static MapLoadEvent buildMapLoadEvent(@NonNull PhoneState phoneState) {
String userId = TelemetryUtils.retrieveVendorId();
return new MapLoadEvent(userId, phoneState);
}
static OfflineDownloadStartEvent buildOfflineDownloadStartEvent(PhoneState phoneState,
String shapeForOfflineRegion,
@FloatRange(from = MapboxConstants.MINIMUM_ZOOM,
to = MapboxConstants.MAXIMUM_ZOOM) Double minZoom,
@FloatRange(from = MapboxConstants.MINIMUM_ZOOM,
to = MapboxConstants.MAXIMUM_ZOOM) Double maxZoom,
String styleURL) {
OfflineDownloadStartEvent offlineEvent =
new OfflineDownloadStartEvent(phoneState, shapeForOfflineRegion, minZoom, maxZoom);
offlineEvent.setStyleURL(styleURL);
return offlineEvent;
}
static OfflineDownloadEndEvent buildOfflineDownloadCompleteEvent(PhoneState phoneState,
String shapeForOfflineRegion,
@FloatRange(from = MapboxConstants.MINIMUM_ZOOM,
to = MapboxConstants.MAXIMUM_ZOOM) Double minZoom,
@FloatRange(from = MapboxConstants.MINIMUM_ZOOM,
to = MapboxConstants.MAXIMUM_ZOOM) Double maxZoom,
String styleURL,
long sizeOfResourcesCompleted,
long numberOfTilesCompleted,
@OfflineRegion.DownloadState int state) {
OfflineDownloadEndEvent offlineEvent =
new OfflineDownloadEndEvent(phoneState, shapeForOfflineRegion, minZoom, maxZoom);
offlineEvent.setStyleURL(styleURL);
offlineEvent.setSizeOfResourcesCompleted(sizeOfResourcesCompleted);
offlineEvent.setNumberOfTilesCompleted(numberOfTilesCompleted);
offlineEvent.setState(state);
return offlineEvent;
}
static PerformanceEvent buildPerformanceEvent(@NonNull PhoneState phoneState, @NonNull String sessionId,
@NonNull Bundle data) {
return new PerformanceEvent(phoneState, sessionId, data);
}
}

Some files were not shown because too many files have changed in this diff Show More