并不总是触发带有 BroadcastReceiver 的地理围栏

Posted

技术标签:

【中文标题】并不总是触发带有 BroadcastReceiver 的地理围栏【英文标题】:Geofence with BroadcastReceiver is not always triggered 【发布时间】:2019-03-26 11:34:29 【问题描述】:

在我的应用程序中使用地理围栏之前,我使用 IntentService 作为其回调,一切正常。但现在由于 android 8 的变化,我无法再启动这样的服务了。因此,现在我使用 BroadcastReceiver 作为我的地理围栏回调,并且该接收器正在启动服务(android 8 的前台)。但是随着这种变化,我注意到地理围栏不再有效。它通常根本不会被触发,我认为更糟糕的情况是应用程序在前台。最好的情况是当应用程序被杀死时,地理围栏就会被触发。 BroadcastReceivers 和地理围栏有问题还是我做错了什么?我提供我的代码:

添加地理围栏的通用类:

public abstract class BaseGeofence<T extends BaseGeofenceObject> implements OnSuccessListener<Void>, OnFailureListener 
    protected int RADIUS_IN_METERS = 300;
    protected GeofencingClient client;
    protected Context context;

    public BaseGeofence(Context context) 
        this.client = LocationServices.getGeofencingClient(context);
        this.context = context;
    

    @SuppressLint("MissingPermission")
    public void addGeofencing(final T object) 
        if (GPSUtils.wasLocationChecked()) 
            Geofence geofence = (new Geofence.Builder()
                    .setRequestId(Integer.toString(getId(object)))

                    .setCircularRegion(
                            object.getLat(),
                            object.getLon(),
                            RADIUS_IN_METERS
                    )
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                            Geofence.GEOFENCE_TRANSITION_EXIT)
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .build());
            client.addGeofences(getGeofencingRequest(geofence), getGeofencePendingIntent(object))
                    .addOnSuccessListener(this).addOnFailureListener(this);
        


    

    private GeofencingRequest getGeofencingRequest(Geofence geofence) 
        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
        builder.addGeofence(geofence);
        return builder.build();
    

    private PendingIntent getGeofencePendingIntent(T object) 
        return PendingIntent.getBroadcast(context, getId(object), createIntent(object), PendingIntent.FLAG_UPDATE_CURRENT);
    

    protected abstract Intent createIntent(T object);

    protected abstract int getId(T object);

    @Override
    public abstract void onSuccess(Void aVoid);

    @Override
    public abstract void onFailure(@NonNull Exception e);

MyGeofencing 类:

public class MyGeofencing extends BaseGeofence<MyObject> 

        private MyObject myObject;

        public MyGeofencing(Context context) 
            super(context);
        

        @Override
        protected Intent createIntent(MyObject object) 
            this.myObject = object;
            Intent intent = new Intent(context, GeofenceTransitionsReceiver.class);

            //put extras to intent 

            return intent;
        

        @Override
        public void addGeofencing(MyObject object) 
            if (object.getGeofencingRadius() == 0) RADIUS_IN_METERS = 300;
            else RADIUS_IN_METERS = object.getGeofencingRadius();
            super.addGeofencing(object);
        

        @Override
        protected int getId(MyObject object) 
            return object.getId();
        



    

我的接收者:

public class GeofenceTransitionsReceiver extends StartingServiceBroadcastReceiver 


    @Override
    public void onReceive(Context context, Intent intent) 
        if (GeofencingEvent.fromIntent(intent) != null && GeofencingEvent.fromIntent(intent).getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_ENTER) 

            startConnectionService(context, "extra");


         else if (GeofencingEvent.fromIntent(intent) != null && GeofencingEvent.fromIntent(intent).getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_EXIT) 
            // do something
        
    

protected void startConnectionService(Context context, String extra) 
        Intent beaconIntent = new Intent(context, BeaconConnectionService.class);
        beaconIntent.putExtra("extra", extra);        
        startService(context, beaconIntent);
    

StartingServiceBroadcastReceiver 启动前台服务,如果是 android 8 或普通的,否则

public abstract class StartingServiceBroadcastReceiver extends BroadcastReceiver 
    @Override
    public abstract void onReceive(Context context, Intent intent);

    protected void startService(Context context, Intent intent) 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
            context.startForegroundService(intent);
         else context.startService(intent);
    

我的服务扩展了 FlexibleFOregroundService,它在需要时启动前台通知:

public class FlexibleForegroundService extends Service 

    private static final String CHANNEL_ID = "test";

    @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        return null;
    

    @Override
    public void onCreate() 
        super.onCreate();
        makeServiceForegroundIfNeeded();
    

    public void stopService()
        stopSelf();
    

    private void makeServiceForegroundIfNeeded() 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
            createNotificationChannel();

            String message = "test";

            Notification notification =
                    new Notification.Builder(this, CHANNEL_ID)
                            .setContentTitle("test")
                            .setStyle(new Notification.BigTextStyle()
                                    .bigText(message))
                            .setContentText(message)
                            .setSmallIcon(R.mipmap.ic_launcher)
                            .build();

            startForeground(1, notification);
        
    


    private void createNotificationChannel() 
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Information", importance);
            channel.setDescription("test");
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        
    





有什么方法可以改善所有 Android 设备上的地理围栏工作吗?

【问题讨论】:

检查这个 repo github.com/vinayakb73/GeoFence-GeoFire 【参考方案1】:

我假设您已经知道您必须这样做的情况 Reregister geofences 每当用户禁用 GPS 时,您的地理围栏就会被注销。

我观察到,当您使用定位服务(例如打开地图时)时,您会更频繁地收到地理围栏事件。

您是否也可以尝试将“ACTION_GEOFENCE_TRANSITION”之类的操作放入清单文件内的接收者意图过滤器中。在创建待处理 Intent 时将其与操作相同。

【讨论】:

以上是关于并不总是触发带有 BroadcastReceiver 的地理围栏的主要内容,如果未能解决你的问题,请参考以下文章

WPF EventTrigger并不总是触发

可运行的Android if语句并不总是触发

以编程方式生成/激活的文件输入并不总是触发 `input` 事件

Application_Error 并不总是触发 ASP.NET

websocket并不总是在angularjs应用程序中触发onopen函数

MTAudioProcessingTap EXC_BAD_ACCESS ,并不总是触发 finalize 回调。如何释放它?