Molte delle app meteo più diffuse su Google Play sono piene di annunci, richiedono troppe autorizzazioni o includono funzionalità che la maggior parte di noi non usa mai. Non sarebbe bello se tu potessi costruire da zero la tua app meteo?
In questo tutorial, ti mostrerò come. La nostra app avrà un'interfaccia utente semplice e minimalista, che mostra all'utente esattamente ciò che è necessario sapere sulle condizioni meteorologiche attuali. Iniziamo.
Questo tutorial ti insegnerà a costruire un'app meteo da zero, ma un'alternativa è quella di utilizzare uno dei modelli di app meteo per Android sul mercato Envato.
Ad esempio, Weminder fornisce un'interfaccia utente semplice e pulita e tutte le funzionalità essenziali di un'app meteo, in modo che tu possa personalizzarla per i tuoi scopi.
Modello di app meteo Weminder sul mercato EnvatoOppure, se vuoi qualcosa di unico e costruito su misura, vai su Envato Studio per dare un'occhiata alla selezione di servizi di sviluppo di app per dispositivi mobili offerti qui.
Prima di continuare, controlla di avere la seguente configurazione:
Chiamerò questa app SimpleWeather, ma sentiti libero di dargli un nome che ti piace. Immettere un nome pacchetto univoco, impostare l'SDK minimo richiesto su Android 2.2, e impostare l'SDK di destinazione su Android 4.4. Puoi lasciare il tema a Holo Dark.
Questa app ne avrà solo una Attività
e sarà basato sul Attività vuota modello come mostrato di seguito.
Dai il nome a Attività
WeatherActivity. Useremo un Frammento
dentro questo Attività
. Il layout associato al Attività
è activity_weather.xml. Il layout associato al Frammento
è fragment_weather.xml.
copia weathericons-regular-webfont.ttf al tuo progetto attività / font directory e rinominarlo in weather.ttf.
L'unica autorizzazione di cui ha bisogno l'app è android.permission.INTERNET
.
Per mantenere questo tutorial semplice, stiamo solo andando a sostenere ritratto modalità. Il attività
il nodo del manifest dovrebbe assomigliare a questo:
Non c'è molto da cambiare activity_weather.xml. Dovrebbe già avere un FrameLayout
. Aggiungi una proprietà extra per cambiare il colore del sfondo
a # FF0099CC
.
modificare fragment_weather.xml aggiungendo cinque TextView
tag per mostrare le seguenti informazioni:
Usare un RelativeLayout
per organizzare le viste del testo. È possibile regolare il dimensione del testo
per adattarsi a vari dispositivi.
Questo file contiene le stringhe utilizzate nella nostra app e i codici dei caratteri Unicode che useremo per rendere le icone del tempo. L'applicazione sarà in grado di visualizzare otto diversi tipi di condizioni meteorologiche. Se vuoi gestire di più, fai riferimento a questo cheat sheet. Aggiungi il seguente a Valori / strings.xml:
Meteo semplice Cambia città 11111 & # Xf00d; & # Xf02e; & # Xf014; & # Xf013; & # Xf019; & # Xf01b; & # Xf01e; & # Xf01c; Siamo spiacenti, nessun dato meteo trovato.
L'utente dovrebbe essere in grado di scegliere la città di cui vogliono vedere il tempo. modificare MENU / weather.xml e aggiungere un elemento per questa opzione.
Ora che tutti i file XML sono pronti per l'uso, passiamo e interrogiamo l'API di OpenWeatherMap per recuperare i dati meteo.
Possiamo ottenere i dettagli meteo attuali di qualsiasi città formattata come JSON utilizzando l'API OpenWeatherMap. Nella stringa di query, passiamo il nome della città e il sistema di misura in cui devono essere inseriti i risultati.
Ad esempio, per ottenere le informazioni meteo attuali per Canberra, utilizzando il sistema metrico, inviamo una richiesta a http://api.openweathermap.org/data/2.5/weather?q=Canberra&units=metric
La risposta che otteniamo dall'API è la seguente:
"base": "cmc stations", "clouds": "all": 90, "cod": 200, "coord": "lat": -35.28, "lon": 149.13, "dt" : 1404390600, "id": 2172517, "main": "umidità": 100, "pressione": 1023, "temp": -1, "temp_max": -1, "temp_min": -1, "nome ":" Canberra "," sys ": " paese ":" AU "," messaggio ": 0.313," alba ": 1404335563," tramonto ": 1404370965," meteo ": [" descrizione ":" nuvoloso clouds "," icon ":" 04n "," id ": 804," main ":" Clouds "]," wind ": " deg ": 305.004," speed ": 1.07
Crea una nuova classe Java e chiamala RemoteFetch.java. Questa classe è responsabile del recupero dei dati meteorologici dall'API OpenWeatherMap.
Noi usiamo il HttpURLConnection
classe per fare la richiesta remota. L'API OpenWeatherMap prevede la chiave API in un'intestazione HTTP denominata x-api-chiave
. Questo è specificato nella nostra richiesta utilizzando il setRequestProperty
metodo.
Noi usiamo a BufferedReader
leggere la risposta dell'API in a StringBuffer
. Quando avremo la risposta completa, la convertiamo in a JSONObject
oggetto.
Come puoi vedere nella risposta sopra, i dati JSON contengono un campo chiamato merluzzo
. Il suo valore è 200
se la richiesta ha avuto successo. Utilizziamo questo valore per verificare se la risposta JSON ha o meno le informazioni meteo correnti.
Il RemoteFetch.java la classe dovrebbe assomigliare a questa:
pacchetto ah.hathi.simpleweather; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import org.json.JSONObject; importare android.content.Context; import android.util.Log; public class RemoteFetch Stringa finale statica privata OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric"; public static JSONObject getJSON (Context context, String city) try URL url = new URL (String.format (OPEN_WEATHER_MAP_API, city)); HttpURLConnection connection = (HttpURLConnection) url.openConnection (); connection.addRequestProperty ("x-api-key", context.getString (R.string.open_weather_maps_app_id)); Lettore BufferedReader = new BufferedReader (new InputStreamReader (connection.getInputStream ())); StringBuffer json = new StringBuffer (1024); Stringa; while ((tmp = reader.readLine ())! = null) json.append (tmp) .append ("\ n"); reader.close (); JSONObject data = new JSONObject (json.toString ()); // Questo valore sarà 404 se la richiesta non è // corretta se (data.getInt ("cod")! = 200) return null; dati di ritorno; catch (Exception e) return null;
L'utente non deve specificare il nome della città ogni volta che desidera utilizzare l'app. L'app dovrebbe ricordare l'ultima città a cui l'utente era interessato. Facciamo questo facendo uso di SharedPreferences
. Tuttavia, invece di accedere direttamente a queste preferenze dal nostro Attività
classe, è meglio creare una classe separata per questo scopo.
Crea una nuova classe Java e chiamala CityPreference.java. Per memorizzare e recuperare il nome della città, creare due metodi setCity
e getCity
. Il SharedPreferences
l'oggetto è inizializzato nel costruttore. Il CityPreference.java la classe dovrebbe assomigliare a questa:
pacchetto ah.hathi.simpleweather; importare android.app.Activity; importare android.content.SharedPreferences; public class CityPreference prefs di SharedPreferences; public CityPreference (Attività dell'attività) prefs = activity.getPreferences (Activity.MODE_PRIVATE); // Se l'utente non ha ancora scelto una città, restituisce // Sydney come città predefinita String getCity () return prefs.getString ("city", "Sydney, AU"); void setCity (String city) prefs.edit (). putString ("city", city) .commit ();
Crea una nuova classe Java e chiamala WeatherFragment.java. Questo frammento utilizza fragment_weather.xml come il suo layout. Dichiara il cinque TextView
oggetti e inizializzarli nel onCreateView
metodo. Dichiara un nuovo carattere tipografico
oggetto chiamato weatherFont
. Il TypeFace
oggetto punterà al carattere web scaricato e memorizzato nel attività / font cartella.
Faremo uso di un separato Filo
per prelevare in modo asincrono i dati dall'API OpenWeatherMap. Non possiamo aggiornare l'interfaccia utente da tale thread in background. Abbiamo quindi bisogno di un handler
oggetto, che inizializziamo nel costruttore del WeatherFragment
classe.
la classe pubblica WeatherFragment estende Fragment Typeface weatherFont; TextView cityField; TextView updatedField; TextView detailsField; TextView currentTemperatureField; TextView weatherIcon; Gestore dell'handler; public WeatherFragment () handler = new Handler (); @Override public Visualizza onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) Visualizza 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); return rootView;
Inizializza il weatherFont
oggetto chiamando createFromAsset
sul carattere tipografico
classe. Invochiamo anche il updateWeatherData
metodo in onCreate
.
@Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); weatherFont = Typeface.createFromAsset (getActivity (). getAssets (), "fonts / weather.ttf"); updateWeatherData (new CityPreference (getActivity ()). getCity ());
Nel updateWeatherData
, iniziamo una nuova discussione e chiamiamo getJSON
sul RemoteFetch
classe. Se il valore restituito da getJSON
è nullo
, mostriamo un messaggio di errore all'utente. Se non lo è, invochiamo il renderWeather
metodo.
Solo il principale Filo
è autorizzato ad aggiornare l'interfaccia utente di un'app Android. chiamata Crostini
o renderWeather
direttamente dal thread in background causerebbe un errore di runtime. Questo è il motivo per cui chiamiamo questi metodi usando il gestore
'S inviare
metodo.
private void updateWeatherData (final String city) new Thread () public void run () final JSONObject json = RemoteFetch.getJSON (getActivity (), city); if (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);); .inizio();
Il renderWeather
metodo utilizza i dati JSON per aggiornare il TextView
oggetti. Il tempo metereologico
il nodo della risposta JSON è una matrice di dati. In questo tutorial, utilizzeremo solo il primo elemento della serie di dati meteo.
private void renderWeather (JSONObject json) try cityField.setText (json.getString ("name"). toUpperCase (Locale.US) + "," + json.getJSONObject ("sys"). getString ("paese")) ; Dettagli JSONObject = json.getJSONArray ("weather"). GetJSONObject (0); JSONObject main = json.getJSONObject ("main"); detailsField.setText (details.getString ("description"). toUpperCase (Locale.US) + "\ n" + "Umidità:" + main.getString ("umidità") + "%" + "\ n" + "Pressione : "+ main.getString (" pressure ") +" hPa "); currentTemperatureField.setText (String.format ("%. 2f", main.getDouble ("temp")) + "℃"); DateFormat df = DateFormat.getDateTimeInstance (); String updatedOn = df.format (new Date (json.getLong ("dt") * 1000)); updatedField.setText ("Ultimo aggiornamento:" + updatedOn); setWeatherIcon (details.getInt ("id"), json.getJSONObject ("sys"). getLong ("sunrise") * 1000, json.getJSONObject ("sys"). getLong ("sunset") * 1000); catch (Exception e) Log.e ("SimpleWeather", "Uno o più campi non trovati nei dati JSON");
Alla fine di renderWeather
metodo, invochiamo setWeatherIcon
con il id
del tempo attuale e delle ore dell'alba e del tramonto. L'impostazione dell'icona del meteo è un po 'complicata, perché l'API di OpenWeatherMap supporta più condizioni meteorologiche di quelle che possiamo supportare con il font web che stiamo usando. Fortunatamente, gli ID del tempo seguono uno schema, che puoi leggere di più sul sito web di OpenWeatherMap.
Questo è il modo in cui mappiamo un ID meteo a un'icona:
R.string.weather_thunder
per questiR.string.weather_drizzle
per questiR.string.weather_rain
per loroUsiamo gli orari di alba e tramonto per visualizzare il sole o la luna, a seconda dell'ora corrente del giorno e solo se il tempo è chiaro.
private void setWeatherIcon (int actualId, long sunrise, long sunset) int id = actualId / 100; String icon = ""; if (actualId == 800) long currentTime = new Date (). getTime (); if (currentTime> = sunrise && currentTimeCerto, puoi gestire più condizioni meteorologiche aggiungendo altro
Astuccio
dichiarazioni alinterruttore
dichiarazione delsetWeatherIcon
metodo.Infine, aggiungi un
changeCity
metodo al frammento per consentire all'utente di aggiornare la città corrente. IlchangeCity
il metodo verrà chiamato solo dal principaleAttività
classe.public void changeCity (String city) updateWeatherData (city);12. Modifica l'attività
Durante la configurazione del progetto, Eclipse è popolato WeatherActivity.java con un po 'di codice boilerplate. Sostituire l'implementazione predefinita di
onCreate
metodo con quello in basso in cui usiamo ilWeatherFragment
. IlonCreate
il metodo dovrebbe assomigliare a questo:@Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_weather); if (savedInstanceState == null) getSupportFragmentManager (). beginTransaction () .add (R.id.container, new WeatherFragment ()) .commit ();Quindi, modifica il
onOptionsItemSelected
metodo e gestire l'unica opzione di menu che abbiamo. Tutto quello che devi fare qui è invocare ilshowInputDialog
metodo.Nel
showInputDialog
metodo, noi usiamoAlertDialog.Builder
creare unDialogo
oggetto che richiede all'utente di inserire il nome di una città. Questa informazione è passata alchangeCity
metodo, che memorizza il nome della città usando ilCityPreference
classe e chiama ilFrammento
'SchangeCity
metodo.@Override public boolean onOptionsItemSelected (MenuItem item) if (item.getItemId () == R.id.change_city) showInputDialog (); return false; private void showInputDialog () AlertDialog.Builder builder = new AlertDialog.Builder (this); builder.setTitle ("Cambia città"); input EditText finale = nuovo EditText (questo); input.setInputType (InputType.TYPE_CLASS_TEXT); builder.setView (ingresso); builder.setPositiveButton ("Go", new DialogInterface.OnClickListener () @Override public void onClick (DialogInterface dialog, int which) changeCity (input.getText (). toString ());); builder.show (); public void changeCity (String city) WeatherFragment wf = (WeatherFragment) getSupportFragmentManager () .findFragmentById (R.id.container); wf.changeCity (città); nuovo CityPreference (this) .setCity (città);La tua app meteo è ora pronta. Costruisci il progetto e distribuiscilo su un dispositivo Android per il test.
Conclusione
Ora hai un'applicazione meteorologica perfettamente funzionante. Sentiti libero di esplorare l'API di OpenWeatherMap per migliorare ulteriormente la tua applicazione. Potresti anche voler utilizzare più icone meteo, perché al momento ne utilizziamo solo un piccolo sottoinsieme.