Buenos días, en esta entrada veremos como podemos bajar una imagen para mostrarla en nuestro Android, mediante una simple función.
Cuando creamos aplicaciones, podemos encontrarnos en la necesidad de tener que bajar imágenes y tener que mostrarlas luego en un ImageView, y a partir de la versión 3.X de Android, llamada Honeycomb, cualquier operación que requiera el uso de Internet debe ir en otro hilo aparte, no puede ir en el hilo principal de la aplicación, es por eso por lo que tendremos que usar un AsyncTask para usar la red de nuestro dispositivo.
-
GUI
Una vez creado nuestro proyecto en Android, vamos a modificar el xml de la actividad, con lo que nos quedará algo así:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ImageView android:id="@+id/imagen" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>
Con este xml tendremos un elemento ImageView que estará posicionado en el centro de nuestra pantalla.
-
Activity
Aquí viene la parte importante de nuestro ejemplo, ya que toda la funcionalidad principal se desarrolla aquí.
Vamos a empezar declarando 1 constante, la cual contendrá la url de una imagen, yo he cogido una del buscador de Google, podeis usar cualquiera que esté alojada en la red. A continuación, tenemos la variable de instancia del ImageView, en el cual pondremos la imagen descargada.
public class MainActivity extends Activity { public static final String URL = "http://www.thebiblescholar.com/android_awesome.jpg"; private ImageView imgImagen; }
Método onCreate()
En este método inicializaremos el ImageView, y llamaremos a la AsyncTask, la cual descargará la imagen y la establecerá en el ImageView.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgImagen = (ImageView)findViewById(R.id.imagen); CargaImagenes nuevaTarea = new CargaImagenes(); nuevaTarea.execute(URL); }
En este punto nuestra aplicación aún no será funcional, ya que no tenemos creada la AsyncTask, la cual yo he llamado CargarImagenes, pero cualquier otro nombre valdría.
AsyncTask CargaImagenes
Aquí viene una de las partes principales de nuestra aplicación, será la tarea que se encargue de bajar la imagen y establecerla en el ImageView, y todo esto se realiza en segundo plano mientras muestra un ProgressDialog, para que el usuario sepa que nuestra aplicación no ha explotado.
private class CargaImagenes extends AsyncTask<String, Void, Bitmap>{ ProgressDialog pDialog; @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); pDialog = new ProgressDialog(MainActivity.this); pDialog.setMessage("Cargando Imagen"); pDialog.setCancelable(true); pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); pDialog.show(); } @Override protected Bitmap doInBackground(String... params) { // TODO Auto-generated method stub Log.i("doInBackground" , "Entra en doInBackground"); String url = params[0]; Bitmap imagen = descargarImagen(url); return imagen; } @Override protected void onPostExecute(Bitmap result) { // TODO Auto-generated method stub super.onPostExecute(result); imgImagen.setImageBitmap(result); pDialog.dismiss(); } }
Como vemos, la AsyncTask tiene un ProgressDialog, el cual es inicializado y lanzado en el método onPreExecute(), el cual es llamado automáticamente antes de empezar el método doInBackground().
En el método doInBackground() se realiza la funcionalidad principal de la aplicación. Primero cogemos el parámetro de la lista de parámetros, en este caso es param[0], porque solo hemos pasado uno, y este se encuentra en la posición 0, como si de un Array se tratase.
Luego definimos un objeto de la clase Bitmap, que será el encargado de guardar la imagen.
-
Método descargarImagen()
Este método es simple, es el siguiente:
private Bitmap descargarImagen (String imageHttpAddress){ URL imageUrl = null; Bitmap imagen = null; try{ imageUrl = new URL(imageHttpAddress); HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection(); conn.connect(); imagen = BitmapFactory.decodeStream(conn.getInputStream()); }catch(IOException ex){ ex.printStackTrace(); } return imagen; }
En este método recibimos la url de la imagen a descargar, el cual pasaremos mas tarde como argumento para crear una nueva instancia de la clase URL.
Por último, en el método onPostExecute(), el cual se inicia al terminar el método doInBackground(), y en este es donde podremos interactuar con el hilo principal de la aplicación, por tanto quitaremos el ProgressDialog, con lo cual el usuario verá que la tarea habrá terminado, y a continuación con el método setImageBitmap(), establecemos la imagen en el ImageView.
-
-
AndroidManifest.xml
Nada funcionará en nuestra aplicación si no añadimos una linea en nuestro AndroidManifest.xml. Es simple, en nuestra aplicación estamos usando Internet para descargar una imagen, y es un permiso que tenemos que declarar. Para ello, nos iremos al directorio raiz de nuestro proyecto y abriremos el archivo AndroidManifest.xml.
Pinchamos en la última pestaña que vemos en la parte inferior de la ventana, la cual se llama AndroidManifest.xml, y añadimos la linea correspondiente, con lo cual quedará así:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sekth.droid.bajarimagen" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="sekth.droid.bajarimagen.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
La línea que hemos agregado es la siguiente:
<uses-permission android:name="android.permission.INTERNET"/>
Con esta línea nuestra aplicación podrá usar internet para realizar acciones que tengan que ver con ello.
Con esto nuestra aplicación es finalmente funcional, y podemos ver que al abrirla se nos carga la imagen. A continuación dejo una foto y un video de como es en funcionamiento.
Aquí la foto
Aquí un video demostrativo
Sin más esto es todo, cualquier aporte o corrección es bienvenido, espero que os sirva.
Saludos!!
Pingback: Guardar Imagen en Memoria Interna Android « SekthDroid
Muy buen tutorial, solo me gustaria consultar, como hago que esto funcione con un boton?
Saludos desde El Salvador
Buenas Gerson, como ves en el tutorial todo se realiza en el método onCreate, es decir cuando se está generando la Activity. Si quieres que se ejecute con un botón, bastaría con agregarlo en la UI, y añadirle un onClickListener, o bien mediante el atributo onClick del xml, y dentro de el instanciar la AsynkTask y ejecutarla. Debido a que no estoy en mi casa y no tengo internet no puedo ponerte un ejemplo ahora mismo, ya que estoy en el ejemplo, en cuanto vuelva te pongo el código de ejemplo con un botón por si sirve de ayuda. Saludos y siento ahora mismo no poder ponerte el ejemplo, pero desde el movil es complicado 🙂
Hola, gran tuto… una pregunta.. adonde guarda la imagen que se descargo, en cache.. en la memoria interna o externa ? es q necesito crear llamar una serie de imagenes dinamicamente desde internet y son grandes para un movil, no se siguardarlas en cache o descargarlas primero en la sd y luego llamarlas en tiempo de ejecucion, y de ser asi como se hace esto??
Buenas Johann,
En esta entrada lo único que se hace es descargar una imagen y colocarla en un ImageView, pero no la guarda ni en la memoria interna ni externa.
Para guardarlo en la memoria externa, debes usar algo parecido a lo que aparece en Android Developer. Lo primero comprobar si está disponible y se puede escribir en ella:
Una vez tengas los datos necesarios, puedes hacer uso de estos métodos:
Descargar Imagen
Guardar Imagen en SD
Estos métodos son los que he usado varias veces, pero al fin y al cabo el tema de bajar imágenes va en función de tu proyecto, de lo que quieras hacer, del comportamiento y el enfoque que le des, ya que si son tamaños de imágenes grandes puede que te convenga descargarlos si la conexión que existe es WiFi únicamente, para no consumir demasiados datos en caso contrario.
Igualmente en el blog de Android que te he puesto arriba aparece algo de hacer Caché con imágenes.
Espero que te sirva de ayuda!
Saludos!!
Hey amigo por favor he visto tutoriales en toda la web y el procedimiento es el mismo pero no me corre la aplicación me sale que la aplicacion ha sido detenida
Buenas Milton,
Has consultado el Log para ver que tipo de excepción te lanza?
Quizás se te pueda haber olvidado darle permisos para usar internet a la aplicación mediante el AndroidManifest.xml
Saludos, y cualquier cosa no dudes en preguntar.
SI ESTA PUESTO EL PERMISO EN EL MANIFIESTO
Muchas gracias por la respuesta espero me lo puedas facilitar
me podrias pasar tu programa a mi correo por favor seria de gran ayuda
Excelente tutorial, te agradezco un montón, por otra parte si quisiera que esta imagen se almacene en un directorio especifico y que la app lo tome desde ahí después, como harías?
Buenas Kivpson,
Si quisieras guardar una imagen en algún directorio especial, puedes crear un directorio en la memoria interna usando la clase ContextWrapper, de la siguiente manera:
De esta manera, puedes obtener el directorio y trabajar con el como quieras.
Por otro lado, si lo que quieres es guardar la ruta para acceder a ella directamente, deberías guardar la ruta de los archivos bien en las preferencias o mediante una base de datos.
Espero que te sea de ayuda!
Saludos!!
Vacan excelente tu tutorial, soy muy novato en esto pero me gustaria saber como cargar varias imagenes creando asi varios imagesviews?
gracias
Buenas Freddy
Lo primero de todo me alegro de que te haya sido de utilidad y gracias por comentar.
Por otro lado, si lo que quieres es mostrar varios «Imageviews» como si fuera una parrilla de imágenes, la mejor implementación seria usar un «GridView», los cuales se pueden llenar con una clase que herede de «BaseAdapter» para cargar cada elemento con una imagen.
Tenia pensado hace tiempo sacar una entrada enseñando esto mismo, pero por unas cosas u otras no he podido. Intentare hacer uno este fin de semana sobre este tipo de implementación y si aun sigues con la duda te puede ayudar.
De igual modo, busca mas información sobre esto que te comento porque creo que es lo que estas buscando.
Espero que te sea de ayuda.
Saludos!!
Yo solo quiero consultar porque si descarga los imagenes como son varias tiende a desordenarse las imganes. pero la informacion sigue igual es por los hilos.
Buenas Ronald,
¿Cual es realmente tu problema?
Saludos!
Ya lo solucione es un problema de Hilos y un efecto de ListView.
Disculpa ya has usado websockets desde android tienes alguna libreria. Estoy intentando conectarme con esta libreria Java-WebSocket a mi servidor el archivo es .ashx con javascript me conecto correctamente. desde android se cierra lo conexion inmediatamente se crea el objeto. Gracias.
Buenas Ronald
Personalmente no he tenido oportunidad de usar sockets entre Android y un servidor, por lo que me temo que no puedo ayudarte con este tema, lo siento.
Saludos, y espero que lo soluciones!
Hola mira yo he descargado una imagen, desde un web services el tema es que cuando lo descargo y lo coloco en el Imageview y el usuario me gira la pantalla vuelve a llamar a la tarea asíncrona, estuve leyendo y la verdad utilizan este texto agregándolo al manifest «android:configChanges=”keyboardHidden|orientation” pero no es lo más óptimo, sabes como descargar la imagen, y que al girar la pantalla el activity no pase su ciclo de nuevo y vuelva a llamar la tarea asíncrona.
Cualquier ayuda se agradece, saludos
Buenas Felipe,
Podrías incluir algún tipo de sistema de cache para ello, algo como comprobar si existe ya una imagen guardada en el dispositivo (alguna carpeta o algo) basándote en la url de la imágen por ejemplo, de manera que en la tarea asíncrona compruebes si existe en caché, de esta manera la tarea asíncrona se ejecutará, pero en vez de descargarla, la cogerá de la caché. En el caso contrario, de que la imagen no hubiera sido bajada previamente, pues se ejecutaría la descarga.
Hay maneras mejores, pero esto puede guiarte un poco.
Saludos y espero que te sea de ayuda.
Muy agradecido por el aporte, fue de gran utilidad. Gracias por tomarte el tiempo de compartir.
Excelente ejemplo,funciono completamente en mi aplicacion. Gracias 🙂