Геозона с BroadcastReceiver не всегда срабатывает - PullRequest
0 голосов
/ 22 октября 2018

Раньше, когда я использовал геозону в своем приложении, я использовал IntentService в качестве обратного вызова, и все было в порядке.Но теперь из-за изменений в Android 8 я больше не мог запускать такой сервис.Поэтому вместо этого теперь я использую BroadcastReceiver в качестве обратного вызова Geofencing, и этот приемник запускает службу (приоритетная для 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?

1 Ответ

0 голосов
/ 30 октября 2018

Я предполагаю, что вы уже знаете о случаях, когда вам нужно Перерегистрировать геозоны Ваши геозоны будут отменены при каждом отключении GPS пользователем.

Я заметил, что вы получаете геозонусобытия чаще, когда вы используете Location Services, например, когда карта открыта.

Можете ли вы также попробовать поместить действие типа "ACTION_GEOFENCE_TRANSITION" в фильтр намерений получателей внутри файла манифеста.Поместите то же самое как действие, когда вы создаете намерение в ожидании.

...