【问题标题】:How to get correct Geofence transition information?如何获得正确的地理围栏过渡信息?
【发布时间】:2019-12-04 16:53:10
【问题描述】:

我一直在开发一个应用程序,该应用程序可以在越界时将地理围栏信息记录在文本文件中。出于某种原因,总是取我的地理围栏提醒数组中的第一个值的名称,而不是已经越过的那个。我在网上找不到任何其他可以以任何身份回答这个问题的东西。

这是 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。如果我输入这些位置中的任何一个,将显示一条消息,告诉我我已进入位置 A,无论我实际在哪里,因为程序在记录时正在检索位置 A 的数据。

我是否必须更改 getFirstReminder 函数中的某些内容?一般来说,有没有更好的方法可以做到这一点?我可以看到该函数似乎从字面上获取了数组中的第一项,这就是导致问题的原因,但我不知道用什么替换它以使其按需要运行。

【问题讨论】:

    标签: android kotlin geofencing android-geofence


    【解决方案1】:

    试试这个 git hub 源 它在科特林 https://github.com/exozet/Geolocator

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 2014-05-19
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-03
      相关资源
      最近更新 更多