Wrap location API in coroutines
up vote
1
down vote
favorite
In my app I need to query location and scan wifi periodically. To conserve power I need to change the rate dynamically, depending on the distance to the target. Also I want to wait for both asynchronous calls to complete. Coroutines seemed the obvious choice, but since this is my first take at coroutines I want to have a second opinion.
I came up with the following solution:
@SuppressLint("MissingPermission")
suspend fun getCurrentLocation(context: Context): Location? = suspendCoroutine { cont ->
val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
val locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.numUpdates = 1
val listener = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
cont.resume(locationResult?.lastLocation)
}
}
val task = fusedLocationProviderClient.requestLocationUpdates(locationRequest,
listener,
null)
task.addOnFailureListener { cont.resumeWithException(it) }
}
also
class WifiScanner(val context: ContextWrapper) {
val wifiManager: WifiManager
init {
wifiManager = context.baseContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
}
suspend fun getCurrentScanResult(): List<ScanResult> =
suspendCoroutine { cont ->
val wifiScanReceiver = object : BroadcastReceiver() {
override fun onReceive(c: Context, intent: Intent) {
if (intent.action?.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) == true) {
val scanResults = wifiManager.scanResults
//sort so that strongest signal is on top
scanResults.sortByDescending { it.level }
Log.i("received wifi", scanResults.toString())
context.unregisterReceiver(this)
cont.resume(scanResults)
}
}
}
context.registerReceiver(wifiScanReceiver,
IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
wifiManager.startScan()
}
}
Both are executed concurrently like this:
val location = async { getCurrentLocation() }
val wifi = async { wifiScanner.getCurrentScanResult() }
val currentLocation = location.await()
val currentWifiInfo = wifi.await()
In a quick test it works fine, but it feels like abusing the system. Can I use this like that without breaking the common conventions?
android asynchronous networking geospatial kotlin
add a comment |
up vote
1
down vote
favorite
In my app I need to query location and scan wifi periodically. To conserve power I need to change the rate dynamically, depending on the distance to the target. Also I want to wait for both asynchronous calls to complete. Coroutines seemed the obvious choice, but since this is my first take at coroutines I want to have a second opinion.
I came up with the following solution:
@SuppressLint("MissingPermission")
suspend fun getCurrentLocation(context: Context): Location? = suspendCoroutine { cont ->
val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
val locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.numUpdates = 1
val listener = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
cont.resume(locationResult?.lastLocation)
}
}
val task = fusedLocationProviderClient.requestLocationUpdates(locationRequest,
listener,
null)
task.addOnFailureListener { cont.resumeWithException(it) }
}
also
class WifiScanner(val context: ContextWrapper) {
val wifiManager: WifiManager
init {
wifiManager = context.baseContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
}
suspend fun getCurrentScanResult(): List<ScanResult> =
suspendCoroutine { cont ->
val wifiScanReceiver = object : BroadcastReceiver() {
override fun onReceive(c: Context, intent: Intent) {
if (intent.action?.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) == true) {
val scanResults = wifiManager.scanResults
//sort so that strongest signal is on top
scanResults.sortByDescending { it.level }
Log.i("received wifi", scanResults.toString())
context.unregisterReceiver(this)
cont.resume(scanResults)
}
}
}
context.registerReceiver(wifiScanReceiver,
IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
wifiManager.startScan()
}
}
Both are executed concurrently like this:
val location = async { getCurrentLocation() }
val wifi = async { wifiScanner.getCurrentScanResult() }
val currentLocation = location.await()
val currentWifiInfo = wifi.await()
In a quick test it works fine, but it feels like abusing the system. Can I use this like that without breaking the common conventions?
android asynchronous networking geospatial kotlin
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
In my app I need to query location and scan wifi periodically. To conserve power I need to change the rate dynamically, depending on the distance to the target. Also I want to wait for both asynchronous calls to complete. Coroutines seemed the obvious choice, but since this is my first take at coroutines I want to have a second opinion.
I came up with the following solution:
@SuppressLint("MissingPermission")
suspend fun getCurrentLocation(context: Context): Location? = suspendCoroutine { cont ->
val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
val locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.numUpdates = 1
val listener = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
cont.resume(locationResult?.lastLocation)
}
}
val task = fusedLocationProviderClient.requestLocationUpdates(locationRequest,
listener,
null)
task.addOnFailureListener { cont.resumeWithException(it) }
}
also
class WifiScanner(val context: ContextWrapper) {
val wifiManager: WifiManager
init {
wifiManager = context.baseContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
}
suspend fun getCurrentScanResult(): List<ScanResult> =
suspendCoroutine { cont ->
val wifiScanReceiver = object : BroadcastReceiver() {
override fun onReceive(c: Context, intent: Intent) {
if (intent.action?.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) == true) {
val scanResults = wifiManager.scanResults
//sort so that strongest signal is on top
scanResults.sortByDescending { it.level }
Log.i("received wifi", scanResults.toString())
context.unregisterReceiver(this)
cont.resume(scanResults)
}
}
}
context.registerReceiver(wifiScanReceiver,
IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
wifiManager.startScan()
}
}
Both are executed concurrently like this:
val location = async { getCurrentLocation() }
val wifi = async { wifiScanner.getCurrentScanResult() }
val currentLocation = location.await()
val currentWifiInfo = wifi.await()
In a quick test it works fine, but it feels like abusing the system. Can I use this like that without breaking the common conventions?
android asynchronous networking geospatial kotlin
In my app I need to query location and scan wifi periodically. To conserve power I need to change the rate dynamically, depending on the distance to the target. Also I want to wait for both asynchronous calls to complete. Coroutines seemed the obvious choice, but since this is my first take at coroutines I want to have a second opinion.
I came up with the following solution:
@SuppressLint("MissingPermission")
suspend fun getCurrentLocation(context: Context): Location? = suspendCoroutine { cont ->
val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
val locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.numUpdates = 1
val listener = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
cont.resume(locationResult?.lastLocation)
}
}
val task = fusedLocationProviderClient.requestLocationUpdates(locationRequest,
listener,
null)
task.addOnFailureListener { cont.resumeWithException(it) }
}
also
class WifiScanner(val context: ContextWrapper) {
val wifiManager: WifiManager
init {
wifiManager = context.baseContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
}
suspend fun getCurrentScanResult(): List<ScanResult> =
suspendCoroutine { cont ->
val wifiScanReceiver = object : BroadcastReceiver() {
override fun onReceive(c: Context, intent: Intent) {
if (intent.action?.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) == true) {
val scanResults = wifiManager.scanResults
//sort so that strongest signal is on top
scanResults.sortByDescending { it.level }
Log.i("received wifi", scanResults.toString())
context.unregisterReceiver(this)
cont.resume(scanResults)
}
}
}
context.registerReceiver(wifiScanReceiver,
IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
wifiManager.startScan()
}
}
Both are executed concurrently like this:
val location = async { getCurrentLocation() }
val wifi = async { wifiScanner.getCurrentScanResult() }
val currentLocation = location.await()
val currentWifiInfo = wifi.await()
In a quick test it works fine, but it feels like abusing the system. Can I use this like that without breaking the common conventions?
android asynchronous networking geospatial kotlin
android asynchronous networking geospatial kotlin
edited Nov 20 at 17:03
200_success
127k15148411
127k15148411
asked Nov 18 at 21:58
leonardkraemer
1065
1065
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207940%2fwrap-location-api-in-coroutines%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown