Skip to content

Commit

Permalink
FENCE-1788: Add FOREGROUND_SERVICE_LOCATION permission (#348)
Browse files Browse the repository at this point in the history
* add FOREGROUND_SERVICE_LOCATION

* bump

* Update config.yml

* Update config.yml

* upgrade gradle

* trying again

* Update gradle-wrapper.properties

* test

* Update build.gradle

* Update build.gradle

Update config.yml

Update config.yml

upgrade gradle

trying again

Update gradle-wrapper.properties

test

* Revert "Update build.gradle"

This reverts commit d5b32e1.

* Revert "Update build.gradle"

This reverts commit d5b32e1.

* bump ci

* bump ci

* should work now

* test

* Update build.gradle

* Update config.yml

* [WIP] FG service spiking (#349)

* Get synced geofences

* beta.3

* Stop FG service after 5s delay

* Revert "Get synced geofences"

This reverts commit 4c26d92.

* 3.9.8-beta.4

* send geofence broadcasts right away

* 'Fix RadarLocationManager to not remove bubble geofence when moving and updateTracking called from updateTrackingFromMeta

* Match formatting to stopped geofence

---------

Co-authored-by: Tim Julien <[email protected]>

* 3.9.8-beta.8

* add blocks when removing geofences

* make block optional

* make block optional

* make block optional

* make block optional

* add bubble geofences after remove bubble completes

* add synched geofences after remove synced completes

* adding back handleLocation()

* beta.9

* Formatting nit

* Try sending background locations immediately

* Beta.10

* Revert "Try sending background locations immediately"

This reverts commit 90533c0.

* 3.9.8

---------

Co-authored-by: Liam Meier <[email protected]>
Co-authored-by: Tim Julien <[email protected]>
  • Loading branch information
3 people authored Mar 23, 2024
1 parent 2b77fbd commit cf886e6
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 43 deletions.
3 changes: 2 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = "1.5.21"
ext.kotlin_version = "1.6.20"
repositories {
google()
mavenCentral()
Expand All @@ -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"
}
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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
12 changes: 6 additions & 6 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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()}"
Expand All @@ -29,7 +29,7 @@ if (githubRelease) {
}

android {
compileSdkVersion 31
compileSdkVersion 34
compileOptions {
coreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
Expand All @@ -40,7 +40,7 @@ android {
}
defaultConfig {
minSdkVersion 16
targetSdkVersion 31
targetSdkVersion 34
buildConfigField "String", "VERSION_NAME", "\"$radarVersion\""
multiDexEnabled = true
}
Expand All @@ -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"
}
Expand Down
1 change: 1 addition & 0 deletions sdk/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />

<application>
<receiver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ internal abstract class RadarAbstractLocationClient() {
)

abstract fun removeGeofences(
pendingIntent: PendingIntent
pendingIntent: PendingIntent,
block: ((success: Boolean) -> Unit)?
)

abstract fun getLocationFromGeofenceIntent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
9 changes: 8 additions & 1 deletion sdk/src/main/java/io/radar/sdk/RadarForegroundService.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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? {
Expand Down
12 changes: 10 additions & 2 deletions sdk/src/main/java/io/radar/sdk/RadarGoogleLocationClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down
12 changes: 10 additions & 2 deletions sdk/src/main/java/io/radar/sdk/RadarHuaweiLocationClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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? {
Expand Down
60 changes: 42 additions & 18 deletions sdk/src/main/java/io/radar/sdk/RadarLocationManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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()
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -341,8 +347,12 @@ internal class RadarLocationManager(
}

private fun replaceSyncedGeofences(radarGeofences: Array<RadarGeofence>?) {
this.removeSyncedGeofences()
this.removeSyncedGeofences() { success ->
this.addSyncedGeofences(radarGeofences)
}
}

private fun addSyncedGeofences(radarGeofences: Array<RadarGeofence>?) {
val options = Radar.getTrackingOptions()
if (!options.syncGeofences || radarGeofences == null) {
return
Expand Down Expand Up @@ -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() {
Expand Down
8 changes: 2 additions & 6 deletions sdk/src/main/java/io/radar/sdk/RadarLocationReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/main/java/io/radar/sdk/RadarNotificationHelper.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.radar.sdk

import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
Expand All @@ -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<RadarEvent>) {
if (Build.VERSION.SDK_INT < 26) {
return
Expand Down
4 changes: 3 additions & 1 deletion sdk/src/main/java/io/radar/sdk/model/RadarRegion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ internal class RadarMockLocationProvider() : RadarAbstractLocationClient() {

}

override fun removeGeofences(pendingIntent: PendingIntent) {
override fun removeGeofences(pendingIntent: PendingIntent, block: ((success: Boolean) -> Unit)?) {

}

Expand Down

0 comments on commit cf886e6

Please sign in to comment.