Muchas de las aplicaciones meteorológicas populares en Google Play están llenas de anuncios, requieren demasiados permisos o incluyen características que la mayoría de nosotros nunca usamos. ¿No sería genial si pudieras construir tu propia aplicación meteorológica desde cero??
En este tutorial, te voy a mostrar cómo. Nuestra aplicación tendrá una interfaz de usuario simple y minimalista, que muestra al usuario exactamente lo que necesita saber sobre las condiciones climáticas actuales. Empecemos.
Este tutorial te enseñará a crear una aplicación meteorológica desde cero, pero una alternativa es utilizar una de las plantillas de aplicaciones meteorológicas de Android en Envato Market..
Por ejemplo, Weminder proporciona una interfaz de usuario sencilla y limpia y todas las características esenciales de una aplicación meteorológica, para que luego pueda personalizarla para sus propios fines..
Plantilla de aplicación del tiempo Weminder en Envato MarketO, si desea algo único y personalizado, diríjase a Envato Studio para ver la selección de servicios móviles y de desarrollo de aplicaciones que se ofrecen allí..
Antes de continuar, compruebe que tiene la siguiente configuración:
Voy a llamar a esta aplicación SimpleWeather, Pero siéntete libre de darle el nombre que quieras. Ingrese un nombre de paquete único, establezca el SDK mínimo requerido en Android 2.2, y establece el SDK de destino en Android 4.4. Puedes dejar el tema en Holo Dark.
Esta aplicación solo tendrá una Actividad
y se basará en el Actividad en blanco plantilla como se muestra a continuación.
Nombra el Actividad
TiempoActividad. Estaremos usando un Fragmento
dentro de este Actividad
. El diseño asociado a la Actividad
es activity_weather.xml. El diseño asociado a la Fragmento
es fragment_weather.xml.
Dupdo weathericons-regular-webfont.ttf a tu proyecto activos / fuentes directorio y renombrarlo a weather.ttf.
El único permiso que necesita esta aplicación es android.permission.INTERNET
.
Para mantener este tutorial simple, solo vamos a apoyar retrato modo. los actividad
El nodo del manifiesto debe verse así:
No hay mucho que cambiar en activity_weather.xml. Ya debería tener un FrameLayout
. Agrega una propiedad extra para cambiar el color de la fondo
a # FF0099CC
.
Editar fragment_weather.xml añadiendo cinco Vista de texto
Etiquetas para mostrar la siguiente información:
Utilizar una Disposición relativa
para organizar las vistas de texto. Puedes ajustar el tamano del texto
para adaptarse a varios dispositivos.
Este archivo contiene las cadenas utilizadas en nuestra aplicación, así como los códigos de caracteres de Unicode que usaremos para representar los iconos del tiempo. La aplicación podrá mostrar ocho tipos diferentes de condiciones climáticas. Si desea manejar más, consulte esta hoja de trucos. Agregue lo siguiente a valores / cadenas.xml:
Clima simple Cambiar ciudad 11111 & # xf00d; & # xf02e; & # xf014; & # xf013; & # xf019; & # xf01b; & # xf01e; & # xf01c; Lo sentimos, no se han encontrado datos meteorológicos.
El usuario debe poder elegir la ciudad cuyo clima desea ver. Editar menu / weather.xml y agregar un elemento para esta opción.
Ahora que todos los archivos XML están listos para usar, avancemos y consultemos la API de OpenWeatherMap para obtener datos meteorológicos.
Podemos obtener los detalles meteorológicos actuales de cualquier ciudad formateada como JSON utilizando la API OpenWeatherMap. En la cadena de consulta, pasamos el nombre de la ciudad y el sistema métrico en el que deben aparecer los resultados..
Por ejemplo, para obtener la información meteorológica actual de Canberra, mediante el sistema métrico, enviamos una solicitud a http://api.openweathermap.org/data/2.5/weather?q=Canberra&units=metric
La respuesta que recibimos de la API se ve así:
"base": "estaciones de cmc", "nubes": "todas": 90, "cod": 200, "coord": "lat": -35.28, "lon": 149.13, "dt" : 1404390600, "id": 2172517, "main": "humedad": 100, "pressure": 1023, "temp": -1, "temp_max": -1, "temp_min": -1, "name ":" Canberra "," sys ": " country ":" AU "," message ": 0.313," sunrise ": 1404335563," sunset ": 1404370965," weather ": [" description ":" overcast nubes "," icono ":" 04n "," id ": 804," main ":" Clouds "]," wind ": " deg ": 305.004," speed ": 1.07
Crear una nueva clase de Java y nombrarla RemoteFetch.java. Esta clase es responsable de obtener los datos del clima de la API de OpenWeatherMap.
Usamos el HttpURLConnection
Clase para realizar la solicitud remota. La API de OpenWeatherMap espera la clave de la API en un encabezado HTTP llamado x-api-key
. Esto se especifica en nuestra solicitud utilizando el setRequestProperty
método.
Usamos un BufferedReader
para leer la respuesta de la API en una StringBuffer
. Cuando tenemos la respuesta completa, la convertimos a un JSONObject
objeto.
Como puede ver en la respuesta anterior, los datos JSON contienen un campo llamado bacalao
. Su valor es 200
si la solicitud fue exitosa Usamos este valor para verificar si la respuesta JSON tiene la información del clima actual o no.
los RemoteFetch.java La clase debería verse así:
paquete ah.hathi.simpleweather; importar java.io.BufferedReader; importar java.io.InputStreamReader; importar java.net.HttpURLConnection; import java.net.URL; importar org.json.JSONObject; importar android.content.Context; import android.util.Log; clase pública RemoteFetch String final privada estática OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric"; público JSONObject estático getJSON (contexto de contexto, ciudad de cadena) try URL url = new URL (String.format (OPEN_WEATHER_MAP_API, ciudad)); Conexión HttpURLConnection = (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); Cuerda; while ((tmp = reader.readLine ())! = null) json.append (tmp) .append ("\ n"); reader.close (); Datos JSONObject = nuevo JSONObject (json.toString ()); // Este valor será 404 si la solicitud no fue satisfactoria // si (data.getInt ("cod")! = 200) return null; datos de retorno; catch (Exception e) return null;
El usuario no debería tener que especificar el nombre de la ciudad cada vez que quiera usar la aplicación. La aplicación debe recordar la última ciudad en la que estaba interesado el usuario. Hacemos esto haciendo uso de Preferencias compartidas
. Sin embargo, en lugar de acceder directamente a estas preferencias desde nuestro Actividad
clase, es mejor crear una clase separada para este propósito.
Crear una nueva clase de Java y nombrarla CityPreference.java. Para almacenar y recuperar el nombre de la ciudad, cree dos métodos setCity
y getCity
. los Preferencias compartidas
El objeto se inicializa en el constructor. los CityPreference.java La clase debería verse así:
paquete ah.hathi.simpleweather; importar android.app.Activity; importar android.content.SharedPreferences; clase pública CityPreference SharedPreferences prefs; public CityPreference (Activity activity) prefs = activity.getPreferences (Activity.MODE_PRIVATE); // Si el usuario aún no ha elegido una ciudad, devuelve // Sydney como la ciudad predeterminada Cadena getCity () return prefs.getString ("city", "Sydney, AU"); void setCity (String city) prefs.edit (). putString ("city", city) .commit ();
Crear una nueva clase de Java y nombrarla WeatherFragment.java. Este fragmento utiliza fragment_weather.xml como su diseño. Declarar los cinco Vista de texto
objetos e inicializarlos en el onCreateView
método. Declarar un nuevo Tipo de letra
objeto llamado climaFont
. los TypeFace
objeto apuntará a la fuente web que descargó y almacenó en el activos / fuentes carpeta.
Estaremos haciendo uso de un separado Hilo
para obtener datos de forma asíncrona de la API de OpenWeatherMap. No podemos actualizar la interfaz de usuario desde tal subproceso en segundo plano. Por lo tanto necesitamos un Entrenador de animales
Objeto, que inicializamos en el constructor del Tiempofragmento
clase.
la clase pública WeatherFragment extiende Fragment Typeface weatherFont; TextView cityField; TextView updatedField; TextView detailsField; TextView currentTemperatureField; TextView weatherIcon; Manejador de manejador; Public WeatherFragment () handler = new Handler (); @Override public View onCreateView (inflador de LayoutInflater, ViewGroup, Bundle savedInstanceState) View 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); devuelve rootView;
Inicializar el climaFont
objetar llamando crearFromAsset
sobre el Tipo de letra
clase. También invocamos el updateWeatherData
método en onCreate
.
@Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); weatherFont = Typeface.createFromAsset (getActivity (). getAssets (), "fonts / weather.ttf"); updateWeatherData (new CityPreference (getActivity ()). getCity ());
En updateWeatherData
, Empezamos un nuevo hilo y llamamos. getJSON
sobre el RemoteFetch
clase. Si el valor devuelto por getJSON
es nulo
, mostramos un mensaje de error al usuario. Si no es así, invocamos el renderWeather
método.
Solo el principal Hilo
Se le permite actualizar la interfaz de usuario de una aplicación de Android. Vocación tostada
o renderWeather
directamente desde el subproceso en segundo plano llevaría a un error de tiempo de ejecución. Es por eso que llamamos a estos métodos usando el entrenador de animales
es enviar
método.
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);); .comienzo();
los renderWeather
método utiliza los datos JSON para actualizar el Vista de texto
objetos. los clima
El nodo de la respuesta JSON es una matriz de datos. En este tutorial, solo usaremos el primer elemento de la matriz de datos meteorológicos.
private void renderWeather (JSONObject json) try cityField.setText (json.getString ("name"). toUpperCase (Locale.US) + "," + json.getJSONObject ("sys"). getString ("country")) ; Detalles de JSONObject = json.getJSONArray ("weather"). GetJSONObject (0); JSONObject main = json.getJSONObject ("main"); detailsField.setText (details.getString ("description"). toUpperCase (Locale.US) + "\ n" + "Humedad:" + main.getString ("temperature") + "%" + "\ n" + "Presión : "+ 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 ("Última actualización:" + 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 más campos que no se encuentran en los datos JSON");
Al final de renderWeather
método, invocamos setWeatherIcon
con el carné de identidad
del clima actual, así como las horas de salida y puesta del sol. Configurar el ícono del clima es un poco complicado, porque la API de OpenWeatherMap admite más condiciones meteorológicas de las que podemos admitir con la fuente web que estamos usando. Afortunadamente, las identificaciones climáticas siguen un patrón, sobre el que puede leer más en el sitio web OpenWeatherMap.
Así es como asignamos una identificación del tiempo a un icono:
R.string.weather_thunder
para éstosR.string.weather_drizzle
para éstosR.string.weather_rain
para ellosUsamos las horas de salida y puesta del sol para mostrar el sol o la luna, dependiendo de la hora actual del día y solo si el clima es despejado.
privado void setWeatherIcon (int actualId, long sunrise, long sunset) int id = actualId / 100; Icono de cadena = ""; if (actualId == 800) long currentTime = new Date (). getTime (); if (currentTime> = sunrise && currentTimePor supuesto, puedes manejar más condiciones climáticas agregando más
caso
declaraciones a lacambiar
declaración de lasetWeatherIcon
método.Finalmente, agregue un
cambioCiudad
Método al fragmento para permitir que el usuario actualice la ciudad actual. loscambioCiudad
Método solo será llamado desde el principalActividad
clase.public void changeCity (String city) updateWeatherData (city);12. Edita la actividad
Durante la configuración del proyecto, se completó Eclipse. WeatherActivity.java Con algún código repetitivo. Reemplace la implementación por defecto del
onCreate
Método con el de abajo en el que usamos elTiempofragmento
. losonCreate
El método debería verse así:@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 ();A continuación, edite el
onOptionsItemSelected
Método y manejar la única opción de menú que tenemos. Todo lo que tienes que hacer aquí es invocar elshowInputDialog
método.En el
showInputDialog
método, usamosAlertDialog.Builder
para crear unDiálogo
objeto que solicita al usuario que ingrese el nombre de una ciudad. Esta información se transmite a lacambioCiudad
Método, que almacena el nombre de la ciudad utilizando elCityPreference
clase y llama alFragmento
escambioCiudad
método.@Override public boolean onOptionsItemSelected (elemento MenuItem) if (item.getItemId () == R.id.change_city) showInputDialog (); falso retorno; privado void showInputDialog () AlertDialog.Builder builder = new AlertDialog.Builder (esto); builder.setTitle ("Cambiar ciudad"); entrada final de EditText = nuevo EditText (este); input.setInputType (InputType.TYPE_CLASS_TEXT); builder.setView (entrada); builder.setPositiveButton ("Go", nuevo DialogInterface.OnClickListener () @Override public void onClick (diálogo DialogInterface, int which) changeCity (input.getText (). toString ());)); constructor.show (); public void changeCity (String city) WeatherFragment wf = (WeatherFragment) getSupportFragmentManager () .findFragmentById (R.id.container); wf.changeCity (ciudad); nueva CityPreference (this) .setCity (city);Tu aplicación del tiempo ya está lista. Cree el proyecto y despliéguelo en un dispositivo Android para realizar pruebas..
Conclusión
Ahora tienes una aplicación de clima completamente funcional. Siéntase libre de explorar la API de OpenWeatherMap para mejorar aún más su aplicación. También es posible que desee utilizar más iconos del clima, ya que actualmente estamos usando solo un pequeño subconjunto de ellos.