Я работал над приложением, которое регистрирует информацию о геозоне в текстовом файле при пересечении периметра. По какой-то причине всегда принимает имя первого значения в моем массиве напоминаний Geofence, а не то, которое было пересечено. Я не могу найти ничего другого в Интернете, что отвечает на этот вопрос в любом качестве.
Вот код для ReminderRepository.kt:
class ReminderRepository(private val context: Context) {
companion object {
private const val PREFS_NAME = "ReminderRepository"
private const val REMINDERS = "REMINDERS"
}
private val preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
private val gson = Gson()
private val geofencingClient = LocationServices.getGeofencingClient(context)
private val geofencePendingIntent: PendingIntent by lazy {
val intent = Intent(context, GeofenceBroadcastReceiver::class.java)
PendingIntent.getBroadcast(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT)
}
fun add(reminder: Reminder, success: () -> Unit, failure: (error: String) -> Unit) {
val geofence = buildGeofence(reminder)
if (geofence != null
&& ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
geofencingClient.addGeofences(buildGeofencingRequest(geofence), geofencePendingIntent)
.addOnSuccessListener {
saveAll(getAll() + reminder)
success()
}.addOnFailureListener {
failure(GeofenceErrorMessages.getErrorString(context, it))
}
}
}
private fun buildGeofence(reminder: Reminder): Geofence? {
val latitude = reminder.latLng?.latitude
val longitude = reminder.latLng?.longitude
val radius = reminder.radius
if (latitude != null && longitude != null && radius != null) {
return Geofence.Builder()
.setRequestId(reminder.id)
.setCircularRegion(
latitude,
longitude,
radius.toFloat()
)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT) // 12/01 - MAJOR necessary addition :x
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build()
}
return null
}
private fun buildGeofencingRequest(geofence: Geofence): GeofencingRequest {
return GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofences(listOf(geofence))
.build()
}
fun remove(reminder: Reminder, success: () -> Unit, failure: (error: String) -> Unit) {
geofencingClient
.removeGeofences(listOf(reminder.id)).addOnSuccessListener {
saveAll(getAll() - reminder)
success()
}.addOnFailureListener {
failure(GeofenceErrorMessages.getErrorString(context, it))
}
}
private fun saveAll(list: List<Reminder>) {
preferences.edit().putString(REMINDERS, gson.toJson(list)).apply()
}
fun getAll(): List<Reminder> {
if (preferences.contains(REMINDERS)) {
val remindersString = preferences.getString(REMINDERS, null)
val arrayOfReminders = gson.fromJson(remindersString, Array<Reminder>::class.java)
if (arrayOfReminders != null) {
return arrayOfReminders.toList()
}
}
return listOf()
}
fun get(requestId: String?) = getAll().firstOrNull { it.id == requestId }
fun getLast() = getAll().lastOrNull()
}
ReminderApp.kt:
class ReminderApp : Application() {
private lateinit var repository: ReminderRepository
override fun onCreate() {
super.onCreate()
repository = ReminderRepository(this)
}
fun getRepository() = repository
}
GeofenceBroadcastReceiver.kt:
class GeofenceBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
GeofenceTransitionsJobIntentService.enqueueWork(context, intent)
}
}
Вот код файла GeofenceTransitionsJobIntentService.kt:
// The file name is saved in ../res/values/strings.xml
val fileName = "fencelog.txt"
val lineBreak: String? = System.getProperty("line.separator")
companion object {
private const val LOG_TAG = "GeoTrIntentService"
private const val JOB_ID = 573
fun enqueueWork(context: Context, intent: Intent) {
enqueueWork(context, GeofenceTransitionsJobIntentService::class.java, JOB_ID, intent)
}
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onHandleWork(intent: Intent) {
val geofencingEvent = GeofencingEvent.fromIntent(intent)
if (geofencingEvent.hasError()) {
val errorMessage = GeofenceErrorMessages.getErrorString(this, geofencingEvent.errorCode)
Log.e(LOG_TAG, errorMessage)
return
}
handleEvent(geofencingEvent)
}
// Handle what happens when a transition is received
@RequiresApi(Build.VERSION_CODES.O)
private fun handleEvent(event: GeofencingEvent) {
if (event.geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) {
// Get the reminder for the entered Geofence and get its message and coordinate values
val reminder = getFirstReminder(event.triggeringGeofences)
val message = reminder?.message
val latLng = reminder?.latLng
// Ensure neither reminder.message nor reminder.latLng is null
if (message != null && latLng != null) {
// Record the transition in fencelog.txt and send the user a notification alerting them to their arrival
writeToLogFile(this, fileName, message, getTimeStamp(), true)
sendNotification(this, "You've arrived at $message!", latLng)
}
}
if (event.geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
val reminder = getFirstReminder(event.triggeringGeofences)
val message = reminder?.message
val latLng = reminder?.latLng
if (message != null && latLng != null) {
sendNotification(this, "You just left $message!", latLng)
writeToLogFile(this, fileName, message, "some time", false)
}
}
}
// Get the reminder that was used to create the Geofence
private fun getFirstReminder(triggeringGeofences: List<Geofence>): Reminder? {
val firstGeofence = triggeringGeofences[0]
return (application as ReminderApp).getRepository().get(firstGeofence.requestId)
}
Скажем, у меня есть три местоположения в моем списке геозон — местоположение A, местоположение B и местоположение C — в позициях 0, 1 и 2 соответственно. Если я войду в какое-либо из этих местоположений, появится сообщение о том, что я вошел в местоположение А, независимо от того, где я на самом деле нахожусь, потому что программа извлекает данные для местоположения А при регистрации.
Нужно ли что-то менять в функции getFirstReminder? Есть ли лучший способ сделать это в целом? Я вижу, что функция, кажется, буквально берет первый элемент в массиве, что и вызывает проблему, но я не знаю, чем его заменить, чтобы он функционировал должным образом.