我一直在开发一个应用程序,当一个周界被跨越时,它可以将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函数中改变一些东西?一般情况下,我有没有更好的方法?我可以看到这个函数似乎是字面上取了数组中的第一个项目,这就是导致问题的原因,但我不知道该用什么来代替它,使其发挥应有的作用。
试试这个git hub源码,它是在kotlin中的https:/github.comexozetGeolocator。