diff --git a/.circleci/config.yml b/.circleci/config.yml
index 13f201bf0..e48c963cf 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,7 +3,8 @@ jobs:
build_and_test:
working_directory: ~/sdk
docker:
- - image: circleci/android:api-30
+ - image: cimg/android:2023.07
+ resource_class: large
steps:
- checkout
- run:
diff --git a/build.gradle b/build.gradle
index 2cca7b3f3..d921a36d5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = "1.5.21"
+ ext.kotlin_version = "1.6.20"
repositories {
google()
mavenCentral()
@@ -8,7 +8,7 @@ buildscript {
}
}
dependencies {
- classpath "com.android.tools.build:gradle:4.2.2"
+ classpath "com.android.tools.build:gradle:7.4.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.32"
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 9c953e830..db4181846 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Wed May 26 11:05:21 EDT 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
diff --git a/sdk/build.gradle b/sdk/build.gradle
index f7ae41fe3..1135216fa 100644
--- a/sdk/build.gradle
+++ b/sdk/build.gradle
@@ -10,7 +10,7 @@ apply plugin: "org.jetbrains.dokka"
apply plugin: 'io.radar.mvnpublish'
ext {
- radarVersion = '3.9.7'
+ radarVersion = '3.9.8'
}
String buildNumber = ".${System.currentTimeMillis()}"
@@ -29,7 +29,7 @@ if (githubRelease) {
}
android {
- compileSdkVersion 31
+ compileSdkVersion 34
compileOptions {
coreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
@@ -40,7 +40,7 @@ android {
}
defaultConfig {
minSdkVersion 16
- targetSdkVersion 31
+ targetSdkVersion 34
buildConfigField "String", "VERSION_NAME", "\"$radarVersion\""
multiDexEnabled = true
}
@@ -62,15 +62,15 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
- coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
+ coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.appcompat:appcompat:1.4.0"
implementation "androidx.core:core-ktx:1.7.0"
implementation "com.google.android.gms:play-services-location:21.0.1"
compileOnly "com.huawei.hms:location:6.4.0.300"
compileOnly "com.google.android.play:integrity:1.2.0"
- testImplementation "androidx.test.ext:junit:1.1.3"
- testImplementation "org.robolectric:robolectric:4.5.1"
+ testImplementation "androidx.test.ext:junit:1.1.5"
+ testImplementation "org.robolectric:robolectric:4.10"
testImplementation 'org.json:json:20211205'
testImplementation "com.google.android.play:integrity:1.2.0"
}
diff --git a/sdk/src/main/AndroidManifest.xml b/sdk/src/main/AndroidManifest.xml
index e139781e4..f7a3fb413 100644
--- a/sdk/src/main/AndroidManifest.xml
+++ b/sdk/src/main/AndroidManifest.xml
@@ -8,6 +8,7 @@
+
Unit)?
)
abstract fun getLocationFromGeofenceIntent(
diff --git a/sdk/src/main/java/io/radar/sdk/RadarActivityLifecycleCallbacks.kt b/sdk/src/main/java/io/radar/sdk/RadarActivityLifecycleCallbacks.kt
index accef3215..838156de8 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarActivityLifecycleCallbacks.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarActivityLifecycleCallbacks.kt
@@ -72,7 +72,7 @@ internal class RadarActivityLifecycleCallbacks(
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
try {
val inputDevice = InputDevice.getDevice(event.deviceId)
- if (event.getToolType(0) == MotionEvent.TOOL_TYPE_UNKNOWN || inputDevice.isVirtual) {
+ if (event.getToolType(0) == MotionEvent.TOOL_TYPE_UNKNOWN || inputDevice?.isVirtual == true) {
RadarSettings.setSharing(activity.applicationContext, true)
}
} catch (e: Exception) {
diff --git a/sdk/src/main/java/io/radar/sdk/RadarForegroundService.kt b/sdk/src/main/java/io/radar/sdk/RadarForegroundService.kt
index 283039846..186cb0b36 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarForegroundService.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarForegroundService.kt
@@ -1,7 +1,9 @@
package io.radar.sdk
+import android.annotation.SuppressLint
import android.app.*
import android.content.Intent
+import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
import android.graphics.Color
import android.os.Build
import android.os.Bundle
@@ -47,6 +49,7 @@ class RadarForegroundService : Service() {
return START_STICKY
}
+ @SuppressLint("DiscouragedApi")
private fun startForegroundService(extras: Bundle?) {
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
manager.deleteNotificationChannel("RadarSDK")
@@ -94,7 +97,11 @@ class RadarForegroundService : Service() {
logger.e("Error setting foreground service content intent", RadarLogType.SDK_EXCEPTION, e)
}
val notification = builder.build()
- startForeground(id, notification)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ startForeground(id, notification, FOREGROUND_SERVICE_TYPE_LOCATION);
+ } else {
+ startForeground(id, notification)
+ }
}
override fun onBind(intent: Intent): IBinder? {
diff --git a/sdk/src/main/java/io/radar/sdk/RadarGoogleLocationClient.kt b/sdk/src/main/java/io/radar/sdk/RadarGoogleLocationClient.kt
index 0ee1ee9ae..9adfba519 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarGoogleLocationClient.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarGoogleLocationClient.kt
@@ -125,9 +125,17 @@ internal class RadarGoogleLocationClient(
}
override fun removeGeofences(
- pendingIntent: PendingIntent
+ pendingIntent: PendingIntent,
+ block: ((success: Boolean) -> Unit)?
) {
- geofencingClient.removeGeofences(pendingIntent)
+ geofencingClient.removeGeofences(pendingIntent).run {
+ addOnSuccessListener {
+ block?.invoke(true)
+ }
+ addOnFailureListener {
+ block?.invoke(false)
+ }
+ }
}
private fun priorityForDesiredAccuracy(desiredAccuracy: RadarTrackingOptions.RadarTrackingOptionsDesiredAccuracy) =
diff --git a/sdk/src/main/java/io/radar/sdk/RadarHuaweiLocationClient.kt b/sdk/src/main/java/io/radar/sdk/RadarHuaweiLocationClient.kt
index ec82b479b..51a36ceb4 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarHuaweiLocationClient.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarHuaweiLocationClient.kt
@@ -135,9 +135,17 @@ internal class RadarHuaweiLocationClient(
}
override fun removeGeofences(
- pendingIntent: PendingIntent
+ pendingIntent: PendingIntent,
+ block: ((success: Boolean) -> Unit)?
) {
- geofenceService.deleteGeofenceList(pendingIntent)
+ geofenceService.deleteGeofenceList(pendingIntent).run {
+ addOnSuccessListener {
+ block?.invoke(true)
+ }
+ addOnFailureListener {
+ block?.invoke(false)
+ }
+ }
}
override fun getLocationFromGeofenceIntent(intent: Intent): Location? {
diff --git a/sdk/src/main/java/io/radar/sdk/RadarLocationManager.kt b/sdk/src/main/java/io/radar/sdk/RadarLocationManager.kt
index 11213db37..ad03e1e5f 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarLocationManager.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarLocationManager.kt
@@ -5,6 +5,8 @@ import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.location.Location
+import android.os.Handler
+import android.os.Looper
import android.os.Build
import io.radar.sdk.Radar.RadarLocationCallback
import io.radar.sdk.Radar.RadarLocationServicesProvider.HUAWEI
@@ -191,10 +193,7 @@ internal class RadarLocationManager(
if (!foregroundService.updatesOnly) {
this.startForegroundService(foregroundService)
}
- } else if (RadarForegroundService.started) {
- this.stopForegroundService()
}
-
val stopped = RadarState.getStopped(context)
if (stopped) {
if (options.desiredStoppedUpdateInterval == 0) {
@@ -217,14 +216,21 @@ internal class RadarLocationManager(
this.startLocationUpdates(options.desiredAccuracy, options.desiredMovingUpdateInterval, options.fastestMovingUpdateInterval)
}
- if (options.useMovingGeofence && location != null) {
- this.replaceBubbleGeofence(location, false)
+ if (options.useMovingGeofence) {
+ if (location != null) {
+ this.replaceBubbleGeofence(location, false)
+ }
} else {
this.removeBubbleGeofences()
}
}
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !options.foregroundServiceEnabled && RadarForegroundService.started) {
+ Handler(Looper.getMainLooper()).postDelayed({
+ this.stopForegroundService()
+ }, 5000)
+ }
} else {
- if (RadarForegroundService.started) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && RadarForegroundService.started) {
this.stopForegroundService()
}
this.stopLocationUpdates()
@@ -271,13 +277,13 @@ internal class RadarLocationManager(
return locationClient.getLocationFromLocationIntent(intent)
}
- private fun replaceBubbleGeofence(location: Location?, stopped: Boolean) {
- if (location == null) {
- return
+ private fun replaceBubbleGeofence(location: Location, stopped: Boolean) {
+ this.removeBubbleGeofences() { success ->
+ this.addBubbleGeofence(location, stopped)
}
+ }
- this.removeBubbleGeofences()
-
+ private fun addBubbleGeofence(location: Location, stopped: Boolean) {
val options = Radar.getTrackingOptions()
if (stopped && options.useStoppedGeofence) {
@@ -341,8 +347,12 @@ internal class RadarLocationManager(
}
private fun replaceSyncedGeofences(radarGeofences: Array?) {
- this.removeSyncedGeofences()
+ this.removeSyncedGeofences() { success ->
+ this.addSyncedGeofences(radarGeofences)
+ }
+ }
+ private fun addSyncedGeofences(radarGeofences: Array?) {
val options = Radar.getTrackingOptions()
if (!options.syncGeofences || radarGeofences == null) {
return
@@ -398,14 +408,28 @@ internal class RadarLocationManager(
}
}
- private fun removeBubbleGeofences() {
- locationClient.removeGeofences(RadarLocationReceiver.getBubbleGeofencePendingIntent(context))
- logger.d("Removed bubble geofences")
+ private fun removeBubbleGeofences(block: ((success: Boolean) -> Unit)? = null) {
+ locationClient.removeGeofences(RadarLocationReceiver.getBubbleGeofencePendingIntent(context)) { success ->
+ if (success) {
+ logger.d("Removed bubble geofences")
+ block?.invoke(true)
+ } else {
+ logger.d("Error removing bubble geofences")
+ block?.invoke(false)
+ }
+ }
}
- private fun removeSyncedGeofences() {
- locationClient.removeGeofences(RadarLocationReceiver.getSyncedGeofencesPendingIntent(context))
- logger.d("Removed synced geofences")
+ private fun removeSyncedGeofences(block: ((success: Boolean) -> Unit)? = null) {
+ locationClient.removeGeofences(RadarLocationReceiver.getSyncedGeofencesPendingIntent(context)) { success ->
+ if (success) {
+ logger.d("Removed synced geofences")
+ block?.invoke(true)
+ } else {
+ logger.d("Error removing synced geofences")
+ block?.invoke(false)
+ }
+ }
}
private fun removeAllGeofences() {
diff --git a/sdk/src/main/java/io/radar/sdk/RadarLocationReceiver.kt b/sdk/src/main/java/io/radar/sdk/RadarLocationReceiver.kt
index 6d8bee496..2b1ffd7f2 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarLocationReceiver.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarLocationReceiver.kt
@@ -113,11 +113,7 @@ class RadarLocationReceiver : BroadcastReceiver() {
return
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !RadarForegroundService.started) {
- RadarJobScheduler.scheduleJob(context, location, source)
- } else {
- Radar.handleLocation(context, location, source)
- }
+ Radar.handleLocation(context, location, source)
}
ACTION_LOCATION -> {
val location = Radar.locationManager.getLocationFromLocationIntent(intent)
@@ -127,7 +123,7 @@ class RadarLocationReceiver : BroadcastReceiver() {
return
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !RadarForegroundService.started) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !RadarForegroundService.started) {
RadarJobScheduler.scheduleJob(context, location, source)
} else {
Radar.handleLocation(context, location, source)
diff --git a/sdk/src/main/java/io/radar/sdk/RadarNotificationHelper.kt b/sdk/src/main/java/io/radar/sdk/RadarNotificationHelper.kt
index 0bd0cf608..642d0f14d 100644
--- a/sdk/src/main/java/io/radar/sdk/RadarNotificationHelper.kt
+++ b/sdk/src/main/java/io/radar/sdk/RadarNotificationHelper.kt
@@ -1,5 +1,6 @@
package io.radar.sdk
+import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
@@ -17,6 +18,7 @@ class RadarNotificationHelper {
private const val CHANNEL_NAME = "Location"
private const val NOTIFICATION_ID = 20160525 // Radar's birthday!
+ @SuppressLint("DiscouragedApi")
internal fun showNotifications(context: Context, events: Array) {
if (Build.VERSION.SDK_INT < 26) {
return
diff --git a/sdk/src/main/java/io/radar/sdk/model/RadarRegion.kt b/sdk/src/main/java/io/radar/sdk/model/RadarRegion.kt
index 1ee32b7fa..c31a16921 100644
--- a/sdk/src/main/java/io/radar/sdk/model/RadarRegion.kt
+++ b/sdk/src/main/java/io/radar/sdk/model/RadarRegion.kt
@@ -115,7 +115,9 @@ class RadarRegion(
obj.putOpt(FIELD_PASSED, this.passed)
obj.putOpt(FIELD_IN_EXCLUSION_ZONE, this.inExclusionZone)
obj.putOpt(FIELD_IN_BUFFER_ZONE, this.inBufferZone)
- obj.putOpt(FIELD_DISTANCE_TO_BORDER, this.distanceToBorder)
+ if (!this.distanceToBorder.isNaN()) {
+ obj.putOpt(FIELD_DISTANCE_TO_BORDER, this.distanceToBorder)
+ }
return obj
}
diff --git a/sdk/src/test/java/io/radar/sdk/RadarMockLocationProvider.kt b/sdk/src/test/java/io/radar/sdk/RadarMockLocationProvider.kt
index 5e094d896..5eab219b0 100644
--- a/sdk/src/test/java/io/radar/sdk/RadarMockLocationProvider.kt
+++ b/sdk/src/test/java/io/radar/sdk/RadarMockLocationProvider.kt
@@ -41,7 +41,7 @@ internal class RadarMockLocationProvider() : RadarAbstractLocationClient() {
}
- override fun removeGeofences(pendingIntent: PendingIntent) {
+ override fun removeGeofences(pendingIntent: PendingIntent, block: ((success: Boolean) -> Unit)?) {
}