Å vite brukerens posisjon er nyttig informasjon i mange applikasjoner vi utvikler og bruker i dag. Det er mange populære stedsbaserte applikasjoner der ute som gjør livene våre enklere, i tillegg til å endre måten vi bruker disse tjenestene på. Et eksempel er den veldig populære applikasjonen Foursquare, der brukere som besøker et etablissement og 'sjekker inn' ofte får rabatter. Uber, som hjelper deg med å få en kjøretur fra mobiltelefonen til en lavere pris enn en vanlig taxi. Listen er stor og vokser fremdeles.
I denne artikkelen skal vi bygge en enkel Android-applikasjon for å bestemme brukerens bredde og lengdegrad ved hjelp av Android’s Google Location Services API. Når utvikle Android-applikasjoner , det er et par måter å få brukerens plassering på.
De pakke “android.location” har vært tilgjengelig siden Android ble introdusert for første gang, og det gir oss tilgang til lokasjonstjenester. Disse tjenestene lar applikasjoner få periodiske oppdateringer av enhetens geografiske beliggenhet.
Pakken gir to måter å skaffe stedsdata på:
LocationManager.GPS_PROVIDER: Bestemmer plassering ved hjelp av satellitter. Avhengig av forholdene, kan det hende at denne leverandøren tar litt tid å returnere en lokalitetsreparasjon.
LocationManager.NETWORK_PROVIDER: Bestemmer beliggenhet basert på tilgjengeligheten til nærliggende celletårn og WiFi-tilgangspunkter. Dette er raskere enn GPS_PROVIDER.
Når du leter etter brukerplassering, må du spille med disse leverandørene og deres tilgjengelighet. Ideelt sett får du den første plasseringen ved hjelp av NETWORK_PROVIDER, som kanskje ikke er like nøyaktig, men som er mye raskere. Du kan da gjøre et forsøk på å øke nøyaktigheten ved å lytte etter en bedre plassering ved hjelp av GPS_PROVIDER.
API-ene som tilbys av denne pakken, er ganske lave, og krever at utvikleren av applikasjonen håndterer de finere detaljene for å bestemme når du skal be om lokasjonsdata og planlegge anrop til API på en optimalisert måte. For å forbedre utvikleropplevelsen med stedsbaserte systemtjenester og lette prosessen med å utvikle stedsbevisste applikasjoner, introduserte Google en ny måte å be om brukerens plassering ved hjelp av Google Play Services. Den tilbyr en enklere API med høyere nøyaktighet, geofencing med lite strøm og mye mer.
Google Location Services API, også kjent som FusedLocationProviderApi, er Googles anbefalte måte å få brukerens plassering på. Det gir best nøyaktighet basert på våre behov. Noen av fordelene ved å bruke denne API-en i forhold til den forrige er:
Enkelhet: I motsetning til forrige API trenger du ikke lenger å håndtere flere leverandører. I stedet spesifiserer du behov på høyt nivå, for eksempel “høy nøyaktighet” eller “lav effekt”, og det vil ta en passende tilnærming.
Tilgjengelighet: Gir appen din øyeblikkelig tilgang til det beste, siste kjente stedet. Vanligvis er denne informasjonen lett tilgjengelig, du må bare be om den.
Strømeffektivitet: Minimerer applikasjonens strømforbruk.
Allsidighet: Oppfyller et bredt spekter av behov, fra forgrunnsbruk - som krever svært nøyaktige posisjonsdata, til bakgrunnsbruk - som kun krever periodiske plasseringsoppdateringer med ubetydelig kraftpåvirkning.
La oss bygge en stedsbasert Android-applikasjon ved hjelp av dette API-et. For dette vil vi bruke Googles foreslåtte IDE for Android-applikasjonsutvikling - Android Studio . Komme i gang med Android Studio er ganske rett frem. Nettstedet deres beskriver prosedyren som involverer installasjon og konfigurasjon av Android Studio i detalj, inkludert hvordan du starter opp din første Android-applikasjon for utvikling.
Android Studio burde gjøre ting superenkelt for oss. Vi må imidlertid begynne med å konfigurere build-skriptet og legge til Google Play Services som en avhengighet for denne applikasjonen. Dette kan gjøres ved å endre 'build.gradle' -filen som følger:
dependencies { compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.google.android.gms:play-services:6.5.87' // Add this line }
Da jeg skrev denne artikkelen, er den siste versjonen av Google Play Services tilgjengelig 6.5.87. Sørg for at du alltid ser etter den nyeste versjonen som er tilgjengelig før du begynner. Hvis nyere versjoner kommer ut senere på veien, og du bestemmer deg for å oppdatere den for dine egne prosjekter, kan du teste alle stedsrelaterte funksjoner mot alle versjoner av Android du støtter.
På dette tidspunktet skal vi kunne begynne å gjøre det faktiske arbeidet for søknaden vår.
Androids har spesifikke sikkerhetsfunksjoner som forhindrer enhver vilkårlig applikasjon fra å be om en presis brukerplassering. For å løse dette, må vi redigere “AndroidManifest.xml” og legge til tillatelse vi trenger for denne applikasjonen:
private boolean checkGooglePlayServices(){ int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(mContext); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * Google Play Services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, mContext, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; }
Mens vi er i gang, bør vi også definere versjonen av Google Play Services vi bruker for denne applikasjonen:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(mContext, 'Google Play Services must be installed.', Toast.LENGTH_SHORT).show(); finish(); } } }
Før vi får tilgang til funksjonene fra Google Play Services, må vi sjekke om enheten har Google Play Services installert, og at versjonen er den vi har tenkt å bruke (6.5.87).
protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); }
Denne metoden vil sjekke for Google Play Services, og i tilfelle enheten ikke har den installert (det er sjelden, men jeg har sett slike tilfeller), vil den åpne en dialog med den tilsvarende feilen og invitere brukeren til å installere / oppdatere Google Play-tjenester fra Google Play-butikken.
Etter at brukeren har fullført oppløsningen fra “GooglePlayServicesUtil.getErrorDialog ()”, blir en tilbakeringingsmetode “onActivityResult ()” utløst, så vi må implementere litt logikk for å håndtere den samtalen:
package com.bitwoo.userlocation; import android.content.Intent; import android.location.Location; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; public class MainActivity extends ActionBarActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static int REQUEST_CODE_RECOVER_PLAY_SERVICES = 200; private GoogleApiClient mGoogleApiClient; private Location mLastLocation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkGooglePlayServices()) { buildGoogleApiClient(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private boolean checkGooglePlayServices() { int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(this); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * google play services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, this, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(this, 'Google Play Services must be installed.', Toast.LENGTH_SHORT).show(); finish(); } } } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } }
For å få tilgang til Google API-er, trenger vi bare å utføre ett trinn til: lage en forekomst av GoogleApiClient. Google API-klienten gir et felles inngangspunkt til alle Google Play-tjenestene, og administrerer nettverkstilkoblingen mellom brukerens enhet og hver Google-tjeneste. Vårt første skritt her er å starte forbindelsen. Jeg kaller vanligvis denne koden fra 'onCreate' -metoden for aktiviteten:
@Override protected void onStart() { super.onStart(); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } }
Ved å kjede en serie metodesamtaler, spesifiserer vi implementeringen av tilbakeringingsgrensesnittet og Location Service API som vi vil bruke. Grensesnittimplementeringen, i dette tilfellet 'dette', vil få svar på den asynkrone 'connect ()' -metoden når forbindelsen til Google Play Services lykkes, mislykkes eller blir suspendert. Etter å ha lagt til denne koden, bør vår 'MainActivity' se slik ut:
@Override public void onConnected(Bundle bundle) { mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient); if (mLastLocation != null) { Toast.makeText(this, 'Latitude:' + mLastLocation.getLatitude()+', Longitude:'+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } }
Så i vår 'onStart' -metode kaller vi 'connect' -metoden og venter på 'onConnected' tilbakeringingsmetode:
protected void createLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(20000); mLocationRequest.setFastestInterval(5000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }
Metoden “onConnected” vil se slik ut:
protected void startLocationUpdates() { LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, this); }
Denne tilbakeringingen utløses når Google Play Services er koblet til, noe som betyr at da skal vi ha det sist kjente stedet. Denne plasseringen kan imidlertid være null (det er sjelden, men ikke umulig). I så fall er det jeg anbefaler å lytte etter stedsoppdateringer som dekkes videre.
Etter at du har påkalt 'getLastLocation', vil du kanskje be om periodiske oppdateringer fra Fused Location Provider. Avhengig av søknaden din, kan denne perioden være kort eller lang. For eksempel, hvis du bygger et program som sporer brukerens posisjon mens han kjører, må du lytte etter oppdateringer med korte intervaller. På den annen side, hvis søknaden din handler om å dele brukerplasseringen med sin venn, trenger du kanskje bare å be om plasseringen en gang i blant.
Å lage en forespørsel er ganske enkelt - du kan kalle denne metoden i 'onCreate' -metoden:
public class MainActivity extends ActionBarActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // ... @Override public void onLocationChanged(Location location) { mLastLocation = location; Toast.makeText(this, 'Latitude:' + mLastLocation.getLatitude()+', Longitude:'+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } }
Vi starter et nytt LocationRequest gjenstand. Sett intervallet til 20 sekunder (20000 millisekunder). Videre setter vi en senket oppdateringshastighet til 5 sekunder. Dette ber APIen om å tilby oppdateringer hvert 20. sekund (helst), men hvis det er en endring tilgjengelig innen en periode på 5 sekunder, bør den også gi det. Til slutt satte vi prioriteten til “ PRIORITY_HIGH_ACCURACY ”, Blant de andre tilgjengelige prioritetsalternativene: PRIORITY_BALANCED_POWER_ACCURACY , PRIORITY_LOW_POWER , PRIORITY_NO_POWER .
Når du har laget forespørselen, er du klar til å begynne å lytte på stedsoppdateringer etter at “onConnected ()” -metoden er utløst:
protected void stopLocationUpdates() { if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates( mGoogleApiClient, this); } }
Alt som gjenstår nå er å implementere tilbakeringingsmetoden for å tilfredsstille LocationListener grensesnitt:
@Override protected void onStop() { super.onStop(); if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } }
Det er viktig å eksplisitt slutte å lytte etter oppdateringer når du ikke trenger dem lenger, eller hvis brukeren forlater applikasjonen. Følgende metode skal påkalles fra 'onPause' tilbakeringing:
|_+_|
... og koble fra Google API:
Som du kan se, er de grunnleggende ideene bak implementering av stedsbevisste applikasjoner i Android veldig enkle. Videre, med tilgjengelige API-er som både er enkle å bruke og enkle å forstå, bør det være en no-brainer å bygge grunnleggende stedsbaserte applikasjoner for Android. Den lille prøveapplikasjonen vi har bygd her, er ment for å demonstrere akkurat det. Du kan finne den komplette kildekode for dette på GitHub . Vær oppmerksom på at for å gjøre ting enkelt, håndterer ikke applikasjonen “onConnectionFailed” tilbakeringingsmetoden.
Forhåpentligvis vil denne opplæringen hjelpe deg med å komme i gang med å bruke Google Location Services API.