Skip to content

Commit 2edef46

Browse files
author
Martin Dinh
committed
Merge branch '16-fix-outofmemoryerror-in-locationprovider' into 'master'
Resolve "Fix OutOfMemoryError in LocationProvider" Closes #16 See merge request pace/mobile/android/pace-cloud-sdk!13
2 parents fd46d9f + d794591 commit 2edef46

File tree

18 files changed

+163
-115
lines changed

18 files changed

+163
-115
lines changed

app/src/main/java/cloud/pace/sdk/app/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,6 @@ class MainActivity : AppCompatActivity() {
199199
private const val AUTHORIZE_CODE = 100
200200
private const val PAYMENT_APP_URL = "YOUR_PAYMENT_APP_URL" // TODO: Replace with your payment app URL
201201
private const val FUELING_APP_URL = "YOUR_FUELING_APP_URL" // TODO: Replace with your fueling app URL
202-
private const val APP_DISTANCE_THRESHOLD = 200
202+
private const val APP_DISTANCE_THRESHOLD = 15
203203
}
204204
}

library/src/main/java/cloud/pace/sdk/appkit/AppKit.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import cloud.pace.sdk.appkit.model.App
1212
import cloud.pace.sdk.appkit.model.Car
1313
import cloud.pace.sdk.appkit.model.Configuration
1414
import cloud.pace.sdk.appkit.persistence.SharedPreferencesModel
15+
import cloud.pace.sdk.utils.AppKitKoinComponent
1516
import cloud.pace.sdk.utils.Completion
16-
import cloud.pace.sdk.utils.CustomKoinComponent
1717
import cloud.pace.sdk.utils.KoinConfig
1818
import org.koin.core.inject
1919

20-
object AppKit : CustomKoinComponent {
20+
object AppKit : AppKitKoinComponent {
2121

2222
private val sharedPreferencesModel: SharedPreferencesModel by inject()
2323
private val appManager: AppManager by inject()
@@ -44,8 +44,8 @@ object AppKit : CustomKoinComponent {
4444
)
4545
)
4646

47+
KoinConfig.setupAppKit(context)
4748
setUserAgent(configuration)
48-
KoinConfig.setup(context, configuration.environment, configuration.deviceId)
4949
sharedPreferencesModel.deleteAllAppStates()
5050
}
5151

library/src/main/java/cloud/pace/sdk/appkit/AppManager.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ import java.net.MalformedURLException
2828
import java.net.URL
2929
import java.util.*
3030

31-
internal class AppManager(private val context: Context) : CustomKoinComponent {
31+
internal class AppManager : AppKitKoinComponent {
3232

33+
private val context: Context by inject()
3334
private val appLocationManager: AppLocationManager by inject()
3435
private val appRepository: AppRepository by inject()
3536
private val networkChangeListener: NetworkChangeListener by inject()
@@ -50,7 +51,7 @@ internal class AppManager(private val context: Context) : CustomKoinComponent {
5051
}
5152
checkRunning = true
5253

53-
appLocationManager.getLocation { result ->
54+
appLocationManager.start { result ->
5455
result.onSuccess {
5556
getAppsByLocation(it, completion)
5657
}

library/src/main/java/cloud/pace/sdk/appkit/app/AppActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import cloud.pace.sdk.R
77
import cloud.pace.sdk.appkit.app.webview.AppWebViewClient
88
import cloud.pace.sdk.appkit.communication.AppEventManager
99
import cloud.pace.sdk.appkit.communication.AppModel
10-
import cloud.pace.sdk.utils.CustomKoinComponent
10+
import cloud.pace.sdk.utils.AppKitKoinComponent
1111
import kotlinx.android.synthetic.main.fragment_app.*
1212
import org.koin.android.ext.android.inject
1313

14-
class AppActivity : AppCompatActivity(), CustomKoinComponent {
14+
class AppActivity : AppCompatActivity(), AppKitKoinComponent {
1515

1616
private var backToFinish = true
1717
private val eventManager: AppEventManager by inject()

library/src/main/java/cloud/pace/sdk/appkit/app/AppFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import androidx.browser.customtabs.CustomTabsIntent
99
import androidx.fragment.app.Fragment
1010
import cloud.pace.sdk.R
1111
import cloud.pace.sdk.appkit.app.webview.AppWebViewClient
12-
import cloud.pace.sdk.utils.CustomKoinComponent
12+
import cloud.pace.sdk.utils.AppKitKoinComponent
1313
import kotlinx.android.synthetic.main.fragment_app.*
1414
import org.koin.android.viewmodel.ext.android.viewModel
1515

16-
class AppFragment : Fragment(), CustomKoinComponent {
16+
class AppFragment : Fragment(), AppKitKoinComponent {
1717

1818
private val viewModel: AppFragmentViewModel by viewModel()
1919

library/src/main/java/cloud/pace/sdk/appkit/app/drawer/AppDrawer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ import androidx.constraintlayout.widget.ConstraintLayout
1818
import androidx.lifecycle.Observer
1919
import cloud.pace.sdk.R
2020
import cloud.pace.sdk.appkit.model.App
21-
import cloud.pace.sdk.utils.CustomKoinComponent
21+
import cloud.pace.sdk.utils.AppKitKoinComponent
2222
import cloud.pace.sdk.utils.Event
2323
import cloud.pace.sdk.utils.dp
2424
import kotlinx.android.synthetic.main.app_drawer.view.*
2525
import org.koin.core.inject
2626

27-
class AppDrawer(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs), CustomKoinComponent {
27+
class AppDrawer(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs), AppKitKoinComponent {
2828

2929
private val viewModel: AppDrawerViewModel by inject()
3030
private val minBackgroundWidth = context.resources.getDimension(R.dimen.app_drawer_height).toInt()

library/src/main/java/cloud/pace/sdk/appkit/app/webview/AppWebView.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import cloud.pace.sdk.R
1515
import cloud.pace.sdk.appkit.AppKit
1616
import cloud.pace.sdk.appkit.model.AuthenticationMode
1717
import cloud.pace.sdk.appkit.utils.BiometricUtils
18-
import cloud.pace.sdk.utils.CustomKoinComponent
18+
import cloud.pace.sdk.utils.AppKitKoinComponent
1919
import cloud.pace.sdk.utils.Event
2020
import kotlinx.android.synthetic.main.app_web_view.view.*
2121
import org.koin.core.inject
2222

23-
class AppWebView(context: Context, attributeSet: AttributeSet) : RelativeLayout(context, attributeSet), CustomKoinComponent {
23+
class AppWebView(context: Context, attributeSet: AttributeSet) : RelativeLayout(context, attributeSet), AppKitKoinComponent {
2424

2525
private val webViewModel: AppWebViewModel by inject()
2626
private var fragment: Fragment? = null

library/src/main/java/cloud/pace/sdk/appkit/geofences/GeofenceBroadcastReceiver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package cloud.pace.sdk.appkit.geofences
33
import android.content.BroadcastReceiver
44
import android.content.Context
55
import android.content.Intent
6-
import cloud.pace.sdk.utils.CustomKoinComponent
6+
import cloud.pace.sdk.utils.AppKitKoinComponent
77
import com.google.android.gms.location.GeofencingEvent
88
import org.koin.core.inject
99

@@ -16,7 +16,7 @@ class GeofenceBroadcastReceiver : BroadcastReceiver() {
1616
}
1717
}
1818

19-
class BroadcastReceiverHelper : CustomKoinComponent {
19+
class BroadcastReceiverHelper : AppKitKoinComponent {
2020

2121
private val eventCallback: GeofenceCallback by inject()
2222

library/src/main/java/cloud/pace/sdk/appkit/geofences/GeofenceManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import androidx.lifecycle.Lifecycle
88
import androidx.lifecycle.ProcessLifecycleOwner
99
import cloud.pace.sdk.R
1010
import cloud.pace.sdk.appkit.utils.NotificationUtils
11-
import cloud.pace.sdk.utils.CustomKoinComponent
11+
import cloud.pace.sdk.utils.AppKitKoinComponent
1212
import cloud.pace.sdk.utils.Log
1313
import com.google.android.gms.location.Geofence
1414
import com.google.android.gms.location.GeofencingClient
@@ -17,7 +17,7 @@ import com.google.android.gms.location.GeofencingRequest
1717
import org.koin.core.inject
1818
import java.util.*
1919

20-
abstract class GeofenceManager : CustomKoinComponent {
20+
abstract class GeofenceManager : AppKitKoinComponent {
2121

2222
abstract fun enable(locations: List<GeofenceLocation>, callback: (event: GeofencingEvent) -> Unit, setupCallback: (Result<Void>) -> Unit = {})
2323

library/src/main/java/cloud/pace/sdk/appkit/location/AppLocationManager.kt

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cloud.pace.sdk.appkit.location
22

33
import android.location.Location
4+
import android.os.Handler
5+
import androidx.lifecycle.Observer
46
import cloud.pace.sdk.appkit.AppKit
57
import cloud.pace.sdk.appkit.utils.NoLocationFound
68
import cloud.pace.sdk.appkit.utils.PermissionDenied
@@ -11,44 +13,53 @@ import cloud.pace.sdk.utils.SystemManager
1113

1214
interface AppLocationManager {
1315

14-
fun getLocation(callback: (Result<Location>) -> Unit)
16+
fun start(callback: (Result<Location>) -> Unit)
17+
fun stop()
1518
}
1619

1720
class AppLocationManagerImpl(
1821
private val locationProvider: LocationProvider,
1922
private val systemManager: SystemManager
2023
) : AppLocationManager {
2124

22-
override fun getLocation(callback: (Result<Location>) -> Unit) {
23-
val startTime = systemManager.getCurrentTimeMillis()
24-
val handler = systemManager.getHandler()
25-
val locationTimeoutRunnable = Runnable {
25+
private var callback: ((Result<Location>) -> Unit)? = null
26+
private var startTime = 0L
27+
private val handler: Handler by lazy { systemManager.getHandler() }
28+
private val locationTimeoutRunnable: Runnable by lazy {
29+
Runnable {
2630
Log.w("AppLocationManager timeout after $LOCATION_TIMEOUT ms")
27-
callback(Result.failure(NoLocationFound))
31+
callback?.invoke(Result.failure(NoLocationFound))
2832
}
29-
handler.postDelayed(locationTimeoutRunnable, LOCATION_TIMEOUT)
30-
31-
locationProvider.location.observeForever {
33+
}
34+
private val locationObserver: Observer<Location> by lazy {
35+
Observer<Location> {
3236
if (isLocationValid(it, startTime)) {
33-
locationProvider.removeLocationUpdates()
34-
handler.removeCallbacks(locationTimeoutRunnable)
35-
callback(Result.success(it))
37+
callback?.invoke(Result.success(it))
38+
stop()
3639
}
3740
}
38-
39-
locationProvider.locationState.observeForever {
41+
}
42+
private val locationStateObserver: Observer<LocationState> by lazy {
43+
Observer<LocationState> {
4044
if (it == LocationState.PERMISSION_DENIED) {
41-
locationProvider.removeLocationUpdates()
42-
handler.removeCallbacks(locationTimeoutRunnable)
43-
callback(Result.failure(PermissionDenied))
45+
callback?.invoke(Result.failure(PermissionDenied))
46+
stop()
4447
} else if (it == LocationState.NO_LOCATION_FOUND) {
45-
locationProvider.removeLocationUpdates()
46-
handler.removeCallbacks(locationTimeoutRunnable)
47-
callback(Result.failure(NoLocationFound))
48+
callback?.invoke(Result.failure(NoLocationFound))
49+
stop()
4850
}
4951
}
52+
}
5053

51-
locationProvider.requestLocationUpdates()
54+
override fun start(callback: (Result<Location>) -> Unit) {
55+
this.callback = callback
56+
startTime = systemManager.getCurrentTimeMillis()
57+
handler.postDelayed(locationTimeoutRunnable, LOCATION_TIMEOUT)
58+
locationProvider.apply {
59+
location.observeForever(locationObserver)
60+
locationState.observeForever(locationStateObserver)
61+
requestLocationUpdates()
62+
}
5263
}
5364

5465
private fun isLocationValid(location: Location?, startTime: Long): Boolean {
@@ -86,6 +97,15 @@ class AppLocationManagerImpl(
8697
}
8798
}
8899

100+
override fun stop() {
101+
handler.removeCallbacks(locationTimeoutRunnable)
102+
locationProvider.apply {
103+
location.removeObserver(locationObserver)
104+
locationState.removeObserver(locationStateObserver)
105+
removeLocationUpdates()
106+
}
107+
}
108+
89109
companion object {
90110
private const val LOCATION_TIMEOUT = 30 * 1000L // 30sec
91111
private const val LOCATION_SEGMENTS = 5

0 commit comments

Comments
 (0)