diff --git a/platform/android/DEVELOPING.md b/platform/android/DEVELOPING.md
index 0e0135af1..50222a13f 100644
--- a/platform/android/DEVELOPING.md
+++ b/platform/android/DEVELOPING.md
@@ -1,12 +1,65 @@
# Developing - MapLibre Native for Android
-These instructions are for developers interested in making code-level contributions to the SDK itself.
+These instructions are for developers interested in making code-level contributions to MapLibre Native for Android.
+
+## Getting the source
+
+Clone the git repository and pull in submodules:
+
+```bash
+git clone git@github.com:maplibre/maplibre-native.git
+cd maplibre-native
+git submodule update --init --recursive
+cd platform/android
+```
+
+## Requirements
+
+[Android Studio](https://developer.android.com/studio) needs to be installed.
+
+Open the `platform/android` directory to get started.
+
+## Setting an API Key
+
+_The test application (used for development purposes) uses MapTiler vector tiles, which require a MapTiler account and API key._
+
+With the first Gradle invocation, Gradle will take the value of the `MLN_API_KEY` environment variable and save it to `MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml`. If the environment variable wasn't set, you can edit `developer-config.xml` manually and add your API key to the `api_key` resource.
+
+## Running the TestApp
+
+Run the configuration for the `MapboxGLAndroidSDKTestApp` module and select a device or emulator to deploy on.
+
+
+
+
+
+## Render Tests
+
+To run the render tests for Android, run the configuration for the `androidRenderTest.app` module.
+
+## Instrumentation Tests
+
+To run the instrumentatin tests, find the `MapboxGLAndroidSDKTestApp` project in the sidebar, go to `src > androidTest`, right click and select "Run 'All Tests'".
+
+
+
+Your device needs remain unlocked for the duration of the tests.
+
+The instrumentation tests take a long time to run (depending on the device, about an hour). You can modify the run configuration in Android Studio and add the regex `^(?!.*org\.maplibre\.android\.benchmark).*$` to exclude the benchmark.
+
+### AWS Device Farm
+
+The instrumentation tests are running on AWS Device Farm. To see the results and the logs, go to:
+
+https://us-west-2.console.aws.amazon.com/devicefarm/home?region=us-east-1#/mobile/projects/20687d72-0e46-403e-8f03-0941850665bc/runs
+
+You can log with the `maplibre` alias, with `maplibre` as username and `maplibre` as password (this is a read-only account).
## Kotlin
All new code should be written in [Kotlin](https://kotlinlang.org/).
-### Style Checking
+## Style Checking
To check Kotlin style, we use [ktlint](https://pinterest.github.io/ktlint/). This linter is based on the [official Kotlin coding conventions](https://kotlinlang.org/docs/coding-conventions.html). We intergrate with it using the [kotlinder](https://github.com/jeremymailen/kotlinter-gradle) Gradle plugin.
@@ -20,114 +73,4 @@ To format all Kotlin source files, use:
```
$ ./gradlew formatKotlin
-```
-
-## Getting the source
-
-Clone the git repository and pull in submodules:
-
-```bash
-git clone git@github.com:maplibre/maplibre-native.git
-cd maplibre-native
-git submodule update --init --recursive
-cd platform/android
-```
-
-## Installing dependencies
-
-These dependencies are required for all operating systems and all platform targets.
-
-- Latest stable [Android Studio](https://developer.android.com/studio/index.html)
-- Update the Mapbox Maps SDK for Android with the latest
- - Android SDK Build-Tools
- - Android Platform-Tools
- - Android SDK Tools
- - CMake
- - NDK
- - LLDB
-- Modern C++ compiler that supports `-std=c++14`\*
- - clang++ 3.5 or later or
- - g++-4.9 or later
-- [Node.js](https://nodejs.org/)
- - make sure [npm](https://www.npmjs.com) is installed as well
-- [ccache](https://ccache.samba.org/) (optional)
-
-**Note**: We partially support C++14 because GCC 4.9 does not fully implement the
-final draft of the C++14 standard. More information in [DEVELOPING.md](../../DEVELOPING.md).
-
-**Note**: On macOS you can install clang with installing the [Apple command line developer tools](https://developer.apple.com/download/).
-
-## Opening the project
-
-### macOS
-
-* Environment
- * Android Studio
- * node
- * `JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home"`
- * `ANDROID_SDK_ROOT=~/Library/Android/sdk`
- * In Android Studio, go to Tools > [SDK Manager](https://developer.android.com/studio/projects/install-ndk#specific-version) to install CMake and the specific NDK version specified in [`dependencies.gradle`](https://github.com/maplibre/maplibre-native/blob/main/platform/android/gradle/dependencies.gradle).
-
-Open `platform/android` with Android Studio.
-
-### Linux
-
-run `make android-configuration` in the root folder of the project and open in Android Studio.
-
-If you are using Arch Linux, install [ncurses5-compat-libs](https://aur.archlinux.org/packages/ncurses5-compat-libs).
-
-## Project configuration
-
-### Setup Checkstyle
-
-Mapbox uses specific IDE settings related to code and check style.
-See [checkstyle guide](https://github.com/mapbox/mapbox-gl-native-android/wiki/Setting-up-Mapbox-checkstyle) for configuration details.
-
-#### Resolving duplicate file entries
-With buck build support, Android Studio can complain about duplicate source files. To remove this warning, open `MapboxGLAndroidSDK.iml` find the list of `excludeFolder` entries and add `` line.
-
-### Setting API Key
-
-_The test application (used for development purposes) uses MapTiler vector tiles, which require a MapTiler account and API key._
-
-With the first gradle invocation, gradle will take the value of the `MLN_API_KEY` environment variable and save it to `MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml`. If the environment variable wasn't set, you can edit `developer-config.xml` manually and add your api key to the `api_key` resource.
-
-## Running project
-
-Run the configuration for the `MapboxGLAndroidSDKTestApp` module and select a device or emulator to deploy on. Based on the selected device, the c++ code will be compiled for the related processor architecture. You can see the project compiling in the `View > Tool Windows > Gradle Console`.
-
-More information about building and distributing this project in [DISTRIBUTE.md](DISTRIBUTE.md).
-
-## Additional resources
-
-### Using the SDK snapshot
-
-Instead of using the latest stable release of the Maps SDK for Android, you can use a "snapshot" or the beta version if there is one available. Our snapshots are built every time a Github pull request adds code to this repository's `master` branch. If you'd like to use a snapshot build, your Android project's gradle file should have -SNAPSHOT appended to the SDK version number:
-
-```java
-// Mapbox SDK dependency
-implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.1.0-SNAPSHOT'
-```
-
-You also need to have the section below in your build.gradle root folder to be able to resolve the SNAPSHOT dependencies:
-```
-allprojects {
- repositories {
- jcenter()
- maven { url 'https://oss.jfrog.org/artifactory/oss-snapshot-local/' }
- }
-}
-```
-
-### Symbolicating native crashes
-
-When hitting native crashes you can use ndk-stack to symbolicate crashes.
-More information in [this](https://github.com/mapbox/mapbox-gl-native-android/wiki/Getting-line-numbers-from-an-Android-crash-with-ndk-stack) guide.
-
-## Instrumentation Tests
-
-The results of the instrumentation tests can be accessed on the AWS Console:
-
-https://us-west-2.console.aws.amazon.com/devicefarm/home?region=us-east-1#/mobile/projects/20687d72-0e46-403e-8f03-0941850665bc/runs
-
-You can log with the `maplibre` alias, with `maplibre` as username and `maplibre` as password (this is a read-only account).
+```
\ No newline at end of file
diff --git a/platform/android/Makefile b/platform/android/Makefile
index 81cb2e718..5d180cf40 100644
--- a/platform/android/Makefile
+++ b/platform/android/Makefile
@@ -234,7 +234,7 @@ run-android-test-app-center:
# Uploads the compiled Android SDK to Maven Central Staging
.PHONY: run-android-publish
run-android-publish:
- $(MLN_ANDROID_GRADLE_SINGLE_JOB) --debug -Pmapbox.abis=all :MapboxGLAndroidSDK:publishReleasePublicationToSonatypeRepository closeAndReleaseSonatypeStagingRepository
+ $(MLN_ANDROID_GRADLE_SINGLE_JOB)-Pmapbox.abis=all :MapboxGLAndroidSDK:publishReleasePublicationToSonatypeRepository closeAndReleaseSonatypeStagingRepository
# Dump system graphics information for the test app
.PHONY: android-gfxinfo
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/org/maplibre/android/offline/OfflineManager.kt b/platform/android/MapboxGLAndroidSDK/src/main/java/org/maplibre/android/offline/OfflineManager.kt
index e234c2781..4bf9ac8ab 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/org/maplibre/android/offline/OfflineManager.kt
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/org/maplibre/android/offline/OfflineManager.kt
@@ -21,11 +21,7 @@ import java.nio.channels.FileChannel
/**
* The offline manager is the main entry point for offline-related functionality.
*
- *
* It'll help you list and create offline regions.
- *
- *
- * @see [Offline Maps Information/](https://docs.mapbox.com/help/troubleshooting/mobile-offline/)
*/
@UiThread
class OfflineManager private constructor(context: Context) {
@@ -106,9 +102,6 @@ class OfflineManager private constructor(context: Context) {
fun onError(error: String)
}
- /*
- * Constructor
- */
init {
this.context = context.applicationContext
fileSource = FileSource.getInstance(this.context)
@@ -126,11 +119,9 @@ class OfflineManager private constructor(context: Context) {
/**
* Retrieve all regions in the offline database.
*
- *
* The query will be executed asynchronously and the results passed to the given
* callback on the main thread.
*
- *
* @param callback the callback to be invoked
*/
fun listOfflineRegions(callback: ListOfflineRegionsCallback) {
@@ -158,26 +149,21 @@ class OfflineManager private constructor(context: Context) {
/**
* Merge offline regions from a secondary database into the main offline database.
*
- *
* When the merge is completed, or fails, the [MergeOfflineRegionsCallback] will be invoked on the main thread.
* The callback reference is **strongly kept** throughout the process,
* so it needs to be wrapped in a weak reference or released on the client side if necessary.
*
- *
* The secondary database may need to be upgraded to the latest schema.
* This is done in-place and requires write-access to the provided path.
* If the app's process doesn't have write-access to the provided path,
* the file will be copied to the temporary, internal directory for the duration of the merge.
*
- *
* Only resources and tiles that belong to a region will be copied over. Identical
* regions will be flattened into a single new region in the main database.
*
- *
* The operation will be aborted and [MergeOfflineRegionsCallback.onError] with an appropriate message
* will be invoked if the merge would result in the offline tile count limit being exceeded.
*
- *
* Merged regions may not be in a completed status if the secondary database
* does not contain all the tiles or resources required by the region definition.
*
@@ -218,12 +204,10 @@ class OfflineManager private constructor(context: Context) {
/**
* Delete existing database and re-initialize.
*
- *
* When the operation is complete or encounters an error, the given callback will be
- * executed on the database thread; it is the responsibility of the SDK bindings
+ * executed on the database thread; it is the responsibility of the platform bindings
* to re-execute a user-provided callback on the main thread.
*
- *
* @param callback the callback to be invoked when the database was reset or when the operation erred.
*/
fun resetDatabase(callback: FileSourceCallback?) {
@@ -248,17 +232,13 @@ class OfflineManager private constructor(context: Context) {
/**
* Packs the existing database file into a minimal amount of disk space.
*
- *
* This operation has a performance impact as it will vacuum the database,
* forcing it to move pages on the filesystem.
*
- *
- *
* When the operation is complete or encounters an error, the given callback will be
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*
- *
* @param callback the callback to be invoked when the database was reset or when the operation erred.
*/
fun packDatabase(callback: FileSourceCallback?) {
@@ -283,18 +263,15 @@ class OfflineManager private constructor(context: Context) {
/**
* Forces re-validation of the ambient cache.
*
- *
- * Forces MapLibre GL Native to revalidate resources stored in the ambient
+ * Forces MapLibre Native to revalidate resources stored in the ambient
* cache with the tile server before using them, making sure they
* are the latest version. This is more efficient than cleaning the
* cache because if the resource is considered valid after the server
* lookup, it will not get downloaded again.
*
- *
* Resources overlapping with offline regions will not be affected
* by this call.
*
- *
* @param callback the callback to be invoked when the ambient cache was invalidated or when the operation erred.
*/
fun invalidateAmbientCache(callback: FileSourceCallback?) {
@@ -319,13 +296,10 @@ class OfflineManager private constructor(context: Context) {
/**
* Erase resources from the ambient cache, freeing storage space.
*
- *
* Erases the ambient cache, freeing resources.
* Note that this operation can be potentially slow if packing the database
* occurs automatically ([OfflineManager.runPackDatabaseAutomatically]).
*
- *
- *
* Resources overlapping with offline regions will not be affected
* by this call.
*
@@ -354,7 +328,6 @@ class OfflineManager private constructor(context: Context) {
/**
* Sets the maximum size in bytes for the ambient cache.
*
- *
* This call is potentially expensive because it will try
* to trim the data in case the database is larger than the
* size defined. The size of offline regions are not affected
@@ -362,25 +335,17 @@ class OfflineManager private constructor(context: Context) {
* to not exceed the maximum size defined, taking into account
* the current size for the offline regions.
*
- *
- *
* Note that if you use the SDK's offline functionality, your ability to set the ambient cache size will be limited.
* Space that offline regions take up detract from the space available for ambient caching, and the ambient cache
* size does not block offline downloads. For example: if the maximum cache size is set to 50 MB and 40 MB are
* already used by offline regions, the ambient cache size will effectively be 10 MB.
*
- *
- *
* Setting the size to 0 will disable the cache if there is no
* offline region on the database.
*
- * <[
- *
- *
* This method should always be called at the start of an app, before setting the style and loading a map.
* Otherwise, the map will instantiate with the default cache size of 50 MB.
*
- *
* @param size the maximum size of the ambient cache
* @param callback the callback to be invoked when the the maximum size has been set or when the operation erred.
*/
@@ -458,23 +423,13 @@ class OfflineManager private constructor(context: Context) {
* Creates an offline region in the database by downloading the resources needed to use
* the given region offline.
*
- *
- * As of version 8.3.0 of the Maps SDK for Android, offline tile requests are no longer exempt from
- * billing on mobile. Developers are subject to separate Vector Tile or Raster Tile API pricing for
- * offline use. See [our pricing page](https://www.mapbox.com/pricing/) for more information.
- *
- *
- *
* When the initial database queries have completed, the provided callback will be
* executed on the main thread.
*
- *
- *
* Note that the resulting region will be in an inactive download state; to begin
* downloading resources, call `OfflineRegion.setDownloadState(DownloadState.STATE_ACTIVE)`,
* optionally registering an `OfflineRegionObserver` beforehand.
*
- *
* @param definition the offline region definition
* @param metadata the metadata in bytes
* @param callback the callback to be invoked
@@ -521,15 +476,13 @@ class OfflineManager private constructor(context: Context) {
}
/**
- * Sets the maximum number of MapLibre-hosted tiles that may be downloaded and stored on the current device.
+ * Sets the maximum number of tiles that may be downloaded and stored on the current device.
* By default, the limit is set to 6,000.
*
- *
* Once this limit is reached, [OfflineRegion.OfflineRegionObserver.mapboxTileCountLimitExceeded]
* fires every additional attempt to download additional tiles until already downloaded tiles are removed
* by calling [OfflineRegion.delete].
*
- *
* @param limit the maximum number of tiles allowed to be downloaded
*/
@Keep
@@ -539,7 +492,6 @@ class OfflineManager private constructor(context: Context) {
* Sets whether database file packing occurs automatically.
* By default, the automatic database file packing is enabled.
*
- *
* If packing is enabled, database file packing occurs automatically
* after an offline region is deleted by calling
* [OfflineRegion.delete]
@@ -548,7 +500,6 @@ class OfflineManager private constructor(context: Context) {
* If packing is disabled, disk space will not be freed after
* resources are removed unless [OfflineManager.packDatabase] is explicitly called.
*
- *
* @param autopack flag setting the automatic database file packing.
*/
@@ -593,7 +544,6 @@ class OfflineManager private constructor(context: Context) {
* Use this method to pre-warm the cache with resources you know
* will be requested.
*
- *
* This call is asynchronous: the data may not be immediately available
* for in-progress requests, although subsequent requests should have
* access to the cached data.
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/org/maplibre/android/maps/MapGestureDetectorTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/org/maplibre/android/maps/MapGestureDetectorTest.kt
index ffeecb76e..2e66ab329 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/org/maplibre/android/maps/MapGestureDetectorTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/org/maplibre/android/maps/MapGestureDetectorTest.kt
@@ -187,7 +187,7 @@ class MapGestureDetectorTest : BaseTest() {
onView(withId(R.id.mapView)).perform(quickScale(-300f, withVelocity = false, duration = 750L))
rule.runOnUiThread {
- Assert.assertEquals(3.0, maplibreMap.cameraPosition.zoom, 0.0001)
+ Assert.assertEquals(3.0, maplibreMap.cameraPosition.zoom, 0.001)
}
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index 1b8d9d849..885a1a2ed 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -1,6 +1,6 @@
- MapLibre Android SDK TestApp
+ MapLibre Native Android TestApp
fps30
fps60
This is an empty Fragment
diff --git a/platform/android/gradle/publish-root.gradle b/platform/android/gradle/publish-root.gradle
index 467ecfa11..6bed2e9db 100644
--- a/platform/android/gradle/publish-root.gradle
+++ b/platform/android/gradle/publish-root.gradle
@@ -1,21 +1,6 @@
-ext["signing.keyId"] = ''
-ext["signing.password"] = ''
+ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID')
+ext["signing.password"] = System.getenv('SIGNING_PASSWORD')
ext["signing.secretKeyRingFile"] = "${projectDir}/../signing-key.gpg"
-ext["ossrhUsername"] = ''
-ext["ossrhPassword"] = ''
-ext["sonatypeStagingProfileId"] = ''
-
-File secretPropsFile = project.rootProject.file('local.properties')
-if (secretPropsFile.exists()) {
- // Read local.properties file first if it exists
- Properties p = new Properties()
- new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) }
- p.each { name, value -> ext[name] = value }
-} else {
- // Use system environment variables
- ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME')
- ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD')
- ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID')
- ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID')
- ext["signing.password"] = System.getenv('SIGNING_PASSWORD')
-}
+ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME')
+ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD')
+ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID')
diff --git a/platform/android/settings.gradle b/platform/android/settings.gradle
index c0315fed0..e4eae6064 100644
--- a/platform/android/settings.gradle
+++ b/platform/android/settings.gradle
@@ -1 +1,4 @@
-include ':MapboxGLAndroidSDK', ':MapboxGLAndroidSDKTestApp', ':MapboxGLAndroidSDKLint'
\ No newline at end of file
+include ':MapboxGLAndroidSDK', ':MapboxGLAndroidSDKTestApp', ':MapboxGLAndroidSDKLint'
+
+def renderTestProjectDir = new File(rootDir, '../../render-test/android')
+includeBuild(renderTestProjectDir)
\ No newline at end of file
diff --git a/render-test/android/app/build.gradle b/render-test/android/app/build.gradle
index 71f7fc24f..aa3ad60d9 100644
--- a/render-test/android/app/build.gradle
+++ b/render-test/android/app/build.gradle
@@ -12,7 +12,7 @@ android {
abi = project.getProperty('mapbox.abis')
}
ndk {
- if (abi != 'all') {
+ if (abi != 'all' && abi != 'none') {
abiFilters abi.split(' ')
} else {
abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a', 'x86_64'
diff --git a/render-test/android/build.gradle b/render-test/android/build.gradle
index 7d6076b86..c763096e6 100644
--- a/render-test/android/build.gradle
+++ b/render-test/android/build.gradle
@@ -4,7 +4,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:8.0.2'
+ classpath 'com.android.tools.build:gradle:8.1.4'
}
}
diff --git a/render-test/android/settings.gradle b/render-test/android/settings.gradle
index 573abcb32..ae45cfc13 100644
--- a/render-test/android/settings.gradle
+++ b/render-test/android/settings.gradle
@@ -1,2 +1,3 @@
-include ':app'
+rootProject.name = "androidRenderTest"
+include ":app"
\ No newline at end of file