Créer une application météo sur Android

Ce que vous allez créer

La plupart des applications météo populaires sur Google Play sont remplies d'annonces, nécessitent trop d'autorisations ou incluent des fonctionnalités que la plupart d'entre nous n'utilisons jamais. Ce ne serait pas génial si vous pouviez créer votre propre application météo à partir de zéro?

Dans ce tutoriel, je vais vous montrer comment. Notre application aura une interface utilisateur simple et minimaliste, montrant à l'utilisateur exactement ce dont ils ont besoin de savoir sur les conditions météorologiques actuelles. Commençons.

À la recherche d'un raccourci?

Ce tutoriel vous apprendra à créer une application météo à partir de rien, mais vous pouvez également utiliser l'un des modèles d'application météo Android sur Envato Market..

Par exemple, Weminder fournit une interface utilisateur simple et claire et toutes les fonctionnalités essentielles d'une application météo, de sorte que vous puissiez ensuite la personnaliser pour vos propres besoins..

Modèle d'application météo Weminder sur le marché Envato

Ou, si vous voulez quelque chose d'unique et de personnalisé, rendez-vous dans Envato Studio pour consulter la sélection de services de développement d'applications mobiles et d'applications qui y sont proposés.

1. Prérequis

Avant de continuer, vérifiez que vous avez configuré les éléments suivants:

  • Eclipse ADT Bundle: Vous pouvez le télécharger sur le site Web des développeurs Android.
  • OpenWeatherMap clé API : Ce n'est pas nécessaire pour compléter le tutoriel, mais c'est gratuit. Vous pouvez en obtenir un en vous inscrivant sur le site Web OpenWeatherMap..
  • Les icônes: Je vous recommande de télécharger la police de météo créée par Erik Flowers. Vous devez télécharger le fichier TTF, car nous allons l'utiliser dans une application native. Nous allons utiliser la police pour rendre différentes icônes en fonction des conditions météorologiques.

2. Créer un nouveau projet

Je vais appeler cette application SimpleWeather, mais n'hésitez pas à lui donner le nom de votre choix. Entrez un nom de package unique, définissez le SDK minimum requis sur Android 2.2, et définissez le SDK cible sur Android 4.4. Vous pouvez laisser le thème à Holo Dark.

Cette application aura seulement un Activité et il sera basé sur la Activité vide modèle comme indiqué ci-dessous.

Nomme le Activité MétéoActivité. Nous allons utiliser un Fragment à l'intérieur de cette Activité. La mise en page associée à la Activité est activity_weather.xml. La mise en page associée à la Fragment est fragment_weather.xml.

3. Ajouter la police personnalisée

Copie weathericons-regular-webfont.ttf à votre projet actifs / polices répertoire et le renommer en weather.ttf.

4. Modifier le manifeste

La seule autorisation nécessaire à cette application est android.permission.INTERNET.


Pour que ce tutoriel reste simple, nous allons seulement supporter portrait mode. le activité Le noeud du manifeste devrait ressembler à ceci:

     

5. Modifier la présentation de l'activité

Il n'y a pas grand chose à changer dans activity_weather.xml. Il devrait déjà avoir un FrameLayout. Ajouter une propriété supplémentaire pour changer la couleur du Contexte à # FF0099CC.

 

6. Editer la mise en page du fragment

modifier fragment_weather.xml en ajoutant cinq Affichage balises pour afficher les informations suivantes:

  • ville et pays
  • température actuelle
  • une icône indiquant les conditions météorologiques actuelles
  • un horodatage informant l'utilisateur de la dernière mise à jour des informations météo
  • des informations plus détaillées sur la météo actuelle, telles que la description et l'humidité

Utiliser un Disposition relative organiser les vues de texte. Vous pouvez ajuster le taille du texte pour convenir à divers appareils.

       

7. Editez strings.xml

Ce fichier contient les chaînes utilisées dans notre application ainsi que les codes de caractères Unicode que nous utiliserons pour restituer les icônes météo. L'application pourra afficher huit types de conditions météorologiques différents. Si vous voulez en gérer plus, référez-vous à cette aide-mémoire. Ajouter ce qui suit à values ​​/ strings.xml:

  Météo simple Changer de ville  11111 & # xf00d; & # xf02e; & # xf014; & # xf013; & # xf019; & # xf01b; & # xf01e; & # xf01c; Désolé, aucune donnée météorologique trouvée. 

8. Ajouter un élément de menu

L'utilisateur doit pouvoir choisir la ville dont il veut voir le temps. modifier menu / weather.xml et ajouter un article pour cette option.

  

Maintenant que tous les fichiers XML sont prêts à être utilisés, passons à autre chose et interrogons l'API OpenWeatherMap pour récupérer les données météorologiques..

9. Récupérer des données depuis OpenWeatherMap

Nous pouvons obtenir les détails météorologiques actuels de toutes les villes au format JSON à l'aide de l'API OpenWeatherMap. Dans la chaîne de requête, nous passons le nom de la ville et le système métrique dans lequel les résultats doivent être en.

Par exemple, pour obtenir les informations météorologiques actuelles de Canberra, en utilisant le système métrique, nous envoyons une demande à http://api.openweathermap.org/data/2.5/weather?q=Canberra&units=metric.

La réponse que nous recevons de l'API ressemble à ceci:

"base": "stations cmc", "nuages": "tous": 90, "cod": 200, "coord": "lat": -35.28, "lon": 149.13, "dt" : 1404390600, "id": 2172517, "principal": "humidité": 100, "pression": 1023, "temp": -1, "temp_max": -1, "temp_min": -1, "nom ":" Canberra "," sys ": " pays ":" AU "," message ": 0.313," lever du soleil ": 1404335563," coucher du soleil ": 1404370965," météo ": [" description ":" couvert " nuages ​​"," icône ":" 04n "," id ": 804," principal ":" Nuages ​​"]," vent ": " deg ": 305.004," vitesse ": 1.07

Créez une nouvelle classe Java et nommez-la. RemoteFetch.java. Cette classe est chargée d'extraire les données météorologiques de l'API OpenWeatherMap.

Nous utilisons le HttpURLConnection classe pour faire la demande à distance. L’API OpenWeatherMap attend la clé d’API dans un en-tête HTTP nommé x-api-key. Ceci est spécifié dans notre demande en utilisant le setRequestProperty méthode.

Nous utilisons un BufferedReader lire la réponse de l'API dans un StringBuffer. Lorsque nous avons la réponse complète, nous le convertissons en un JSONObject objet.

Comme vous pouvez le constater dans la réponse ci-dessus, les données JSON contiennent un champ nommé la morue. Sa valeur est 200 si la demande a abouti. Nous utilisons cette valeur pour vérifier si la réponse JSON contient ou non les informations météorologiques actuelles..

le RemoteFetch.java la classe devrait ressembler à ceci:

package ah.hathi.simpleweather; importer java.io.BufferedReader; importer java.io.InputStreamReader; importer java.net.HttpURLConnection; importer java.net.URL; import org.json.JSONObject; importer android.content.Context; importer android.util.Log; Classe publique RemoteFetch Chaîne statique privée finale String OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric"; JSONObject statique public getJSON (contexte de contexte, chaîne de ville) try URL url = nouvelle URL (String.format (OPEN_WEATHER_MAP_API, ville)); HttpURLConnection connection = (HttpURLConnection) url.openConnection (); connection.addRequestProperty ("x-api-key", context.getString (R.string.open_weather_maps_app_id)); BufferedReader reader = new BufferedReader (new InputStreamReader (connection.getInputStream ())); StringBuffer json = new StringBuffer (1024); Chaîne; while ((tmp = reader.readLine ())! = null) json.append (tmp) .append ("\ n"); lecteur.close (); JSONObject data = new JSONObject (json.toString ()); // Cette valeur sera 404 si la demande n'a pas été // réussie si (data.getInt ("cod")! = 200) return null;  renvoyer des données;  catch (Exception e) return null; 

10. Stocker la ville comme une préférence

L'utilisateur ne devrait pas avoir à spécifier le nom de la ville chaque fois qu'il souhaite utiliser l'application. L’application doit se rappeler de la dernière ville à laquelle l’utilisateur était intéressé. Nous le faisons en utilisant Préférences partagées. Cependant, au lieu d’accéder directement à ces préférences depuis notre Activité classe, il est préférable de créer une classe séparée à cet effet.

Créez une nouvelle classe Java et nommez-la. CityPreference.java. Pour stocker et récupérer le nom de la ville, créez deux méthodes. setCity et getCity. le Préférences partagées l'objet est initialisé dans le constructeur. le CityPreference.java la classe devrait ressembler à ceci:

package ah.hathi.simpleweather; importer android.app.Activity; importer android.content.SharedPreferences; classe publique CityPreference SharedPreferences prefs; public CityPreference (Activité d'activité) prefs = activity.getPreferences (Activity.MODE_PRIVATE);  // Si l'utilisateur n'a pas encore choisi de ville, retourne // Sydney comme ville par défaut String getCity () return prefs.getString ("city", "Sydney, AU");  void setCity (Ville de chaîne) prefs.edit (). putString ("ville", ville) .commit (); 

11. Créer le fragment

Créez une nouvelle classe Java et nommez-la. MétéoFragment.java. Ce fragment utilise fragment_weather.xml comme sa mise en page. Déclarer les cinq Affichage objets et les initialiser dans le onCreateView méthode. Déclarer un nouveau Police de caractères objet nommé WeatherFont. le TypeFace l'objet pointe sur la police Web que vous avez téléchargée et stockée dans le actifs / polices dossier.

Nous allons utiliser un outil séparé Fil extraire de manière asynchrone des données à partir de l’API OpenWeatherMap. Nous ne pouvons pas mettre à jour l'interface utilisateur à partir d'un tel fil d'arrière-plan. Nous avons donc besoin d'un Gestionnaire objet, que nous initialisons dans le constructeur du MétéoFragment classe.

classe publique WeatherFragment étend Fragment Typeface weatherFont; TextView cityField; TextView updatedField; TextView detailsField; TextView currentTemperatureField; TextView weatherIcon; Gestionnaire de manutention; public WeatherFragment () handler = new Handler ();  @Override public View onCreateView (inflateur LayoutInflater, conteneur ViewGroup, Bundle savedInstanceState) View rootView = inflater.inflate (R.layout.fragment_weather, conteneur, 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); retourne rootView; 

Initialiser le WeatherFont objet en appelant createFromAsset sur le Police de caractères classe. Nous invoquons aussi le updateWeatherData méthode en onCreate.

@Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); weatherFont = Typeface.createFromAsset (getActivity (). getAssets (), "fonts / weather.ttf"); updateWeatherData (nouvelle CityPreference (getActivity ()). getCity ()); 

Dans updateWeatherData, nous commençons un nouveau fil et appelons getJSON sur le RemoteFetch classe. Si la valeur renvoyée par getJSON est nul, nous affichons un message d'erreur à l'utilisateur. Si ce n'est pas le cas, nous invoquons le renderWeather méthode.

Seul le principal Fil est autorisé à mettre à jour l'interface utilisateur d'une application Android. Appel Pain grillé ou renderWeather directement à partir du thread d'arrière-plan conduirait à une erreur d'exécution. C’est pourquoi nous appelons ces méthodes en utilisant le gestionnairede poster méthode.

private void updateWeatherData (ville de chaîne finale) 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 (), .Activity (). getString (R.string.place_not_found), Toast.LENGTH_LONG) .show (););  else handler.post (new Runnable () public void run () renderWeather (json););   .début(); 

le renderWeather méthode utilise les données JSON pour mettre à jour le Affichage objets. le Météo Le noeud de la réponse JSON est un tableau de données. Dans ce tutoriel, nous n'utiliserons que le premier élément du tableau de données météorologiques.

renderWeather (JSONObject json) try cityField.setText (json.getString ("name"). toUpperCase (Locale.US) + "," + json.getJSONObject ("sys"). getString ("pays") ; JSONObject details = json.getJSONArray ("météo"). GetJSONObject (0); JSONObject main = json.getJSONObject ("main"); detailsField.setText (details.getString ("description"). toUpperCase (Locale.US) + "\ n" + "Humidity:" + main.getString ("humidité ") +"% "+" \ n "+" Pression : "+ main.getString (" pression ") +" 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 ("Dernière mise à jour:" + updatedOn); setWeatherIcon (details.getInt ("id"), json.getJSONObject ("sys"). getLong ("sunrise") * 1000, json.getJSONObject ("sys"). getLong ("sunset") * 1000);  catch (Exception e) Log.e ("SimpleWeather", "Un ou plusieurs champs introuvables dans les données JSON"); 

À la fin de renderWeather méthode, nous invoquons setWeatherIcon avec le identifiant de la météo actuelle ainsi que les heures de lever et de coucher du soleil. Définir l’icône météo est un peu délicat, car l’API OpenWeatherMap prend en charge davantage de conditions météorologiques que la police Web que nous utilisons. Heureusement, les identifiants météo suivent un modèle, sur lequel vous pouvez en savoir plus sur le site OpenWeatherMap..

Voici comment associer un identifiant météo à une icône:

  • les codes météo dans la gamme 200 sont liés aux orages, ce qui signifie que nous pouvons utiliser R.string.weather_thunder pour ces
  • les codes météorologiques dans la gamme 300 sont liés aux bruines et nous utilisons R.string.weather_drizzle pour ces
  • les codes météo dans la gamme 500 signifient pluie et nous utilisons R.string.weather_rain pour eux
  • etc…

Nous utilisons les heures de lever et de coucher du soleil pour afficher le soleil ou la lune, en fonction de l'heure du jour et uniquement si le temps est clair..

void privé setWeatherIcon (int actualId, long lever de soleil, long coucher de soleil) int id = actualId / 100; Icône de chaîne = ""; if (actualId == 800) long currentTime = new Date (). getTime (); if (currentTime> = sunrise && currentTime

Bien sûr, vous pouvez gérer plus de conditions météorologiques en ajoutant plus Cas déclarations à la commutateur déclaration du setWeatherIcon méthode.

Enfin, ajoutez un changer la ville méthode au fragment pour permettre à l'utilisateur de mettre à jour la ville actuelle. le changer la ville méthode ne sera appelée à partir de la principale Activité classe.

public void changeCity (String city) updateWeatherData (city); 

12. Modifier l'activité

Au cours de la configuration du projet, Eclipse a rempli MétéoActivité.java avec un code passe-partout. Remplacer l'implémentation par défaut du onCreate méthode avec celle ci-dessous dans laquelle nous utilisons le MétéoFragment. le onCreate méthode devrait ressembler à ceci:

@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 (); 

Ensuite, éditez le onOptionsItemSelected méthode et gérer la seule option de menu que nous avons. Tout ce que vous avez à faire ici est d’invoquer le showInputDialog méthode.

dans le showInputDialog méthode, nous utilisons AlertDialog.Builder créer un Dialogue objet qui invite l'utilisateur à entrer le nom d'une ville. Cette information est transmise au changer la ville méthode, qui stocke le nom de la ville en utilisant le CityPreference classe et appelle le Fragmentde changer la ville méthode.

@Override public boolean onOptionsItemSelected (élément MenuItem) if (item.getItemId () == R.id.change_city) showInputDialog ();  return false;  private void showInputDialog () AlertDialog.Builder builder = new AlertDialog.Builder (this); builder.setTitle ("Changer de ville"); Final EditText input = new EditText (this); input.setInputType (InputType.TYPE_CLASS_TEXT); builder.setView (entrée); builder.setPositiveButton ("Go", nouveau DialogInterface.OnClickListener () @Override public void onClick (dialogue DialogInterface, entier qui) changeCity (input.getText (). toString ());); builder.show ();  public void changeCity (Ville de la chaîne) WeatherFragment wf = (WeatherFragment) getSupportFragmentManager () .findFragmentById (R.id.container); wf.changeCity (ville); nouvelle CityPreference (this) .setCity (ville); 

Votre application météo est maintenant prête. Construisez le projet et déployez-le sur un périphérique Android pour le tester..

Conclusion

Vous avez maintenant une application météo entièrement fonctionnelle. N'hésitez pas à explorer l'API OpenWeatherMap pour améliorer davantage votre application. Vous pouvez également utiliser davantage d'icônes météo, car nous n'en utilisons actuellement qu'un petit sous-ensemble..