继续触发 GeoFence 事件

Continues Trigger GeoFence Event

GeoFence 触发问题

我在我的应用程序中设置了地理围栏, 我正在使用 IntetnService 处理触发事件。

我的问题是多次触发事件。

假设我在 Geofence 内的 1 个位置,不幸的是有一段时间进入或退出事件触发, 然后我喜欢检查 geoEvent.getTriggerdLocation() 属性并检查地理围栏半径,

如果触发位置到地理围栏位置的距离大于地理围栏半径,那么我将释放我的退出事件功能,

但最终地理围栏触发事件 2 3 公里远,即使我已经进入围栏并且我的上述逻辑将失败。见快照

我想对这些进行一些可靠的修复。

位置处于高优先级

当我靠近栅栏边界时,这种情况会发生得更多

添加地理围栏列表,目前我只使用一个围栏。

mGeofenceList.add(new Geofence.Builder().setRequestId(String.valueOf(loGeoFenceModels.liGeoFenceID))
                    .setCircularRegion(loGeoFenceModels.ldGeoLatitude, loGeoFenceModels.ldGeoLongitude,
                            loGeoFenceModels.lfRadius)
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                    .build());

PendidngIntentService

moGeofencePendingIntent = getGeofencePendingIntent();
        LocationServices.GeofencingApi
                .addGeofences(moLocationClient, getGeofencingRequest(), moGeofencePendingIntent)
                .setResultCallback(this);

getGeofencingRequest() 和 moGeofencePendingIntent

private GeofencingRequest getGeofencingRequest() {
    return new GeofencingRequest.Builder().setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            .addGeofences(mGeofenceList).build();
}



private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (moGeofencePendingIntent != null) {
        return moGeofencePendingIntent;
    }

    Intent intent = new Intent(moContext, GeofenceTransitionsIntentService.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent
    // back when calling addgeoFences()
    return PendingIntent.getService(moContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

GeofenceTransitionsIntentService.class

import java.util.ArrayList;
import java.util.List;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofenceStatusCodes;
import com.google.android.gms.location.GeofencingEvent;
import android.R.bool;
import android.app.IntentService;
import android.app.usage.UsageEvents.Event;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.text.TextUtils;

public class GeofenceTransitionsIntentService extends IntentService {

protected static final String TAG = "GeofenceTransitionsIS";

public GeofenceTransitionsIntentService() {
    super(TAG); // use TAG to name the IntentService worker thread
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
}

private static String getGeofenceTransitionDetails(GeofencingEvent event) {
    String transitionString = GeofenceStatusCodes.getStatusCodeString(event.getGeofenceTransition());
    List<String> triggeringIDs = new ArrayList<String>();
    for (Geofence geofence : event.getTriggeringGeofences()) {
        triggeringIDs.add(geofence.getRequestId());
    }
    return String.format("%s: %s", transitionString, TextUtils.join(", ", triggeringIDs));
}

@Override
protected void onHandleIntent(Intent intent) {

    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    Log.i(TAG, "Geofencing Event : " + event);
    if (event.hasError()) {
        Log.i(TAG, "GeofencingEvent Error : " + event.getErrorCode());
        return;
    }

    // Get the type of transition (entry or exit)
    if (event.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_ENTER) {
        Log.i(TAG, "GeofencingEvent Enter");
    }
    if (event.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_EXIT) {
        Log.i(TAG, "GeofencingEvent Exit");
    ?
    String description = getGeofenceTransitionDetails(event);
    Log.i(TAG, "GeofencingEvent description : " + description);
}

}

权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.hardware.location.gps" />

我卡在这个问题很多天了,请帮忙解决这个问题。

Application

中使用Geofence时需要注意以下几点

来自官方documentation

  • 为您的地理围栏选择最佳半径

For best results, the minimium radius of the geofence should be set between 100 - 150 meters. When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor location is available, the accuracy range can be as small as 5 meters. Unless you know indoor location is available inside the geofence, assume that Wi-Fi location accuracy is about 50 meters.

When Wi-Fi location is not available (for example, when you are driving in rural areas) the location accuracy degrades. The accuracy range can be as large as several hundred meters to several kilometers. In cases like this, you should create geofences using a larger radius.

  • 使用停留过渡类型减少警报垃圾邮件

If you receive a large number of alerts when driving briefly past a geofence, the best way to reduce the alerts is to use a transition type of GEOFENCE_TRANSITION_DWELL instead of GEOFENCE_TRANSITION_ENTER. This way, the dwelling alert is sent only when the user stops inside a geofence for a given period of time. You can choose the duration by setting a loitering delay.

找到一个补丁来避免不需要的或虚拟的事件。

您可以在触发时间获取位置

Location loTriggerGeoFenceLocation = moEvent.getTriggeringLocation();
long ldAccuracy = loTriggerGeoFenceLocation.getAccuracy();

现在存储您的地理围栏位置经纬度和半径。 没有得到触发经纬度并检查触发位置和经纬度地理围栏位置之间的距离。如果距离小于半径它应该是进入事件并且距离大于半径它应该是退出事件

 if (event.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_EXIT) {

    ldGeoLatLong = moSharedPreferenceManager.getGeoFenceTimeLocation();
    Location loExistGeoFenceLocation = new Location("");
    loExistGeoFenceLocation.setLatitude(ldGeoLatLong[0]);
    loExistGeoFenceLocation.setLongitude(ldGeoLatLong[1]);

    String lsRadius = moSharedPreferenceManager.getGeoFenceRadius();
    float lfRadius = Float.parseFloat(lsRadius);
        Log.i(TAG, "GeofencingEvent Exit");
        float lfDistance = loTriggerGeoFenceLocation.distanceTo(loExistGeoFenceLocation);
        if (lfDistance >= lfRadius && ldAccuracy <= 100f) {
            moSharedPreferenceManager.setGeoFenceExit(true);
        }
}