Google, API, klucze i limity, Android.

0

Naszło mnie wczoraj na przemyślenia na temat kluczy do API Google i narzuconych limitów.
W aplikacji korzystam z serwisów google (dokładnie to Google Maps Elevation API które wymaga klucza, oraz kilku innych API, standardowych i w żaden sposób nielimitowanych), i niemiło zorientowałem się wczoraj po sprawdzeniu konsoli developerskiej, że na GM Elevation jest narzucony globalny limit zapytań 2500/dzień/klucz (jak przekroczysz to płać, albo odcinamy dostęp do serwisu).
W aplikacji używałem tego serwisu żeby otrzymać bardzo dokładną informację o wysokości nad poziomem morza (na zasadzie podania latitude i longitude z GPS, i dla tych wartości otrzymania wyniku zwrotnego z wartością elevation). Podyktowane było to tym, że wartości wysokości z GPS/LocationServices są strasznie niedokładne, ale za to zwracają (mniej więcej) dokładną długość i szerokość geograficzną. Nie miałem jeszcze sytuacji przekroczenia limitu, ale jestem jednym użytkownikiem z jednym urządzeniem. Ostatecznie chciałem wypuścić aplikację do sklepu, z ficzerami jak zapisywanie do baz danych, ściąganie jako plik, za darmo i bez żadnych bzdetnych reklam itp., jednak już kilka(naście) osób łatwo przekroczy granicę 2500 zapytań/dzień.
Powiem szczerze, że szukałem tego wczoraj całe popołudnie oraz sporą część nocy, i nie znalazłem konkretnych odpowiedzi.
Piszę oczywiście o Androidzie, nie o web serwisach, stronach itp.

Pytania:

  1. Czy może źle rozumiem użytkowanie tych kluczy i odnoszą się one na zasadzie 2500 zapytań/użytkownik? Jeśli da się tak, to jak do tego podejść?
  2. Co stałoby się gdyby w ogóle nie używać klucza w żądaniu? Sprawdziłem sobie teraz z ciekawości i wszystko działa, na konsoli developerskiej nie wyskakuje mi żadne naliczanie nowych żądań. Czy w takiej sytuacji jest to naliczane względem IP? Czegoś innego?
  3. Jak w ogóle ugryźć temat ciągłego (możliwie jak najdokładniejszego, kilka razy na minutę) aktualizowania danych o wysokości?

Ktokolwiek widział ktokolwiek wie? :)

EDIT: dodaję jeszcze trochę kodu, żeby było jaśniejsze do zrozumienia o co pytam. Komentarze PL dodałem teraz.
Otrzymywanie aktualizacji nowych lokalizacji z GPS:

 
// konstruktor mojego location listenera (korzysta z GoogleApiClient), nie rozwijam tutaj tego dalej, bo są tam standardowe metody (zbudowanie, połączenie z serwisem)
    public GoogleLocationListener() {
        buildGooglePlayService();
        connectGoogleAPIClient();
    }

// po kliknięciu PLAY budowane jest zapytanie/żądanie o aktualizację lokalizacji (ustawia się tam kilka parametrów, takich jak odstęp czasu między kolejnymi żądaniami, dokładność itp)
    @Override
    public void startListenForLocations() {
        // set location request
        LocationRequest locationRequest = new LocationRequest();
        locationRequest = setLocationRequest(locationRequest);

        // build request settings
        LocationSettingsRequest.Builder builder =
                new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);

        // tutaj sprawdzane są pozwolenia, od Android API 23 otrzymywanie aktualizacji lokalizacji wymaga tego rodzaju sprawdzenia
        // check for location permissions
        checkLocationPermissions(mContext, locationRequest);
    }

// sprawdzenie czy aplikacja otrzymała pozwolenia i wykonanie jakiejś akcji (ja dodaję tam żądanie do wykonania)
    private void checkLocationPermissions(@NonNull Context context, LocationRequest locationRequest) {
        // check for location permissions (required in android API 23 and above)
        if ("BARDZO DŁUGI KILKULINIJKOWY WARUNEK")
        } else {
            // remove old location request and add new one
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
        }
    }

// później przy zmianie lokalizacji przekaż ją dalej za pomocą callback
    @Override
    public void onLocationChanged(Location location) {
        mCallback.onNewLocationFound(location);
    }

O samym GPS tyle. Lokalizacja ma względnie dokładną latitude i longitude, ale elevation/altitude jest żałośnie niedokładna (brana na żywca, może da się porobić jakieś przeliczenia na dokładniejszy wynik-> nie wiem)

Później, mając latitude i longitude chciałem skorzystać z serwisu Google Maps Elevation na zasadzie wyciągnięcia wysokości z mapy dla tego punktu koordynacyjnego przy wykorzystaniu AsyncTask. Streszczając:
standardowe połączenie za pomocą HttpURLConnection w doInBackground() i otrzymanie zwrotnych danych dla danej lokalizacji w formacie JSON:

 {
   "results" : [
      {
         "elevation" : 1608.637939453125,
         "location" : {
            "lat" : 39.73915360,
            "lng" : -104.98470340
         },
         "resolution" : 4.771975994110107
      }
   ],
   "status" : "OK"
}

Z powyższego wyciągałem sobie wartość "elevation" i gitara. Mam bardzo dokładną wartość, gdy w tym samym czasie GPS zwracał wartości +/-30 metrów, albo w ogóle zero.
Cały ten kod dodałem tylko poglądowo. Sens tego tematu to początek + te trzy pytania:).
Ciekaw jestem czy ktoś z zajmujących się Androidem miał w ogóle tutaj do czynienia z takim problemem.

1
  1. Limit jest na klucz
  2. Nie ma żadnej gwarancji, że będzie działać. Zapytanie bez api key jest zapewne ograniczone jakimś globalnym limitem.
  3. Musiałbyś korzystać z wysokościomierza barometrycznego. Wiele sportowych zegarków posiada takowe.
0
Haskell napisał(a):
  1. Limit jest na klucz
  2. Nie ma żadnej gwarancji, że będzie działać. Zapytanie bez api key jest zapewne ograniczone jakimś globalnym limitem.
  3. Musiałbyś korzystać z wysokościomierza barometrycznego. Wiele sportowych zegarków posiada takowe.

Dzięki za odpowiedź.
Z tego co znalazłem wychodzi na to, że w moim przypadku najlepszym rozwiązaniem będzie zastosowanie GPS + barometr.
O barometrze nie wiem jeszcze nic, więc najpierw zajmę się poprawieniem GPS.
Zniechęciło mnie w GPS to, że zwracał wartość +40metrów w stosunku do tego co powinno być, ale po poszukiwaniach znalazłem info, że Android Location z GPS to goła wartość dla Elipsoidy WGS-84 (mapa średniej wysokości poziomu morza... lol, a myślałem, że nigdy mi się studia nie przydadzą - wiem co to jest ;d).
Tak więc, muszę zastosować algorytm/bibliotekę do uwzględnienia Geoidy (prawdziwy średni poziom morza (lokalnie)) i poprawienia wyniku GPS.
Sprawdziłem sobie na przykładzie mojej lokacji, gdzie mam +160m n.p.m.. Gps zwraca +198m ale po wklepaniu długości, szerokości geograficznej oraz 198m do internetowych kalkulatorów, zwracały mi wartość +165m n.p.m. Tak więc w granicach akceptacji.
Teraz tylko jak to wklepać do projektu? Mam nadzieję, że nie jest to porywanie się z motyką na słońce i są jakieś biblioteki, albo algorytm jest w miarę do zrozumienia.

Jakby ktoś chciał poczytać o czym tutaj bełkoczę:
http://www.unavco.org/education/resources/tutorials-and-handouts/tutorials/geoid-gps-receivers.html
http://www.unavco.org/education/resources/tutorials-and-handouts/tutorials/elevation-and-geoid.html

0
  1. z tego co czytałem to jest limit na minimalny czas pomiędzy zapytaniami
0

Jakby kogoś interesowało, to w celu korekty wartości WGS84 GPS z Android można zastosować tego rodzaju kod.
https://github.com/barbeau/earth-gravitational-model

Postanowiłem zrobić tak:

  1. (do zrobienia) dorzucę wykorzystanie sensorów barometru z urządzenia w celu zmierzenia wysokości
  2. GPS: (właściwą wartość count ustawię sobie eksperymentalnie, teraz jest byle co; PL dodane teraz żeby się ktoś nie czepiał o PolEnglish:)
     @Override
    public void onLocationChanged(Location location) {
        if (location.getAltitude() == 0) {
            // jeśli GPS nie może znaleźć wysokości to zwraca wartość double 0, nie null
            // try to get correct GPS with non-zero altitude several times; if failed call for Google Map Elevation API
            count++;
            if (count > 20) {
                //w callbacku dodałem sobie boolean czy mam wartość altitude z GPS, czy może chcę skorzystać z serwisów Web (przypominam, że serwisy są limitowane:))
                mCallback.onNewLocationFound(location, true);
                count = 0;
            }
        } else {
            //wywołanie korekty wysokości z GPS z wykorzystaniem algorytmu z gita do którego link wstawiłem
            location = fixGpsAltitude(location);
            mCallback.onNewLocationFound(location, false);
            count = 0;
        }
    }
  1. Wpadłem też na pomysł, żeby poszukać kilku serwisów/API w których można pobrać dokładną wysokość. Nic nie stoi na przeszkodzie, żebym w przypadku niedostępności jednego serwisu z powodu przekroczenia limitu, nie zaczął wysyłać żądań do następnego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1