Skip to content

Commit

Permalink
Merge pull request #12 from SimpleAppProjects/develop
Browse files Browse the repository at this point in the history
v5.8.4
  • Loading branch information
thewizrd authored Jan 23, 2024
2 parents aa75264 + b7c686b commit a9c60ec
Show file tree
Hide file tree
Showing 47 changed files with 861 additions and 1,078 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.targetSdkVersion
// NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 00, WearOS: 01)
versionCode 335830000
versionName "5.8.3"
versionCode 335840000
versionName "5.8.4"

vectorDrawables.useSupportLibrary true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ class SettingsFragment : BaseSettingsFragment(),
settingsManager.setAPIKey(provider, key)
settingsManager.setAPI(provider)
settingsManager.setKeyVerified(provider, true)
settingsManager.setPersonalKey(true)

updateKeySummary()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ class SetupProviderFragment : CustomPreferenceFragmentCompat(), StepperFragment
settingsManager.setAPIKey(provider, key)
settingsManager.setAPI(provider)
settingsManager.setKeyVerified(provider, true)
settingsManager.setPersonalKey(true)

updateKeySummary()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class WeatherNowViewModel(app: Application) : AndroidViewModel(app) {
when (result) {
is WeatherResult.Error -> {
viewModelState.update { state ->
if (state.locationData?.countryCode?.let { !wm.isRegionSupported(it) } == true) {
if (state.locationData?.let { !wm.isRegionSupported(it) } == true) {
Logger.writeLine(
Log.WARN,
"Location: %s; countryCode: %s",
Expand Down Expand Up @@ -290,7 +290,7 @@ class WeatherNowViewModel(app: Application) : AndroidViewModel(app) {
val weatherData = result.data.toUiModel()

viewModelState.update { state ->
if (state.locationData?.countryCode?.let { !wm.isRegionSupported(it) } == true) {
if (state.locationData?.let { !wm.isRegionSupported(it) } == true) {
Logger.writeLine(
Log.WARN,
"Location: %s; countryCode: %s",
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ buildscript {
preference_version = '1.2.1'
recyclerview_version = '1.3.1'
room_version = '2.5.2'
coresplash_version = '1.0.0'
coresplash_version = '1.0.1'
work_version = '2.8.1'

test_core_version = '1.5.0'
Expand Down
207 changes: 142 additions & 65 deletions common/src/fullgms/java/com/thewizrd/common/location/LocationProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ package com.thewizrd.common.location
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.location.Criteria
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.util.Log
import androidx.core.location.LocationManagerCompat
import androidx.core.os.CancellationSignal
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.android.gms.wearable.Wearable
import com.thewizrd.common.R
import com.thewizrd.common.helpers.locationPermissionEnabled
import com.thewizrd.common.utils.ErrorMessage
Expand All @@ -22,6 +25,7 @@ import com.thewizrd.shared_resources.exceptions.WeatherException
import com.thewizrd.shared_resources.locationdata.LocationData
import com.thewizrd.shared_resources.locationdata.toLocation
import com.thewizrd.shared_resources.locationdata.toLocationData
import com.thewizrd.shared_resources.utils.ContextUtils.isPhone
import com.thewizrd.shared_resources.utils.ConversionMethods
import com.thewizrd.shared_resources.utils.Logger
import com.thewizrd.weather_api.weatherModule
Expand Down Expand Up @@ -65,16 +69,12 @@ class LocationProvider {
suspend fun getLastLocation(): Location? {
if (!checkPermissions()) return null

if (isGMSAvailable) {
val isFusedLocationAvailable = canUseFusedLocation().await()

if (isFusedLocationAvailable) {
return mFusedLocationProviderClient.lastLocation.await()
} else {
val locCriteria = Criteria().apply {
accuracy = Criteria.ACCURACY_COARSE
isCostAllowed = false
powerRequirement = Criteria.POWER_LOW
}

val provider = mLocationMgr.getBestProvider(locCriteria, true) ?: return null
val provider = getBestProvider() ?: return null
return mLocationMgr.getLastKnownLocation(provider)
}
}
Expand All @@ -89,74 +89,75 @@ class LocationProvider {
return@suspendCancellableCoroutine
}

if (isGMSAvailable) {
val cts = CancellationTokenSource()
canUseFusedLocation()
.continueWith { task ->
if (!continuation.isActive) return@continueWith

continuation.invokeOnCancellation {
cts.cancel()
}
val isFusedLocationAvailable = task.result

mFusedLocationProviderClient.getCurrentLocation(
LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY,
cts.token
).addOnCompleteListener {
if (it.isSuccessful) {
Logger.writeLine(Log.INFO, "$TAG: Location update received...")
if (isFusedLocationAvailable) {
val cts = CancellationTokenSource()

if (continuation.isActive) {
continuation.resume(it.result)
}
} else {
it.exception?.let { ex ->
Logger.writeLine(Log.INFO, ex, "$TAG: Error retrieving location...")
continuation.invokeOnCancellation {
cts.cancel()
}

if (continuation.isActive) {
continuation.resume(null)
mFusedLocationProviderClient.getCurrentLocation(
Priority.PRIORITY_BALANCED_POWER_ACCURACY,
cts.token
).addOnCompleteListener {
if (it.isSuccessful) {
Logger.writeLine(Log.INFO, "$TAG: Location update received...")

if (continuation.isActive) {
continuation.resume(it.result)
}
} else {
it.exception?.let { ex ->
Logger.writeLine(Log.INFO, ex, "$TAG: Error retrieving location...")
}

if (continuation.isActive) {
continuation.resume(null)
}
}
}
}
}
} else {
val locCriteria = Criteria().apply {
accuracy = Criteria.ACCURACY_COARSE
isCostAllowed = false
powerRequirement = Criteria.POWER_LOW
}

val cancelSignal = CancellationSignal()
} else {
val cancelSignal = CancellationSignal()

continuation.invokeOnCancellation {
cancelSignal.cancel()
}
continuation.invokeOnCancellation {
cancelSignal.cancel()
}

val provider = mLocationMgr.getBestProvider(locCriteria, true)
val provider = getBestProvider()

if (provider == null) {
if (continuation.isActive) {
continuation.resume(null)
}
return@suspendCancellableCoroutine
}
if (provider == null) {
if (continuation.isActive) {
continuation.resume(null)
}
return@continueWith
}

runCatching {
LocationManagerCompat.getCurrentLocation(
mLocationMgr,
provider,
cancelSignal,
Executors.newSingleThreadExecutor()
) {
Logger.writeLine(Log.INFO, "$TAG: Location update received...")
if (continuation.isActive) {
continuation.resume(it)
runCatching {
LocationManagerCompat.getCurrentLocation(
mLocationMgr,
provider,
cancelSignal,
Executors.newSingleThreadExecutor()
) {
Logger.writeLine(Log.INFO, "$TAG: Location update received...")
if (continuation.isActive) {
continuation.resume(it)
}
}
}.onFailure {
Logger.writeLine(Log.INFO, it, "$TAG: Error retrieving location...")
if (continuation.isActive) {
continuation.resume(null)
}
}
}
}.onFailure {
Logger.writeLine(Log.INFO, it, "$TAG: Error retrieving location...")
if (continuation.isActive) {
continuation.resume(null)
}
}
}
}

suspend fun getLatestLocationData(previousLocation: LocationData? = null): LocationResult {
Expand Down Expand Up @@ -236,4 +237,80 @@ class LocationProvider {

return LocationResult.NotChanged(previousLocation, false)
}

private fun getBestProvider(): String? {
val enabledProviders = mLocationMgr.getProviders(true)

if (enabledProviders.isNotEmpty()) {
return if (mContext.isPhone() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && enabledProviders.contains(
LocationManager.FUSED_PROVIDER
)
) {
LocationManager.FUSED_PROVIDER
} else if (enabledProviders.contains(LocationManager.GPS_PROVIDER)) {
LocationManager.GPS_PROVIDER
} else if (enabledProviders.contains(LocationManager.NETWORK_PROVIDER)) {
LocationManager.NETWORK_PROVIDER
} else if (enabledProviders.contains(LocationManager.PASSIVE_PROVIDER)) {
LocationManager.PASSIVE_PROVIDER
} else {
enabledProviders.first()
}
}

return null
}

/**
* On non-wearables: Check if Google Play Services are available. If so, return [com.google.android.gms.location.LocationAvailability.isLocationAvailable]
*
* On wearables: Check if Google Play Services are available. If so, check if any paired phone is available and nearby.
* If so, confirm fused location availability [com.google.android.gms.location.LocationAvailability.isLocationAvailable]
*
* @see [FusedLocationProviderClient.getLocationAvailability]
* @see [com.google.android.gms.wearable.NodeClient.getConnectedNodes]
* @return true if we can use fused location provider
*/
private fun canUseFusedLocation(): Task<Boolean> {
return Tasks.forResult(isGMSAvailable)
.continueWithTask {
val isGMSAvailable = it.result

if (isGMSAvailable) {
if (!mContext.isPhone()) {
// Wearables: FusedLocationProvider will likely not be of use if phone is not connected nearby
// Verify phone status
Wearable.getNodeClient(mContext)
.connectedNodes
.continueWithTask { nodesTask ->
if (it.isSuccessful) {
val nodes = nodesTask.result
val isNearbyNodes = nodes.any { n -> n.isNearby }
if (isNearbyNodes) {
isFusedLocationAvailable()
} else {
Tasks.forResult(false)
}
} else {
Tasks.forResult(false)
}
}
} else {
isFusedLocationAvailable()
}
} else {
Tasks.forResult(false)
}
}
}

private fun isFusedLocationAvailable(): Task<Boolean> {
return mFusedLocationProviderClient.locationAvailability.continueWith { avail ->
if (avail.isSuccessful) {
avail.result.isLocationAvailable
} else {
false
}
}
}
}
Loading

0 comments on commit a9c60ec

Please sign in to comment.