Mange av de populære værappene på Google Play er enten fulle av annonser, krever for mange tillatelser, eller inkluderer funksjoner som de fleste av oss aldri bruker. Ville det ikke vært bra hvis du kunne bygge din egen vær app fra grunnen av?
I denne opplæringen skal jeg vise deg hvordan. Vår app vil ha et enkelt og minimalistisk brukergrensesnitt, som viser brukeren nøyaktig hva de trenger å vite om dagens værforhold. La oss komme i gang.
Denne opplæringen vil lære deg å bygge en vær app fra begynnelsen, men ett alternativ er å bruke en av Android Weather App-malene på Envato Market.
For eksempel gir Weminder et enkelt, rent brukergrensesnitt og alle de viktigste funksjonene i et værprogram, slik at du kan tilpasse det til dine egne formål.
Weminder værmeldingsmal på Envato MarketEller, hvis du vil ha noe unikt og skreddersydd, gå over til Envato Studio for å se utvalget av mobil- og apputviklingstjenester som tilbys der.
Før du fortsetter, må du kontrollere at du har følgende konfigurasjon:
Jeg skal ringe denne appen SimpleWeather, men vær så snill å gi det noe navn du liker. Skriv inn et unikt pakke navn, angi minimumskrav til SDK til Android 2.2, og sett mål SDK til Android 4.4. Du kan forlate temaet på Holo Dark.
Denne appen vil bare ha en Aktivitet
og det vil være basert på Blank aktivitet mal som vist nedenfor.
Navn på Aktivitet
WeatherActivity. Vi bruker en Fragment
inne i dette Aktivitet
. Oppsettet knyttet til Aktivitet
er activity_weather.xml. Oppsettet knyttet til Fragment
er fragment_weather.xml.
Kopiere weathericons-vanlige-webfont.ttf til prosjektets eiendeler / skrifter katalog og endre navn på det til weather.ttf.
Den eneste tillatelsen denne appen trenger er android.permission.INTERNET
.
For å holde denne opplæringen enkel, skal vi bare støtte portrett modus. De aktivitet
node av manifestet skal se slik ut:
Det er ikke mye å forandre seg i activity_weather.xml. Det burde allerede ha a FrameLayout
. Legg til en ekstra egenskap for å endre fargen på bakgrunn
til # FF0099CC
.
Redigere fragment_weather.xml ved å legge til fem TextView
koder for å vise følgende informasjon:
Bruk en RelativeLayout
å ordne tekstvisningen. Du kan justere tekststørrelse
for å passe til forskjellige enheter.
Denne filen inneholder strenger som brukes i vår app, samt de Unicode-tegnkoder som vi skal bruke til å gjengi værsikoner. Søknaden vil kunne vise åtte forskjellige typer værforhold. Hvis du vil håndtere mer, så referer til dette cheat sheet. Legg til følgende til Verdiene / strings.xml:
Enkelt vær Bytt by 11111 & # Xf00d; & # Xf02e; & # Xf014; & # Xf013; & # Xf019; & # Xf01b; & # Xf01e; & # Xf01c; Beklager, ingen værdata funnet.
Brukeren skal kunne velge byen hvis vær de ønsker å se. Redigere meny / weather.xml og legg til et element for dette alternativet.
Nå som alle XML-filene er klare til bruk, la oss gå videre og spørre API-en for OpenWeatherMap for å hente værdata.
Vi kan få dagens værinformasjon om hvilken som helst by som er formatert som JSON ved hjelp av OpenWeatherMap API. I spørrekretsen passerer vi byens navn og det metriske systemet resultatene skal være i.
For eksempel, for å få dagens værinformasjon for Canberra, ved hjelp av metriske systemet, sender vi en forespørsel til http://api.openweathermap.org/data/2.5/weather?q=Canberra&units=metric
Svaret vi kommer tilbake fra API ser slik ut:
"base": "cmc stasjoner", "clouds": "alle": 90, "torsk": 200, "koord": "lat": -35.28, "lon": 149.13, "dt" : 1404390600, "id": 2172517, "main": "fuktighet": 100, "trykk": 1023, "temp": -1, "temp_max": -1, "temp_min": -1 ":" Canberra "," sys ":" land ":" AU "," melding ": 0.313," soloppgang ": 1404335563," solnedgang ": 1404370965," vær ": [ skyer "," ikon ":" 04n "," id ": 804," main ":" Clouds "]," vind ": " deg ": 305.004," fart ": 1,07
Opprett en ny Java-klasse og gi den navnet RemoteFetch.java. Denne klassen er ansvarlig for å hente værdata fra OpenWeatherMap API.
Vi bruker HttpURLConnection
klasse for å gjøre den eksterne forespørselen. OpenWeatherMap API forventer at API-nøkkelen i en HTTP-tittel heter x-api-key
. Dette er spesifisert i vår forespørsel ved hjelp av setRequestProperty
metode.
Vi bruker en BufferedReader
å lese APIs respons i a Stringbuffer
. Når vi har det komplette svaret, konverterer vi det til a JSONObject
gjenstand.
Som du kan se i svaret ovenfor, inneholder JSON-dataene et navn som heter torsk
. Dens verdi er 200
hvis forespørselen var vellykket. Vi bruker denne verdien for å sjekke om JSON-responsen har gjeldende værinformasjon eller ikke.
De RemoteFetch.java klassen skal se slik ut:
pakke ah.hathi.simpleweather; importer java.io.BufferedReader; importer java.io.InputStreamReader; importer java.net.HttpURLConnection; importer java.net.URL; importer org.json.JSONObject; importer android.content.Context; importer android.util.Log; offentlig klasse RemoteFetch privat statisk endelig streng OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric"; offentlig statisk JSONObject getJSON (Kontekst kontekst, String city) prøv URL url = ny URL (String.format (OPEN_WEATHER_MAP_API, by)); HttpURLConnection forbindelse = (HttpURLConnection) url.openConnection (); connection.addRequestProperty ("x-api-key", context.getString (R.string.open_weather_maps_app_id)); BufferedReader Reader = Ny BufferedReader (Ny InputStreamReader (Connection.getInputStream ())); StringBuffer json = ny StringBuffer (1024); string; mens ((tmp = reader.readLine ())! = null) json.append (tmp) .append ("\ n"); reader.close (); JSONObject data = nytt JSONObject (json.toString ()); // Denne verdien vil være 404 dersom forespørselen ikke var // vellykket hvis (data.getInt ("cod")! = 200) return null; returnere data; fangst (unntak e) return null;
Brukeren må ikke angi navnet på byen hver gang de vil bruke appen. Appen bør huske den siste byen brukeren var interessert i. Vi gjør dette ved å benytte SharedPreferences
. Men i stedet for å få direkte tilgang til disse innstillingene fra vår Aktivitet
klasse, er det bedre å lage en egen klasse for dette formålet.
Opprett en ny Java-klasse og gi den navnet CityPreference.java. For å lagre og hente navnet på byen, opprett to metoder setCity
og getCity
. De SharedPreferences
objektet initialiseres i konstruktøren. De CityPreference.java klassen skal se slik ut:
pakke ah.hathi.simpleweather; importer android.app.Activity; importer android.content.SharedPreferences; offentlig klasse CityPreference SharedPreferences prefs; offentlig byreferanse (aktivitetsaktivitet) prefs = activity.getPreferences (Activity.MODE_PRIVATE); // Hvis brukeren ikke har valgt en by ennå, returner // Sydney som standardby String getCity () return prefs.getString ("city", "Sydney, AU"); void setCity (String city) prefs.edit (). putString ("by", by) .commit ();
Opprett en ny Java-klasse og gi den navnet WeatherFragment.java. Dette fragmentet bruker fragment_weather.xml som sin oppsett. Erklære de fem TextView
objekter og initialiser dem i onCreateView
metode. Erklære en ny skriftsnitt
objekt som heter weatherFont
. De skriftsnitt
objektet vil peke på webfonten du lastet ned og lagret i eiendeler / skrifter mappe.
Vi vil benytte seg av en egen Tråd
å asynkront hente data fra OpenWeatherMap API. Vi kan ikke oppdatere brukergrensesnittet fra en slik bakgrunnstråd. Vi trenger derfor en handler
objekt, som vi initialiserer i konstruktøren til WeatherFragment
klasse.
offentlig klasse WeatherFragment utvider fragment Typeface weatherFont; TextView cityField; TextView updatedField; TextView detailsField; TextView currentTemperatureField; TextView weatherIcon; Handler handler; offentlig WeatherFragment () handler = new Handler (); @ Overstyr offentlig visning onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) Se rootView = inflater.inflate (R.layout.fragment_weather, container, false); cityField = (TextView) rootView.findViewById (R.id.city_field); updatedField = (TextView) rootView.findViewById (R.id.updated_field); detailsField = (TextView) rootView.findViewById (R.id.details_field); currentTemperatureField = (TextView) rootView.findViewById (R.id.current_temperature_field); weatherIcon = (TextView) rootView.findViewById (R.id.weather_icon); weatherIcon.setTypeface (weatherFont); returnere rootView;
Initialiser weatherFont
objekt ved å ringe createFromAsset
på skriftsnitt
klasse. Vi påberoper også updateWeatherData
metode i onCreate
.
@Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); weatherFont = Typeface.createFromAsset (getActivity (). getAssets (), "skrifter / weather.ttf"); updateWeatherData (new CityPreference (getActivity ()). getCity ());
I updateWeatherData
, Vi starter en ny tråd og ringer getJSON
på RemoteFetch
klasse. Hvis verdien returneres av getJSON
er null
, Vi viser en feilmelding til brukeren. Hvis det ikke er det, anvender vi renderWeather
metode.
Bare de viktigste Tråd
har lov til å oppdatere brukergrensesnittet til en Android-app. ringe Skål
eller renderWeather
direkte fra bakgrunnen tråden ville føre til en runtime feil. Det er derfor vi kaller disse metodene ved hjelp av behandleren
's post
metode.
privat ugyldig oppdateringWeatherData (siste trådby) ny tråd () offentlig tomgangsløp () endelig JSONObject json = RemoteFetch.getJSON (getActivity (), by); hvis (json == null) handler.post (new Runnable () public void run () Toast.makeText (getActivity (), getActivity (). getString (R.string.place_not_found), Toast.LENGTH_LONG) .show ();); else handler.post (new Runnable () public void run () renderWeather (json);); .start();
De renderWeather
Metoden bruker JSON-dataene til å oppdatere TextView
objekter. De vær
noden til JSON-responsen er en rekke data. I denne opplæringen bruker vi bare det første elementet i utvalg av værdata.
private void renderWeather (JSONObject json) prøv cityField.setText (json.getString ("navn"). toUpperCase (Locale.US) + "," + json.getJSONObject ("sys"). ; JSONObject detaljer = json.getJSONArray ("vær"). GetJSONObject (0); JSONObject main = json.getJSONObject ("main"); detailsFile.setText (detaljer.getString ("beskrivelse"). toUpperCase (Locale.US) + "\ n" + "Fuktighet:" + main.getString ("fuktighet") + "%" + "\ n" + "Trykk : "+ main.getString (" pressure ") +" hPa "); currentTemperatureField.setText (String.format ("%. 2f", main.getDouble ("temp")) + "℃"); DateFormat df = DateFormat.getDateTimeInstance (); String updatedOn = df.format (nytt dato (json.getLong ("dt") * 1000)); updatedField.setText ("Sist oppdatert:" + oppdatertOn); setWeatherIcon (detaljer.getInt ("id"), json.getJSONObject ("sys"). getLong ("soloppgang") * 1000, json.getJSONObject ("sys"). getLong ("solnedgang") * 1000); fangst (Unntak e) Log.e ("SimpleWeather", "Ett eller flere felt ikke funnet i JSON-dataene");
På slutten av renderWeather
metode, påberoper vi oss setWeatherIcon
med id
av det nåværende været samt tidene med soloppgang og solnedgang. Angi værikonet er litt vanskelig, fordi OpenWeatherMap API støtter flere værforhold enn vi kan støtte med nettfonten vi bruker. Heldigvis følger værmeldingene et mønster, som du kan lese mer om på OpenWeatherMap-nettsiden.
Slik kartlegger du et vær-id til et ikon:
R.string.weather_thunder
for disseR.string.weather_drizzle
for disseR.string.weather_rain
for demVi bruker soloppgang og solnedgangstider for å vise sol eller månen, avhengig av dagens tid og bare hvis været er klart.
privat tomt settWeatherIcon (int actualId, lang soloppgang, lang solnedgang) int id = actualId / 100; Stringikon = ""; hvis (actualId == 800) long currentTime = ny dato (). getTime (); hvis (currentTime> = soloppgang && currentTimeSelvfølgelig kan du takle flere værforhold ved å legge til flere
sak
uttalelser tilbytte om
uttalelse avsetWeatherIcon
metode.Til slutt legg til en
changeCity
metode til fragmentet for å la brukeren oppdatere den nåværende byen. DechangeCity
Metoden vil bare bli hentet fra hovedmenyenAktivitet
klasse.offentlig ugyldig forandring (String city) updateWeatherData (by);12. Rediger aktiviteten
Under prosjektets oppsett befolket Eclipse WeatherActivity.java med litt boilerplate kode. Erstatt standard implementering av
onCreate
metode med den nedenfor som vi brukerWeatherFragment
. DeonCreate
metoden skal se slik ut:@Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_weather); hvis (savedInstanceState == null) getSupportFragmentManager (). beginTransaction () .add (R.id.container, new WeatherFragment ()) .commit ();Deretter redigerer du
onOptionsItemSelected
metode og håndtere det eneste menyalternativet vi har. Alt du trenger å gjøre her er å påkalleshowInputDialog
metode.I
showInputDialog
metode, bruker viAlertDialog.Builder
å lage enDialog
objekt som ber brukeren om å skrive inn navnet på en by. Denne informasjonen sendes videre tilchangeCity
metode, som lagrer navnet på byen ved hjelp avCityPreference
klasse og kallerFragment
'schangeCity
metode.@Override public boolean onOptionsItemSelected (MenuItem item) if (item.getItemId () == R.id.change_city) showInputDialog (); returner falsk; private void showInputDialog () AlertDialog.Builder builder = ny AlertDialog.Builder (dette); builder.setTitle ("Bytt by"); Endelig EditText input = Ny EditText (dette); input.setInputType (InputType.TYPE_CLASS_TEXT); builder.setView (input); builder.setPositiveButton ("Go", ny DialogInterface.OnClickListener () @Override public void onClick (DialogInterface dialog, int som) changeCity (input.getText (). toString ());); builder.show (); offentlig ugyldig forandringCity (String city) WeatherFragment wf = (WeatherFragment) getSupportFragmentManager () .findFragmentById (R.id.container); wf.changeCity (by); Ny CityPreference (dette) .set City (by);Værmeldingen din er nå klar. Bygg prosjektet og distribuere det til en Android-enhet for testing.
Konklusjon
Du har nå et fullt funksjonelt værprogram. Du er velkommen til å utforske OpenWeatherMap API for å forbedre søknaden ytterligere. Du vil kanskje også bruke flere værsikoner, fordi vi for øyeblikket bare bruker en liten delmengde av dem.