Android/Kotlin: geofencingEvent.geofenceTransition застрял на значении 2Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Android/Kotlin: geofencingEvent.geofenceTransition застрял на значении 2

Сообщение Anonymous »

Я изучаю геозоны.
geofencingEvent.geofenceTransition, похоже, вызывает 2 (Выход), даже если я установил геозону на расстоянии нескольких километров.
Тестовые среды:
  • Эмуляторы;
  • Телефон (S9)
Вещи, которые, как я думал, могут быть причиной:
Радиус. Возможно, радиус считывается неправильно, но база данных указывает Радиус 50 м, и при отображении на карте радиус кажется точным.
Система уведомлений: кажется, самый простой виновник. Однако журнал onReceive() также подтверждает, что пользователь вышел из геозоны, даже если он никогда в нее не входил.
2024-06-22 18:08:51.982 9613-9613 GeofenceBr...stReceiver com.example.geofenceapp D User exits the geofence

onReceive() может ошибаться: это мой текущий вывод. Но я не могу найти, в чем проблема.
Я также добавил еще одно представление (SharedViewModel, на которое onReceive() ссылается несколько раз).
Есть идеи?
GeofenceBroadcastReceiver
package com.example.geofenceapp.broadcastreceiver

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import com.example.geofenceapp.R
import com.example.geofenceapp.util.Constants.NOTIFICATION_CHANNEL_ID
import com.example.geofenceapp.util.Constants.NOTIFICATION_CHANNEL_NAME
import com.example.geofenceapp.util.Constants.NOTIFICATION_ID
import com.example.geofenceapp.util.Permissions
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.Geofence.GeofenceTransition
import com.google.android.gms.location.GeofenceStatusCodes
import com.google.android.gms.location.GeofencingEvent

class GeofenceBroadcastReceiver: BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {
if (context == null || intent == null) {
Log.e("GeofenceBroadcastReceiver", "Received null context or intent")
return
}

val geofencingEvent = GeofencingEvent.fromIntent(intent)
Log.e("geofencingEvent", "geofencingEvent is $geofencingEvent")
if (geofencingEvent == null) {
Log.e("GeofenceBroadcastReceiver", "GeofencingEvent is null. Intent details: ${intent.toUri(0)}")
return
}

if (geofencingEvent.hasError()) {
val errorMessage = GeofenceStatusCodes.getStatusCodeString(geofencingEvent.errorCode)
Log.e("GeofenceBroadcastReceiver", "GeofencingEvent error: $errorMessage")
return
}

val geofenceTransition = geofencingEvent.geofenceTransition
Log.d("GeofenceBroadcastReceiver", "Received geofence event: $geofenceTransition")

// Check if the transition type is valid
if (geofenceTransition in listOf(Geofence.GEOFENCE_TRANSITION_ENTER, Geofence.GEOFENCE_TRANSITION_EXIT, Geofence.GEOFENCE_TRANSITION_DWELL)) {
val triggeringGeofences = geofencingEvent.triggeringGeofences
val geofenceIds = triggeringGeofences?.joinToString(", ") { it.requestId }
Log.d("GeofenceBroadcastReceiver", "Triggering geofences: $geofenceIds")

// Handle specific geofence transitions
when (geofenceTransition) {
Geofence.GEOFENCE_TRANSITION_ENTER -> {
Log.d("GeofenceBroadcastReceiver", "Geofence Enter")
Log.d("GeofenceBroadcastReceiver", "User is within the geofence")
displayNotification(context, "Geofence ENTER")
}
Geofence.GEOFENCE_TRANSITION_EXIT -> {
Log.d("GeofenceBroadcastReceiver", "Geofence Exit")
Log.d("GeofenceBroadcastReceiver", "User exits the geofence")
displayNotification(context, "Geofence Exit")
}
Geofence.GEOFENCE_TRANSITION_DWELL -> {
Log.d("GeofenceBroadcastReceiver", "Geofence Dwell")
Log.d("GeofenceBroadcastReceiver", "User dwells within the geofence")
displayNotification(context, "Geofence Dwell")
}
}
} else {
Log.d("GeofenceBroadcastReceiver", "Unknown geofence transition: $geofenceTransition")
}
}

}

SharedViewModel
package com.example.geofenceapp.viewmodels

import android.app.Application
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.location.GnssAntennaInfo.SphericalCorrections
import android.location.LocationManager
import android.os.Build
import android.provider.Settings
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.example.geofenceapp.broadcastreceiver.GeofenceBroadcastReceiver
import com.example.geofenceapp.data.DataStoreRepository
import com.example.geofenceapp.data.GeofenceEntity
import com.example.geofenceapp.data.GeofenceRepository
import com.example.geofenceapp.util.Permissions
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofencingRequest
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.maps.android.SphericalUtil

import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.math.sqrt

@HiltViewModel
class SharedViewModel @Inject constructor (
application: Application,
private val dataStoreRepository: DataStoreRepository,
private val geofenceRepository: GeofenceRepository,
):AndroidViewModel(application) {

val app = application

private var geofencingClient = LocationServices.getGeofencingClient(app.applicationContext)

var geoId:Long = 0L
var geoName: String = "Default"
var geoCountryCode: String = ""
var geoLocationName: String = "Search a City"
var geoLatLng: LatLng = LatLng(0.0, 0.0)
var geoRadius: Float = 50f
var geoSnapShot: Bitmap? = null

var geoCitySelected = false
var geofenceReady = false

var geofencePrepared = false

//DataStore
val readFirstLaunch = dataStoreRepository.readFirstLaunch.asLiveData()

fun saveFirstLaunch(firstLaunch: Boolean) =
viewModelScope.launch(Dispatchers.IO){
dataStoreRepository.saveFirstLaunch(firstLaunch)

}

//Database
val readyGeofences = geofenceRepository.readGeofences.asLiveData()

fun addGeofence(geofenceEntity: GeofenceEntity) =
viewModelScope.launch(Dispatchers.IO) {
geofenceRepository.addGeofence(geofenceEntity)
}

fun removeGeofence(geofenceEntity: GeofenceEntity) =
viewModelScope.launch(Dispatchers.IO) {
geofenceRepository.removeGeofence(geofenceEntity)
}

fun addGeofenceToDatabase(location:LatLng){
val geofenceEntity =
GeofenceEntity(
geoId,
geoName,
geoLocationName,
location.latitude,
location.longitude,
geoRadius,
geoSnapShot!!,
)
addGeofence(geofenceEntity)
}

private fun setPendingIntent(geoId:Int): PendingIntent{
val intent = Intent(app, GeofenceBroadcastReceiver::class.java)

Log.d("setPendingIntent", "Creating PendingIntent for geoId: $geoId with action $intent")

// Choose FLAG_IMMUTABLE or FLAG_MUTABLE based on your needs
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_MUTABLE
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}

Log.d("Flag is","flag is ${flags}")

return PendingIntent.getBroadcast(
app,
geoId,
intent,
flags,
).also {
Log.d("setPendingIntent", "PendingIntent created: $it")
}
}

fun startGeofence(
latitude: Double,
longitude: Double,
){

if(Permissions.hasBackgroundLocationPermission(app)){
val geofence = Geofence.Builder()
.setRequestId(geoId.toString())
.setCircularRegion(
latitude,
longitude,
geoRadius,
)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(
Geofence.GEOFENCE_TRANSITION_ENTER
or Geofence.GEOFENCE_TRANSITION_EXIT
or Geofence.GEOFENCE_TRANSITION_DWELL
)
.setLoiteringDelay(5000)
.build()
val geofencingRequest = GeofencingRequest.Builder()
.setInitialTrigger(
GeofencingRequest.INITIAL_TRIGGER_ENTER
or GeofencingRequest.INITIAL_TRIGGER_EXIT
or GeofencingRequest.INITIAL_TRIGGER_DWELL
)
.addGeofence(geofence)
.build()

geofencingClient.addGeofences(geofencingRequest, setPendingIntent(geoId.toInt())).run{
addOnSuccessListener {
Log.d("Geofence","Successfully added.")
}
addOnFailureListener{
Log.d("Geofence", it.message.toString())
}
}
}else{
Log.d("Geofence","Permission not granted.")
}
}

fun getBounds(center:LatLng, radius:Float): LatLngBounds{
val distanceFromCenterToCorner = radius * sqrt(2.0)
//to find south west corner of a point
//we apply 225 degrees from north point
//then apply a square root of the radius
val southWestCorner = SphericalUtil.computeOffset(center, distanceFromCenterToCorner, 225.0)
//to find north east corner of a point
//we apply 45 degrees from north point
//then apply a square root of the radius
val northEastCorner = SphericalUtil.computeOffset(center, distanceFromCenterToCorner,45.0)

return LatLngBounds(southWestCorner, northEastCorner)
}

fun checkDeviceLocationSettings(context: Context):Boolean{

return if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
val LocationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
LocationManager.isLocationEnabled
}else{
val mode: Int = Settings.Secure.getInt(
context.contentResolver,
Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF
)
mode != Settings.Secure.LOCATION_MODE_OFF
}

}
}


Подробнее здесь: https://stackoverflow.com/questions/786 ... stuck-at-2
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»