Skip to content
This repository has been archived by the owner on Aug 23, 2023. It is now read-only.

Updated project files and files of the modules (LocationUpdatesForegroundService and BasicLocationKotlin) #243

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ActivityRecognition/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dependencies {
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.1', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.12'

implementation 'com.google.android.material:material:1.0.0'
Expand Down
33 changes: 28 additions & 5 deletions BasicLocationKotlin/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion parent.ext.compileSdkVersion


defaultConfig {
applicationId "com.google.android.gms.location.sample.basiclocationsample"
minSdkVersion parent.ext.minSdkVersion
Expand All @@ -19,11 +18,35 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

buildFeatures {
viewBinding true
}
}

ext {
// Android Jetpack
// AppCompat
appCompatVersion = "1.2.0"
// MaterialComponents
materialComponentsVersion = "1.2.1"

// Google PlayServices
// Location
locationVersion = "17.1.0"
}

dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation "com.google.android.gms:play-services-location:17.0.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50"
// Android Jetpack
// AppCompat
implementation "androidx.appcompat:appcompat:$appCompatVersion"
// MaterialComponents
implementation "com.google.android.material:material:$materialComponentsVersion"

// Google PlayServices
// Location
implementation "com.google.android.gms:play-services-location:$locationVersion"

// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,55 +16,56 @@

package com.google.android.gms.location.sample.basiclocationsample

import android.Manifest
import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.location.Location
import android.net.Uri
import android.os.Bundle
import android.os.Looper
import android.provider.Settings
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_INDEFINITE
import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
import androidx.core.app.ActivityCompat
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.TextView

import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.sample.basiclocationsample.BuildConfig.APPLICATION_ID
import com.google.android.gms.tasks.Task
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.viewbinding.BuildConfig
import com.google.android.gms.location.*
import com.google.android.gms.location.sample.basiclocationsample.databinding.MainActivityBinding
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.snackbar.Snackbar.LENGTH_INDEFINITE

/**
* Demonstrates use of the Location API to retrieve the last known location for a device.
*/
class MainActivity : AppCompatActivity() {

class MainActivity: AppCompatActivity() {
private val TAG = "MainActivity"
private val REQUEST_PERMISSIONS_REQUEST_CODE = 34

/**
* Provides the entry point to the Fused Location Provider API.
*/
private lateinit var fusedLocationClient: FusedLocationProviderClient

private lateinit var latitudeText: TextView
private lateinit var longitudeText: TextView

/**
* ViewBinding
*/
private lateinit var binding: MainActivityBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)

latitudeText = findViewById(R.id.latitude_text)
longitudeText = findViewById(R.id.longitude_text)


// ViewBinding initialization
binding = MainActivityBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)

fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}

override fun onStart() {
super.onStart()

Expand All @@ -74,75 +75,23 @@ class MainActivity : AppCompatActivity() {
getLastLocation()
}
}

/**
* Provides a simple way of getting a device's location and is well suited for
* applications that do not require a fine-grained location and that do not need location
* updates. Gets the best and most recent location currently available, which may be null
* in rare cases when a location is not available.
*
* Note: this method should be called after location permission has been granted.
*/
@SuppressLint("MissingPermission")
private fun getLastLocation() {
fusedLocationClient.lastLocation
.addOnCompleteListener { taskLocation ->
if (taskLocation.isSuccessful && taskLocation.result != null) {

val location = taskLocation.result

latitudeText.text = resources
.getString(R.string.latitude_label, location?.latitude)
longitudeText.text = resources
.getString(R.string.longitude_label, location?.longitude)
} else {
Log.w(TAG, "getLastLocation:exception", taskLocation.exception)
showSnackbar(R.string.no_location_detected)
}
}
}

/**
* Shows a [Snackbar].
*
* @param snackStrId The id for the string resource for the Snackbar text.
* @param actionStrId The text of the action item.
* @param listener The listener associated with the Snackbar action.
*/
private fun showSnackbar(
snackStrId: Int,
actionStrId: Int = 0,
listener: View.OnClickListener? = null
) {
val snackbar = Snackbar.make(findViewById(android.R.id.content), getString(snackStrId),
LENGTH_INDEFINITE)
if (actionStrId != 0 && listener != null) {
snackbar.setAction(getString(actionStrId), listener)
}
snackbar.show()
}

/**
* Return the current state of the permissions needed.
*/
private fun checkPermissions() =
ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED

private fun startLocationPermissionRequest() {
ActivityCompat.requestPermissions(this, arrayOf(ACCESS_COARSE_LOCATION),
REQUEST_PERMISSIONS_REQUEST_CODE)
}

private fun checkPermissions() = ActivityCompat.checkSelfPermission(this,
ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED
private fun requestPermissions() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_COARSE_LOCATION)) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_COARSE_LOCATION)
&& ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_FINE_LOCATION)) {
// Provide an additional rationale to the user. This would happen if the user denied the
// request previously, but didn't check the "Don't ask again" checkbox.
Log.i(TAG, "Displaying permission rationale to provide additional context.")
showSnackbar(R.string.permission_rationale, android.R.string.ok, View.OnClickListener {
showSnackbar(R.string.permission_rationale, android.R.string.ok) {
// Request permission
startLocationPermissionRequest()
})

}
} else {
// Request permission. It's possible this can be auto answered if device policy
// sets the permission in a given state or the user denied the permission
Expand All @@ -151,7 +100,10 @@ class MainActivity : AppCompatActivity() {
startLocationPermissionRequest()
}
}

private fun startLocationPermissionRequest() {
ActivityCompat.requestPermissions(this, arrayOf(ACCESS_COARSE_LOCATION,
ACCESS_FINE_LOCATION), REQUEST_PERMISSIONS_REQUEST_CODE)
}
/**
* Callback received when a permissions request has been completed.
*/
Expand All @@ -166,35 +118,118 @@ class MainActivity : AppCompatActivity() {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
grantResults.isEmpty() -> Log.i(TAG, "User interaction was cancelled.")

// Permission granted.
(grantResults[0] == PackageManager.PERMISSION_GRANTED) -> getLastLocation()

(grantResults[0] == PERMISSION_GRANTED) -> getLastLocation()
// Permission denied.

// Notify the user via a SnackBar that they have rejected a core permission for the
// app, which makes the Activity useless. In a real app, core permissions would
// typically be best requested during a welcome-screen flow.

// Additionally, it is important to remember that a permission might have been
// rejected without asking the user for permission (device policy or "Never ask
// again" prompts). Therefore, a user interface affordance is typically implemented
// when permissions are denied. Otherwise, your app could appear unresponsive to
// touches or interactions which have required permissions.
else -> {
showSnackbar(R.string.permission_denied_explanation, R.string.settings,
View.OnClickListener {
// Build intent that displays the App settings screen.
val intent = Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.fromParts("package", APPLICATION_ID, null)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
startActivity(intent)
})
showSnackbar(R.string.permission_denied_explanation, R.string.settings) {
// Build intent that displays the App settings screen.
val intent = Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.fromParts("package",
BuildConfig.LIBRARY_PACKAGE_NAME, null)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
startActivity(intent)
}
}
}
}
}

/**
* Provides a simple way of getting a device's location and is well suited for
* applications that do not require a fine-grained location and that do not need location
* updates. Gets the best and most recent location currently available, which may be null
* in rare cases when a location is not available.
*
* Note: this method should be called after location permission has been granted.
*/
@SuppressLint("MissingPermission")
private fun getLastLocation() {
Log.d(TAG, "getLastLocation")
fusedLocationClient.lastLocation.addOnCompleteListener { taskLocation ->
if (taskLocation.isSuccessful && taskLocation.result != null) {
updateViews(taskLocation.result)
} else {
requestNewLocationData()
/*Log.w(TAG, "getLastLocation:exception", taskLocation.exception)
showSnackbar(R.string.no_location_detected)*/
}
}
}
fun updateViews(currentLocation: Location) {
Log.d(TAG, "updateViews")
binding.currentLatitude.text = resources
.getString(R.string.latitude_label, currentLocation.latitude)
binding.currentLongitude.text = resources
.getString(R.string.longitude_label, currentLocation.longitude)
}
fun requestNewLocationData() {
Log.d(TAG, "requestNewLocationData")
// Initializing LocationRequest
// object with appropriate methods
val locationRequest = LocationRequest().apply {
// For a high level accuracy use PRIORITY_HIGH_ACCURACY argument.
// For a low level accuracy (city), use PRIORITY_LOW_POWER
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = 3
fastestInterval = 1
numUpdates = 2
}

// setting LocationRequest on a FusedLocationClient
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

/*if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_DENIED && ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(Manifest.permission_group.LOCATION), PERMISSIONS_ALLOW_USING_LOCATION_ID
)
} else {
locationClient?.requestLocationUpdates(locationRequest,
locationCallback, Looper.myLooper())
}*/

if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)
== PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) {
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback, Looper.myLooper())
}
}
private val locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
Log.d(TAG, "onLocationResult")
updateViews(locationResult.lastLocation)
}
}
/**
* Shows a [Snackbar].
*
* @param snackStrId The id for the string resource for the Snackbar text.
* @param actionStrId The text of the action item.
* @param listener The listener associated with the Snackbar action.
*/
private fun showSnackbar(snackStrId: Int, actionStrId: Int = 0,
listener: View.OnClickListener? = null) {
val snackBar = Snackbar.make(findViewById(android.R.id.content), getString(snackStrId),
LENGTH_INDEFINITE)
if (actionStrId != 0 && listener != null) {
snackBar.setAction(getString(actionStrId), listener)
}
snackBar.show()
}
}
4 changes: 2 additions & 2 deletions BasicLocationKotlin/app/src/main/res/layout/main_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
android:paddingTop="@dimen/activity_vertical_margin">

<TextView
android:id="@+id/latitude_text"
android:id="@+id/current_latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_start"
Expand All @@ -35,7 +35,7 @@
android:textSize="@dimen/lat_long_text_size" />

<TextView
android:id="@+id/longitude_text"
android:id="@+id/current_longitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_start"
Expand Down
Loading