Tworzenie i monitorowanie geofencingu

Geofencing łączy świadomość bieżącej lokalizacji użytkownika ze świadomością odległości od miejsc, które mogą Cię zainteresować. Aby oznaczyć lokalizację interesującej Cię lokalizacji, musisz określić jej szerokość i długość geograficzną. Aby dostosować bliskość dodaj promień. Szerokość, długość i promień wyznaczają geofencing, tworząc okrągłego obszaru lub ogrodzenia wokół wybranej lokalizacji.

Możesz mieć wiele aktywnych geofence z limitem 100 na aplikację na użytkownika urządzenia. Dla każdej wartości geofence, możesz poprosić usługi lokalizacyjne o wysyłanie zdarzeń wejścia i wyjścia, czas oczekiwania w obszarze geofencingu, czyli zamieszanie przed wywołaniem zdarzenia. Ty może ograniczyć czas trwania dowolnego geofence przez określenie czasu ważności w milisekundach. Gdy geofence wygaśnie, usługi lokalizacyjne automatycznie go usuną.

Ta lekcja pokazuje, jak dodawać i usuwać geofencing, a następnie nasłuchiwać przejść geofencingu za pomocą funkcji BroadcastReceiver.

Uwaga: na urządzeniach Wear interfejsy Geofencing API nie wykorzystują w efektywny sposób . Nie zalecamy korzystania z tych interfejsów API na Wear. Odczytano Oszczędzaj energię i baterię, aby dowiedzieć się więcej.

Skonfiguruj monitorowanie geofencingu

Aby poprosić o monitorowanie geofencingu, najpierw poproś o niezbędną uprawnień. Aby można było korzystać z geofencingu, aplikacja musi prosić o te uprawnienia:

Więcej informacji znajdziesz w przewodniku poprosić o dostęp do lokalizacji.

Jeśli chcesz użyć interfejsu BroadcastReceiver, aby nasłuchiwać przejść geofencingu, dodaj element określający nazwę usługi. Ten element musi być element podrzędny elementu <application>:

<application
   android:allowBackup="true">
   ...
   <receiver android:name=".GeofenceBroadcastReceiver"/>
<application/>

Aby uzyskać dostęp do interfejsów API lokalizacji, musisz utworzyć instancję Klient Geofencing. Aby dowiedzieć się, jak połączyć klienta:

Kotlin

lateinit var geofencingClient: GeofencingClient

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    geofencingClient = LocationServices.getGeofencingClient(this)
}

Java

private GeofencingClient geofencingClient;

@Override
public void onCreate(Bundle savedInstanceState) {
    // ...
    geofencingClient = LocationServices.getGeofencingClient(this);
}

Tworzenie i dodawanie geofence

Aplikacja musi utworzyć i dodać geofencje za pomocą klasy kreatora lokalizacji interfejsu API dla tworzenie obiektów Geofence i klasę wygodną do ich dodawania. Ponadto, aby obsłużyć intencje wysyłane z usług lokalizacyjnych przy przechodzeniu geofencingu, możesz zdefiniować PendingIntent jak pokazano w tej sekcji.

Uwaga: na urządzeniach jednego użytkownika obowiązuje limit 100 geofencingu na aplikację. W przypadku urządzeń, z których korzysta wielu użytkowników, limit wynosi 100 geofencji na aplikację na użytkownika.

Tworzenie obiektów geofence

Najpierw za pomocą funkcji Geofence.Builder utwórz geofence, ustawiając odpowiedni promień, czas trwania i typów przejść dla geofencingu. Aby na przykład wypełnić obiekt listy:

Kotlin

geofenceList.add(Geofence.Builder()
        // Set the request ID of the geofence. This is a string to identify this
        // geofence.
        .setRequestId(entry.key)

        // Set the circular region of this geofence.
        .setCircularRegion(
                entry.value.latitude,
                entry.value.longitude,
                Constants.GEOFENCE_RADIUS_IN_METERS
        )

        // Set the expiration duration of the geofence. This geofence gets automatically
        // removed after this period of time.
        .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)

        // Set the transition types of interest. Alerts are only generated for these
        // transition. We track entry and exit transitions in this sample.
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)

        // Create the geofence.
        .build())

Java

geofenceList.add(new Geofence.Builder()
    // Set the request ID of the geofence. This is a string to identify this
    // geofence.
    .setRequestId(entry.getKey())

    .setCircularRegion(
            entry.getValue().latitude,
            entry.getValue().longitude,
            Constants.GEOFENCE_RADIUS_IN_METERS
    )
    .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
            Geofence.GEOFENCE_TRANSITION_EXIT)
    .build());

Ten przykład pobiera dane z pliku stałych. W praktyce aplikacje mogą dynamicznie tworzyć granice geograficzne na podstawie lokalizacji użytkownika.

Określanie obszarów geograficznych i aktywatorów początkowych

Ten fragment kodu używa klasy GeofencingRequest i zagnieżdżonej klasy GeofencingRequestBuilder w Możesz określić obszary geograficzne, które mają być monitorowane, i określić sposób wywoływania powiązanych zdarzeń geofencingu:

Kotlin

private fun getGeofencingRequest(): GeofencingRequest {
    return GeofencingRequest.Builder().apply {
        setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
        addGeofences(geofenceList)
    }.build()
}

Java

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

Ten przykład pokazuje użycie 2 aktywatorów geofencingu. GEOFENCE_TRANSITION_ENTER przejście jest uruchamiane, gdy urządzenie znajdzie się w regionie geofencingu, a GEOFENCE_TRANSITION_EXIT przejście jest uruchamiane, gdy urządzenie opuści geofence. Określanie INITIAL_TRIGGER_ENTER informuje usługi lokalizacyjne, że GEOFENCE_TRANSITION_ENTER powinien zostać wyzwolony, jeśli urządzenie znajduje się już w obrębie geofencingu.

W wielu przypadkach lepiej jest użyć zamiast niego INITIAL_TRIGGER_DWELL, który wywołuje zdarzenia tylko wtedy, gdy użytkownik zatrzyma się na określony czas w obrębie geofencingu. Takie podejście może pomóc ograniczyć ilość spamu w alertach wynikające z powiadomień o dużej liczbie znaków, gdy urządzenie na chwilę włącza się i wyłącza funkcje geofence. Inną strategią uzyskiwania najlepszych wyników geofence to ustawienie minimalnego promienia 100 metrów. Pomaga to uwzględnić dokładność lokalizacji typowe sieci Wi-Fi, a także pomaga zmniejszyć zużycie energii przez urządzenie.

Zdefiniuj odbiornik na potrzeby przejść geofence

Intent wysłany z usług lokalizacyjnych może wywołać różne działania w aplikacji, ale nie należy uruchamiać jej aktywności ani fragmentów, ponieważ komponenty powinny być widoczne tylko w odpowiedzi na działanie użytkownika. W wielu przypadkach BroadcastReceiver to dobry sposób na obsługę przejść geofencingu. O BroadcastReceiver otrzymuje aktualizacje, gdy wystąpi zdarzenie, takie jak przejść do geofencingu lub z niego i może uruchomić długotrwałe działanie w tle; w naszej pracy.

Ten fragment kodu pokazuje, aby zdefiniować PendingIntent, który zaczyna się BroadcastReceiver:

Kotlin

class MainActivity : AppCompatActivity() {

    // ...

    private val geofencePendingIntent: PendingIntent by lazy {
        val intent = Intent(this, GeofenceBroadcastReceiver::class.java)
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
        // addGeofences() and removeGeofences().
        PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }
}

Java

public class MainActivity extends AppCompatActivity {

    // ...

    private PendingIntent getGeofencePendingIntent() {
        // Reuse the PendingIntent if we already have it.
        if (geofencePendingIntent != null) {
            return geofencePendingIntent;
        }
        Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
        // calling addGeofences() and removeGeofences().
        geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.
                FLAG_UPDATE_CURRENT);
        return geofencePendingIntent;
    }

Dodaj granice geograficzne

Aby dodać geofencje, użyj metody GeofencingClient.addGeofences(). Podaj obiekt GeofencingRequest i PendingIntent. Ten fragment kodu ilustruje przetwarzanie wyników:

Kotlin

geofencingClient?.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run {
    addOnSuccessListener {
        // Geofences added
        // ...
    }
    addOnFailureListener {
        // Failed to add geofences
        // ...
    }
}

Java

geofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
        .addOnSuccessListener(this, new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                // Geofences added
                // ...
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Failed to add geofences
                // ...
            }
        });

Obsługa przejść geofencingu

Gdy Usługi lokalizacyjne wykryją, że użytkownik włączył geofence lub go opuściła, wysyła pole Intent zawarte w PendingIntent które masz uwzględnione w prośbie o dodanie geofencingu. Odbiornik – np. Aplikacja GeofenceBroadcastReceiver zauważa, że został wywołany Intent, mogą następnie uzyskać z intencji zdarzenie geofencingu, określić typ przejść geofencingu, i określić, który ze zdefiniowanych obszarów geograficznych został aktywowany. Transmisja odbiorca może przekierować aplikację tak, aby rozpoczęła pracę w tle lub wyślij powiadomienie jako dane wyjściowe.

Uwaga: w Androidzie 8.0 (poziom interfejsu API 26) i nowszych, jeśli aplikacja która działa w tle podczas monitorowania geofencingu, odpowiada na zdarzenia geofencingu co kilka minut. Aby dowiedzieć się, jak się dostosować do tych limitów odpowiedzi, zobacz Informacje ogólne Limity lokalizacji.

Poniższy fragment kodu pokazuje, jak zdefiniować BroadcastReceiver który publikuje powiadomienie o przejściu geofencingu. Gdy użytkownik kliknie powiadomienie, pojawi się główna aktywność w aplikacji:

Kotlin

class GeofenceBroadcastReceiver : BroadcastReceiver() {
    // ...
    override fun onReceive(context: Context?, intent: Intent?) {
        val geofencingEvent = GeofencingEvent.fromIntent(intent)
        if (geofencingEvent.hasError()) {
            val errorMessage = GeofenceStatusCodes
                    .getStatusCodeString(geofencingEvent.errorCode)
            Log.e(TAG, errorMessage)
            return
        }

        // Get the transition type.
        val geofenceTransition = geofencingEvent.geofenceTransition

        // Test that the reported transition was of interest.
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER |
                geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

            // Get the geofences that were triggered. A single event can trigger
            // multiple geofences.
            val triggeringGeofences = geofencingEvent.triggeringGeofences

            // Get the transition details as a String.
            val geofenceTransitionDetails = getGeofenceTransitionDetails(
                    this,
                    geofenceTransition,
                    triggeringGeofences
            )

            // Send notification and log the transition details.
            sendNotification(geofenceTransitionDetails)
            Log.i(TAG, geofenceTransitionDetails)
        } else {
            // Log the error.
            Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
                    geofenceTransition))
        }
    }
}

Java

public class GeofenceBroadcastReceiver extends BroadcastReceiver {
    // ...
    protected void onReceive(Context context, Intent intent) {
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            String errorMessage = GeofenceStatusCodes
                    .getStatusCodeString(geofencingEvent.getErrorCode());
            Log.e(TAG, errorMessage);
            return;
        }

        // Get the transition type.
        int geofenceTransition = geofencingEvent.getGeofenceTransition();

        // Test that the reported transition was of interest.
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

            // Get the geofences that were triggered. A single event can trigger
            // multiple geofences.
            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();

            // Get the transition details as a String.
            String geofenceTransitionDetails = getGeofenceTransitionDetails(
                    this,
                    geofenceTransition,
                    triggeringGeofences
            );

            // Send notification and log the transition details.
            sendNotification(geofenceTransitionDetails);
            Log.i(TAG, geofenceTransitionDetails);
        } else {
            // Log the error.
            Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
                    geofenceTransition));
        }
    }
}

Po wykryciu zdarzenia przejścia za pomocą interfejsu PendingIntent BroadcastReceiver otrzymuje typ przejścia geofencingu, sprawdza, czy jest to jedno ze zdarzeń używanych przez aplikację do wywoływania powiadomień – albo GEOFENCE_TRANSITION_ENTER lub GEOFENCE_TRANSITION_EXIT w tej sprawie. Usługa następnie wysyła powiadomienie i zapisuje szczegóły przejścia.

Zatrzymaj monitorowanie geofencingu

Wyłączenie monitorowania geofencingu, gdy nie jest już potrzebne lub potrzebne, może pomóc oszczędzać baterię i cykli pracy procesora. Możesz zatrzymać monitorowanie geofencingu w głównej aktywności używanej do dodawania i usuwania geofencingu; usunięcie geofencingu zatrzymuje natychmiast. Interfejs API udostępnia metody usunąć granice geograficzne według identyfikatorów żądań lub poprzez usunięcie obszarów geograficznych związanych z danym zapytaniem, PendingIntent

Ten fragment kodu usuwa geofence przez PendingIntent, wstrzymując wszystkie dalsze powiadomienia, gdy urządzenie wejdzie w życie lub je opuści:

Kotlin

geofencingClient?.removeGeofences(geofencePendingIntent)?.run {
    addOnSuccessListener {
        // Geofences removed
        // ...
    }
    addOnFailureListener {
        // Failed to remove geofences
        // ...
    }
}

Java

geofencingClient.removeGeofences(getGeofencePendingIntent())
        .addOnSuccessListener(this, new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                // Geofences removed
                // ...
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Failed to remove geofences
                // ...
            }
        });

Geofencing możesz połączyć z innymi funkcjami wykorzystującymi lokalizację, na przykład okresowymi aktualizacjami lokalizacji. Więcej informacji znajdziesz w innych lekcjach tych zajęć.

Korzystanie ze sprawdzonych metod dotyczących geofencingu

W tej sekcji znajdziesz zalecenia dotyczące używania geofencingu w lokalizacji. Interfejsy API na Androida.

Zmniejsz zużycie energii

Aby zoptymalizować zużycie energii w aplikacjach korzystających z geofencingu, możesz skorzystać z tych metod:

  • Ustaw reagowania na powiadomienia na wyższą wartość. Pozwala to zmniejszyć zużycie energii, ponieważ zwiększając czas oczekiwania na alerty geofencingu. Jeśli np. ustawisz wartość responsywności na pięć a aplikacja sprawdza alert wejścia i wyjścia co 5 minut. Ustawienie niższych wartości nie musi oznaczać, że użytkownicy będą powiadamiani w danym okresie (Na przykład jeśli ustawisz wartość 5 sekund, otrzymanie kodu może potrwać trochę dłużej alert).

  • ustawić większy promień geofencingu w lokalizacjach, w których użytkownik spędza dużo czasu; takich jak dom lub praca. Większe promienie nie zmniejszają bezpośrednio zużycia energii, ale zmniejszają częstotliwość, z jaką aplikacja sprawdza wejście lub wyjście z aplikacji, co skutecznie obniża ogólną moc baterii konsumpcją treści.

Wybierz optymalny promień dla geofencingu

Aby uzyskać najlepsze wyniki, minimalny promień geofencingu powinien wynosić od 100 do 150 metrów. Gdy dostępna jest sieć Wi-Fi, dokładność lokalizacji wynosi zwykle 20–50 metrów. W pomieszczeniu lokalizacja jest dostępna, dokładność może wynosić maksymalnie 5 metrów. Chyba że wiesz, że wewnątrz budynku lokalizacja jest dostępna w obrębie geofencingu, załóżmy, że dokładność lokalizacji Wi-Fi jest 50 metrów.

Jeśli sieć Wi-Fi jest niedostępna (np. jedziesz samochodem na obszarze wiejskim), dokładność lokalizacji jest mniejsza. Zakres dokładności może wynosić od kilkuset metrów kilka kilometrów. W takich przypadkach należy utworzyć granice geograficzne, korzystając z większego promienia.

Wyjaśnij użytkownikom, dlaczego Twoja aplikacja używa geofencingu

Podczas korzystania z geofencingu aplikacja uzyskuje dostęp do lokalizacji w tle, zastanów się, jak Twoja aplikacja przynosi korzyści użytkownikom. Wyjaśnij dziecku, dlaczego. aplikacja potrzebuje tego dostępu, aby zwiększyć przejrzystość i zrozumienie użytkowników.

Aby dowiedzieć się więcej o sprawdzonych metodach dostępu do lokalizacji, w tym geofencing, zobacz najlepszą ochronę prywatności metod weryfikacji danych.

Używanie typu przejścia bez kontaktu w celu ograniczenia spamu w alertach

Jeśli podczas krótkiej przejeżdżania obok geofencingu otrzymujesz dużą liczbę alertów, zmniejsz liczbę alertów, użyj typu przejścia GEOFENCE_TRANSITION_DWELL zamiast GEOFENCE_TRANSITION_ENTER. Dzięki temu alert dotyczący miejsca zamieszkania jest wysyłany tylko wtedy, gdy użytkownik przestaje działać. w obrębie geofencingu w danym okresie. Aby wybrać czas trwania, ustaw opóźnienia w ruchu.

Ponowna rejestracja geofencingu tylko wtedy, gdy jest to wymagane

Zarejestrowane granice geograficzne są przechowywane w procesie com.google.process.location, którego właścicielem jest pakiet com.google.android.gms. Aplikacja nie musi nic robić do obsługi tych zdarzeń, bo system przywraca geofencje po tych zdarzeniach:

  • Usługi Google Play zostały uaktualnione.
  • Usługi Google Play są wyłączane i uruchamiane ponownie przez system z powodu ograniczenia zasobów.
  • Proces lokalizacji ulega awarii.

Aplikacja musi ponownie zarejestrować geofencing, jeśli są nadal potrzebne po tych wydarzeniach, ponieważ system nie może przywrócić geoferencji w tych przypadkach:

  • Urządzenie zostało zrestartowane. Aplikacja powinna nasłuchiwać zakończenia uruchamiania urządzenia, a następnie – zarejestrować wymagane geofence.
  • Aplikacja zostanie odinstalowana i zainstalowana ponownie.
  • Dane aplikacji zostaną wyczyszczone.
  • Dane Usług Google Play zostały wyczyszczone.
  • Aplikacja otrzymała GEOFENCE_NOT_AVAILABLE alert. Zwykle dzieje się tak po wyłączeniu NLP (dostawcy lokalizacji sieciowej na Androida).

Rozwiązywanie problemów ze zdarzeniem wejścia do geofencingu

Jeśli geofencing nie jest wyzwalany, gdy urządzenie wchodzi w interakcję z funkcją geofencingu (alert GEOFENCE_TRANSITION_ENTER nie jest wyzwalany), najpierw upewnij się, że granice geograficzne są prawidłowo zarejestrowane, tak jak to opisano w tym przewodniku.

Oto kilka możliwych powodów, dla których alerty nie działają zgodnie z oczekiwaniami:

  • W obrębie Twojego geofencingu nie jest dostępna dokładna lokalizacja lub geofence też jest niedostępne Na większości urządzeń usługa geofence używa tylko lokalizacji sieciowej na potrzeby geofencingu które wywołujące stres. Usługa stosuje tę metodę, ponieważ lokalizacja sieciowa zużywa znacznie mniej energia elektryczna, dojazd do wybranych lokalizacji zajmuje mniej czasu, a co najważniejsze, jest dostępne wewnątrz budynków.
  • Wi-Fi na urządzeniu jest wyłączone. Włączenie Wi-Fi może znacznie poprawić jakość połączenia dokładności lokalizacji, więc jeśli Wi-Fi jest wyłączone, aplikacja może nie otrzymywać alertów geofence. w zależności od różnych ustawień, w tym promienia geofencingu, modelu urządzenia lub Wersja Androida. Począwszy od Androida 4.3 (poziom API 18) dodaliśmy możliwość skanowania Wi-Fi „tylko tryb”, który pozwala użytkownikom wyłączyć Wi-Fi, ale nadal korzystać z dobrej lokalizacji sieciowej. To dobrze ćwiczenie promptów i udostępniania mu skrótu umożliwiającego włączenie tylko skanowania Wi-Fi lub Wi-Fi , jeśli oba tryby są wyłączone. Użyj formatu SettingsClient, aby zapewnić odpowiednią konfigurację ustawień systemowych urządzenia. wykrywanie lokalizacji.

    Uwaga: jeśli aplikacja jest kierowana na Androida 10 (poziom interfejsu API 29) lub wyżej, nie można zadzwonić bezpośrednio pod numer WifiManager.setEnabled(), Twoja aplikacja jest aplikacją systemową lub zasadami dotyczącymi urządzeń (DPC). Zamiast tego użyj panelu ustawień.

  • W obrębie geofencingu nie ma niezawodnego połączenia sieciowego. Jeśli Brak niezawodnego połączenia do transmisji danych, mogą nie być generowane alerty. Dzieje się tak, ponieważ usługa geofence zależy od operatora lokalizacji, co z kolei wymaga połączenia transmisji danych.
  • Alerty mogą być opóźnione. Usługa geofencingu nie wysyła stale zapytań lokalizacji, więc alerty mogą pojawić się z opóźnieniem. Zazwyczaj opóźnienie jest mniejsze niż 2. nawet mniej, gdy urządzenie jest w ruchu. Jeśli Informacje ogólne Obowiązują limity lokalizacji. Opóźnienie wynosi średnio 2–3 minuty. Jeśli urządzenie było nieruchome przez dłuższy czas, opóźnienie może wzrosnąć (do 6 minut).

Dodatkowe materiały

Więcej informacji o geofencingu znajdziesz w tych materiałach:

Próbki

Przykładowa aplikacja do tworzenia i monitorowania obszarów geograficznych.