地理围栏事件并不总是被称为

时间:2017-09-27 14:15:01

标签: android location broadcastreceiver geofencing android-geofence

这是我添加地理围栏的方式:

var s = "Teterboro US [TEB] - 20KM";

console.log(
  s.match(/.*?(?=\s*\[)/)
)

这是我的BroadcastReceiver。我应该在哪里收到它们:

public void setGeofenceRequest(Location location) {
    if (geofences == null) {
        geofences = new ArrayList<Geofence>();
    }
    geofences.add(new Geofence.Builder()
            .setRequestId("3")
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
            .setCircularRegion(
                    location.getLatitude(), location.getLongitude(), PSLocationService.getInstance(context).kPSGeofencingDistanceMedium)
            .setExpirationDuration(Geofence.NEVER_EXPIRE)
            .build());
    Intent intent = new Intent(context, ReceiveTransitionsBroadcastReceiver.class);
    PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    if (geofences.size() > 0) {
        LocationServices.GeofencingApi.addGeofences(mLocationClient, geofences, pi);
        Log.i("", "geof autopilot2 will set geofence for autopilot-3");
    }
}

现在通常它有效,但并非总是如此。我会说只有大约75%的时间它应该工作,地理围栏事件实际上被称为。我觉得自从我设定地理围栏以来的时间越多,被召唤的可能性就越小。 为什么会这样?当垃圾收集器清理应用程序时,触发事件是否也被解除? 我怎样才能做到这一点,以便在案件结束时始终调用我的地理围栏?

编辑:

这是我的defaultConfig:

public class ReceiveTransitionsBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context ctx, Intent intent) {
    Log.i("","autopilot valid geof on receive transisionts broadcast receiver");
    PSMotionService.getInstance(ctx).buildGoogleApiClient();
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    int transitionType = geofencingEvent.getGeofenceTransition();
    Location geofenceCenter = PSApplicationClass.getInstance().pref.getGeoCenter(ctx);
    if(geofencingEvent.getTriggeringLocation() != null) {
        if (geofenceCenter != null) {
            Utils.appendLog("GEOFENCE ENTERED ReceiveTransitionsBroadcastReceiver TRIGGERING LOCATION: " + geofencingEvent.getTriggeringLocation().toString() + " / GEOFENCE CENTER: " + geofenceCenter.getLatitude() + ", " + geofenceCenter.getLongitude(), "D", Constants.TRACKER);
        } else
            Utils.appendLog("GEOFENCE ENTERED ReceiveTransitionsBroadcastReceiver TRIGGERING LOCATION: " + geofencingEvent.getTriggeringLocation().toString(), "D", Constants.TRACKER);
    }else Utils.appendLog("GEOFENCE ENTERED ReceiveTransitionsBroadcastReceiver ERROR => TRIGGERING LOCATION NULL", "D", Constants.TRACKER);
    if(transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
        List<Geofence> triggerList = geofencingEvent.getTriggeringGeofences();
        for (Geofence geofence : triggerList) {
            Log.i("", "geof is s receive transition broadcast receiver " + transitionType + " GPS zone " + geofence.getRequestId());
            if(geofence.getRequestId().contentEquals("3")) {
                Log.i("", "geof autopilot2 ENTERED GEOFENCE will start pilot with first location");
                Utils.appendLog("GEOFENCE ENTERED ReceiveTransitionsBroadcastReceiver check to see if should start pilot", "T", Constants.TRACKER);
                PSLocationService.getInstance(ctx).fastGPS = -1;
                PSLocationService.getInstance(ctx).RequestLocationUpdates();
                if(PSTrip.getActiveTrip() != null) {
                    PSLocationService.getInstance(ctx).removeAutoPilotGeofence();
                }else PSMotionService.getInstance(ctx).checkinTime = System.currentTimeMillis() / 1000;
            }
        }
    }
}
}

我从广播接收器更改为IntentService:

 defaultConfig {
    minSdkVersion 15
    targetSdkVersion 23

    ndk {
        moduleName "ndkVidyoSample"
    }
}

}

我还有删除和添加地理围栏的代码,并且监听器总是会在onSuccess中添加它们。

1 个答案:

答案 0 :(得分:6)

对于初学者,我不会将此代码放在BroadcastReceiver中。

除了不好的做法之外,组件可能会在代码执行完毕之前关闭。

如果您需要运行可能需要一些时间的代码,请考虑从您的Receiver启动Service。 否则,执行时间较短,您可以使用IntentService

通过查看您的代码,我发现您的地理围栏没有按预期工作的两个原因:

1)Geofences的性质

Geofences API主要通过WiFi /移动数据检索您的位置,这通常无法使用。

我尝试过使用Geofences一次,发现它们非常不准确。我切换到LocationManager,使其使用纯GPS位置,它符合我的期望。

请参阅this answer,建议

  

在一段时间内轮询GPS硬件而不对结果做任何事情,您将开始获得更准确的地理围栏。

我从未尝试过谷歌的FusedLocation API,但我听到有人说这对他们来说效果很好。

如果您使用LocationManager,则必须实施您的地理围栏逻辑&#39;自己;您可以使用Location.distanceTo(Location)轻松完成。

示例:

final float distanceFromCenter = currentLocation.distanceTo(this.destination);

if (distanceFromCenter <= YOUR_RADIUS_IN_METERS) {
   // you are inside your geofence
} 

2)CPU未激活

Geofences处于活动状态的事实并不一定意味着您的手机处于清醒状态并且计算位置检查。

要解决此问题,您可以从BroacastReceiver启动ForegroundService。该服务也应该持有partial WakeLock。 这保证了:

  1. 操作系统不会杀死服务(或更好:杀死的机会更少......)
  2. 用户知道该服务,并可在必要时将其解雇
  3. CPU正在运行。因此,您可以确保检索该位置的代码正在运行(请记住在服务停止时释放WakeLock)。
  4. 请注意,Android可能仍会在必要时终止您的服务。

    你可以在网上找到很多关于如何从BroadcastReceiver启动ForegroundService,如何持有WakeLock等等的例子......

    另外,请查看新的Android O API,它会对ForegroundService和其他组件进行一些小的更改。

    PS:我开发的应用程序使用了上面提到的所有组件(FusedLocation除外),我非常满意。

    编辑:回答OP的问题

    哎呀,我们试着在这里做一些订单,否则未来的读者可能会很容易混淆。我将首先回答原始问题和“赏金旗帜”中的内容,然后是OP编辑,最后是OP在评论中提出的问题。

    1)原始问题

      

    当垃圾收集器清理应用程序时,触发事件是否也被解除?

    最有可能是的。请参阅this answer,其中OP实施了一个在单独进程中运行的服务,以便即使在应用程序被杀死时也会触发地理围栏。

      

    如果已经过了足够的时间,我需要了解导致地理围栏不被调用的原因

    很多原因。请参阅我的原始答案。

      

    我看到使用服务而不是广播接收器实现地理围栏逻辑,这会更好吗?

    接收者和服务是两回事。请阅读Android的文档。您可以从BroadcastReceiver启动服务,这通常是接收&#39;的首选方式。 PendingIntents并与他们合作。

    2)编辑

    • 请注意,我没有告诉您用服务替换BroadcastReceiver,但是从接收器启动服务并在那里处理所有逻辑可能是个好主意。
    • 不需要将您的IntentService设为Singleton类(来自IntentService documentation
      

    所有请求都在一个工作线程上处理 - 它们可能需要多长时间(并且不会阻止应用程序的主循环),但一次只能处理一个请求。

    • 不要将Context存储到Singleton类或某些静态引用中。我印象深刻的Android Studio没有警告你。

    3)评论

      

    我需要这个全天候工作,因此我无法一直使用该位置,导致明显的电池问题。

    请阅读Android Oreo Background Execution Limits。这对您来说可能是一个问题。

      

    现在我改为使用了intentService,是否足以确保它保持清醒状态?

    不,正如我所说,你可能需要部分WakeLock来打开CPU。

      

    我是否需要以另一种方式启动它,以便将其保留在前台?

    是。要启动前台服务,您需要致电startForeground(int, Notification)

    请注意:IntentServices的生命周期仅限于onHandleIntent()函数的结尾。通常,它们不应该活超过几秒钟。如果要启动前景,请使用Service类。

    此外,正如原始答案中所述,Android Oreo提供了一个新的Foreground API,并且首选。

      

    不是问题,只是一个通知:我需要在这里使用Geofencing。 (如有必要,Geofencing将启动gps

    好的完美。看看什么最适合你。