如何获得正确的Geofence过渡信息?

问题描述 投票:0回答:1

我一直在开发一个应用程序,当一个周界被跨越时,它可以将Geofence信息记录在一个文本文件中。由于某些原因,它总是取我的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)
    }
}

这里是代码 地理围栏转换JobIntentService.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的位置。如果我输入这些位置中的任何一个,就会显示一条消息,告诉我我已经输入了位置A,而不管我实际在哪里,因为程序在记录时正在检索位置A的数据。

我是否必须在getFirstReminder函数中改变一些东西?一般情况下,我有没有更好的方法?我可以看到这个函数似乎是字面上取了数组中的第一个项目,这就是导致问题的原因,但我不知道该用什么来代替它,使其发挥应有的作用。

android kotlin geofencing android-geofence
1个回答
0
投票

试试这个git hub源码,它是在kotlin中的https:/github.comexozetGeolocator。

© www.soinside.com 2019 - 2024. All rights reserved.