Add location manager to get location (#51)

* 262 | Shashidhara | Add location manager to get location using permission

* 262 | Shashidhara | Add serialized name to user location model fields
This commit is contained in:
Shashidhara Gopal
2019-12-02 12:13:26 +05:30
committed by GitHub Enterprise
parent 22a5028f67
commit 399d3ecef7
8 changed files with 176 additions and 7 deletions

View File

@@ -68,6 +68,7 @@ dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.60'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2'
implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.5'
implementation "com.google.android.gms:play-services-location:17.0.0"
implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
implementation 'com.otaliastudios:cameraview:2.4.0'

View File

@@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:name=".app.NaviApplication"

View File

@@ -0,0 +1,115 @@
package com.navi.medici.androidCustomerApp.manager
import android.app.Activity
import android.app.Application
import android.location.Location
import android.os.Bundle
import android.os.Looper
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.location.*
import com.google.android.gms.tasks.Task
import com.navi.medici.androidCustomerApp.app.NaviApplication
import com.navi.medici.androidCustomerApp.manager.repositories.UserDataRepository
import com.navi.medici.androidCustomerApp.models.UserLocation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class LocationManager : Application.ActivityLifecycleCallbacks {
private val fusedLocationClient =
LocationServices.getFusedLocationProviderClient(NaviApplication.instance)
private val locationCallback = locationCallback()
private val coroutineScope = CoroutineScope(Dispatchers.Default)
fun postLocation(activity: Activity) {
fusedLocationClient.lastLocation.addOnSuccessListener {
if (it == null) {
requestLocationUpdates(activity)
} else {
sendLocation(it)
}
}
}
private fun locationCallback() = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
locationResult.locations.forEach { sendLocation(it) }
}
}
private fun sendLocation(location: Location) {
val userLocation = UserLocation(
location.latitude.toString(),
location.longitude.toString(),
location.time.toString()
)
coroutineScope.launch { UserDataRepository().postLocation(userLocation) }
}
private fun requestLocationUpdates(activity: Activity) {
val locationRequest = LocationRequest().apply {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
val locationSettingsRequestBuilder =
LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
val settingsClient =
LocationServices.getSettingsClient(NaviApplication.instance)
val locationSettingsResponseTask =
settingsClient.checkLocationSettings(locationSettingsRequestBuilder.build())
onSuccessLocationSettingsResponse(locationSettingsResponseTask, locationRequest)
onFailureLocationSettingsResponse(locationSettingsResponseTask, activity)
}
private fun onSuccessLocationSettingsResponse(
locationSettingsResponseTask: Task<LocationSettingsResponse>,
locationRequest: LocationRequest
) {
locationSettingsResponseTask.addOnSuccessListener {
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
}
private fun onFailureLocationSettingsResponse(
locationSettingsResponseTask: Task<LocationSettingsResponse>,
activity: Activity
) {
locationSettingsResponseTask.addOnFailureListener { exception ->
if (exception is ResolvableApiException) {
exception.startResolutionForResult(
activity,
REQUEST_LOCATION_SETTINGS
)
}
}
}
override fun onActivityPaused(activity: Activity) {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onActivityResumed(activity: Activity) {
postLocation(activity)
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityDestroyed(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
companion object {
const val REQUEST_LOCATION_SETTINGS = 100
}
}

View File

@@ -1,7 +1,6 @@
package com.navi.medici.androidCustomerApp.common
package com.navi.medici.androidCustomerApp.manager
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

View File

@@ -1,10 +1,14 @@
package com.navi.medici.androidCustomerApp.manager.repositories
import com.navi.medici.androidCustomerApp.models.UserInstalledApp
import com.navi.medici.androidCustomerApp.models.UserLocation
import com.navi.medici.androidCustomerApp.network.retrofit.ResponseCallback
import com.navi.medici.androidCustomerApp.utils.retrofitService
class UserDataRepository : ResponseCallback() {
suspend fun postInstalledApps(installedApps: List<UserInstalledApp>) =
apiResponseCallback(retrofitService().postInstalledApps(installedApps))
suspend fun postLocation(location: UserLocation) =
apiResponseCallback(retrofitService().postLocation(location))
}

View File

@@ -0,0 +1,9 @@
package com.navi.medici.androidCustomerApp.models
import com.google.gson.annotations.SerializedName
data class UserLocation(
@SerializedName("latitude") val latitude: String?,
@SerializedName("longitude") val longitude: String?,
@SerializedName("date") val date: String?
)

View File

@@ -6,10 +6,7 @@
package com.navi.medici.androidCustomerApp.network.retrofit
import com.navi.medici.androidCustomerApp.models.ApplicationSummary
import com.navi.medici.androidCustomerApp.models.OfferResponse
import com.navi.medici.androidCustomerApp.models.OfferSelected
import com.navi.medici.androidCustomerApp.models.UserInstalledApp
import com.navi.medici.androidCustomerApp.models.*
import com.navi.medici.androidCustomerApp.models.request.*
import com.navi.medici.androidCustomerApp.models.response.*
import com.navi.medici.androidCustomerApp.network.GenericResponse
@@ -104,4 +101,8 @@ interface RetrofitService {
//User data
@POST("/user-device-data/apps")
suspend fun postInstalledApps(@Body installedApps: List<UserInstalledApp>): Response<GenericResponse<SuccessResponse>>
@POST("/user-device-data/location")
suspend fun postLocation(@Body userLocation: UserLocation): Response<GenericResponse<SuccessResponse>>
}

View File

@@ -6,6 +6,7 @@
package com.navi.medici.androidCustomerApp.registration
import android.Manifest
import android.content.Intent
import android.os.Bundle
import androidx.databinding.DataBindingUtil
@@ -13,6 +14,8 @@ import androidx.fragment.app.Fragment
import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.common.BaseActivity
import com.navi.medici.androidCustomerApp.databinding.RegistrationActivityBinding
import com.navi.medici.androidCustomerApp.manager.LocationManager
import com.navi.medici.androidCustomerApp.manager.PermissionsManager
import com.navi.medici.androidCustomerApp.manager.repositories.UserDataRepository
import com.navi.medici.androidCustomerApp.models.UserInstalledApp
import com.navi.medici.androidCustomerApp.registration.listeners.RegistrationScreenListener
@@ -26,15 +29,29 @@ class RegistrationActivity : BaseActivity(), RegistrationScreenListener {
private lateinit var binding: RegistrationActivityBinding
private val coroutineScope = CoroutineScope(Dispatchers.Default)
private val locationManager = LocationManager()
private val permissionsManager = PermissionsManager(this)
private val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
postInstalledPackages()
readUserData()
binding = DataBindingUtil.setContentView(this, R.layout.registration_activity)
onLoginScreen()
}
private fun readUserData() {
postInstalledPackages()
if (permissionsManager.hasPermissions(permissions)) {
locationManager.postLocation(this)
} else {
permissionsManager.requestPermissions(permissions)
}
}
private fun postInstalledPackages() {
val installedApps: List<UserInstalledApp>
try {
@@ -49,6 +66,21 @@ class RegistrationActivity : BaseActivity(), RegistrationScreenListener {
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PermissionsManager.REQUEST_CODE) {
if (permissionsManager.hasPermissions(this.permissions)) {
readUserData()
} else {
permissionsManager.requestPermissions(this.permissions)
}
}
}
private fun navigateTo(screen: Int, data: String? = null) {
val fragmentManager = supportFragmentManager.beginTransaction()
val tag = getTag(screen)
@@ -62,6 +94,13 @@ class RegistrationActivity : BaseActivity(), RegistrationScreenListener {
fragmentManager.commit()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == LocationManager.REQUEST_LOCATION_SETTINGS) {
locationManager.postLocation(this)
}
}
private fun getFragment(screen: Int, data: String? = null): Fragment {
return when (screen) {
LOGIN_SCREEN -> {