Hola amigos, espero hayan pasado excelentes fiestas y empiezen el año 2018 con muchas ganas de salir adelante, a pedido de un usuario concurrente vamos a ver un nuevo tutorial:
Como extraer(descargar) imágenes desde una webservices con base de datos mysql en Android Studio
Contenidos
Estructura:
Clases:
- Conector
- DataParser
- DescargarImagen
- Fruta
- FrutaAdapter
- MainActivity
Layout
- activity_main.xml
- content_main.xml
- lista.xml
Drawable
- fruits.png
- ic_launcher.png
- placeholder.png
WebServices
- listar-fruta.php
Base de Datos
- lista_imagen
Empezamos con la WebServices
WebServices
listar-fruta.php
<?php
$host='localhost';
$username='root';
$password='12345';
$db="lista_imagen";
$con=mysqli_connect($host,$username,$password,$db) or die('No puede conectarse');
if(mysqli_connect_error($con))
{
echo "Error al conectarse a la base de datos".mysqli_connect_error();
}
$sql="SELECT * from imagen";
$resultado=mysqli_query($con,$sql);
if($resultado)
{
while($row=mysqli_fetch_array($resultado))
{
$data[]=$row;
}
print(json_encode($data));
}
mysqli_close($con);
?>
Continuando la estructura dentro de la capeta imágenes debemos pegar las imágenes acorde a cada uno de nuestros registros, en mi caso como son frutas queda como la siguiente imagen:
Base de datos
lista_imagen
CREATE TABLE `imagen` (
`codigo` int(11) NOT NULL,
`nombre` varchar(100) NOT NULL,
`url` varchar(150) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `imagen` (`codigo`, `nombre`, `url`) VALUES
(1, 'MANZANA', 'manzana.png'),
(2, 'BANANA', 'banana.png'),
(3, 'MANGO', 'mango.png'),
(4, 'UVA', 'uva.png');
Clases
Conector
public class Conector {
public static HttpURLConnection connect(String urlAddress)
{
try {
URL url=new URL(urlAddress);
HttpURLConnection con= (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(20000);
con.setReadTimeout(20000);
con.setDoInput(true);
return con;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
DataParser
public class DataParser extends AsyncTask<Void,Void,Integer> {
Context c;
String jsonData;
ListView listaFrutas;
ProgressDialog pd;
public static final String
URL_IMAGENES = "http://192.168.8.133/imagen/imagenes/";
ArrayList<Fruta> frutas =new ArrayList<>();
public DataParser(Context c, String jsonData, ListView listaFrutas) {
this.c = c;
this.jsonData = jsonData;
this.listaFrutas = listaFrutas;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
pd=new ProgressDialog(c);
pd.setTitle("Parse");
pd.setMessage("Analizando ... Por favor espere");
pd.show();
}
@Override
protected Integer doInBackground(Void... params) {
return this.parseData();
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
pd.dismiss();
if(result==0)
{
Toast.makeText(c,"No se puede analizar", Toast.LENGTH_SHORT).show();
}else {
FrutaAdapter adapter=new FrutaAdapter(c, frutas);
listaFrutas.setAdapter(adapter);
}
}
private int parseData()
{
try
{
JSONArray ja=new JSONArray(jsonData);
JSONObject jo=null;
frutas.clear();
Fruta fruta;
for(int i=0;i<ja.length();i++)
{
jo=ja.getJSONObject(i);
int id=jo.getInt("codigo");
String nombre=jo.getString("nombre");
String imagen=jo.getString("url");
fruta =new Fruta();
fruta.setCodigo(id);
fruta.setNombre(nombre);
fruta.setImageUrl(URL_IMAGENES+imagen);
frutas.add(fruta);
}
return 1;
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
}
DescargarImagen
public class DescargaImagen extends AsyncTask<Void,Void,String> {
Context c;
String urlAddress;
ListView lv;
ProgressDialog pd;
public DescargaImagen(Context c, String urlAddress, ListView lv) {
this.c = c;
this.urlAddress = urlAddress;
this.lv = lv;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
pd=new ProgressDialog(c);
pd.setTitle("Recuperar");
pd.setMessage("Recuperando ... Por favor espere");
pd.show();
}
@Override
protected String doInBackground(Void... params) {
return downloadData();
}
@Override
protected void onPostExecute(String jsonData) {
super.onPostExecute(jsonData);
pd.dismiss();
if(jsonData==null)
{
Toast.makeText(c,"Sin éxito, sin datos recuperados",Toast.LENGTH_SHORT).show();
}else {
//PARSE
DataParser parser=new DataParser(c,jsonData,lv);
parser.execute();
}
}
private String downloadData()
{
HttpURLConnection con= Conector.connect(urlAddress);
if(con==null)
{
return null;
}
try
{
InputStream is=new BufferedInputStream(con.getInputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer jsonData=new StringBuffer();
while ((line=br.readLine()) != null)
{
jsonData.append(line+"n");
}
br.close();
is.close();
return jsonData.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Fruta
public class Fruta {
int codigo;
String nombre;
String url;
public int getCodigo() {
return codigo;
}
public void setCodigo(int id) {
this.codigo = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getUrl() {
return url;
}
public void setImageUrl(String url) {
this.url = url;
}
}
public class FrutaAdapter extends BaseAdapter {
Context c;
ArrayList<Fruta> frutas;
LayoutInflater inflater;
public FrutaAdapter(Context c, ArrayList<Fruta> frutas) {
this.c = c;
this.frutas = frutas;
inflater= (LayoutInflater)
c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return frutas.size();
}
@Override
public Object getItem(int position) {
return frutas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
if(convertView==null)
{
convertView=inflater.inflate(R.layout.lista,parent,false);
}
TextView mombre= (TextView) convertView.findViewById(R.id.txtNombre);
ImageView img= (ImageView) convertView.findViewById(R.id.Imagen);
Fruta fruta = frutas.get(position);
mombre.setText(fruta.getNombre());
PicassoClient.downloadImage(c, fruta.getUrl(),img);
return convertView;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
final static String
URL_WEB_SERVICE="http://192.168.8.133/imagen/web-service/listar-fruta.php";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
final ListView lv= (ListView) findViewById(R.id.lvFrutas);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new DescargaImagen(MainActivity.this,URL_WEB_SERVICE,lv).execute();
}
});
}
}
Layout
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.androfast.pc.appimagenbd.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_menu_send" />
</android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.androfast.pc.appimagenbd.MainActivity"
tools:showIn="@layout/activity_main">
<ListView
android:id="@+id/lvFrutas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
lista.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_margin="10dp"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="5dp"
android:layout_height="150dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="174dp"
android:layout_height="wrap_content"
android:id="@+id/Imagen"
android:padding="10dp"
android:src="@drawable/fruits" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Nombre"
android:id="@+id/txtNombre"
android:padding="10dp"
android:textColor="@color/colorAccent"
android:layout_alignParentLeft="true"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
Drawable
Estas imágenes deben guardarlos en tu carpeta Drawable
Ahora en nuestro AndroidManifest debemos agregar el siguiente permiso:
<uses-permission android:name=»android.permission.INTERNET»/>
Ahora en nuestro build.gradle debemos agregar lo siguiente:
compile ‘com.android.support:design:26.0.0-alpha1’
compile ‘com.android.support:cardview-v7:26.0.0-alpha1’
compile ‘com.squareup.picasso:picasso:2.5.2’
y en el mismo archivo de buil.gradle en los corchetes de android agregamos lo siguiente:
useLibrary ‘org.apache.http.legacy’
sino sabes donde te dejo la siguiente imagen:
Hola soy Alex Céspedes fundador de ANDROFAST, programo algunas cosas por diversión, me gusta aprender cosas nuevas y estoy pendiente de todo lo que tenga que ver con tecnología. Este blog lo cree para todas las personas que tengan dificultades en la programación, para ser sincero nunca fui bueno y reprobé algunos cursos de programación, pero mis ganas de aprender pudieron más. SI YO PUEDO TU PUEDES ANIMO!
Gracias por este nuevo tutorial, y aprovecho este post para felicitarte el año nuevo, que ni si quiera lo hice después de enviarte unos correos.
Al ver este tutorial de base de datos me gustaría preguntarte si se puede crear un archivo de base de datos desde Windows para luego poner ese archivo de BD en la aplicación y leer los datos de ahí, los datos que tendría serian fotos, texto y teléfonos, una especie de agenda, para luego hacer llamadas, y de ser posible protegida para no poder ser manipulada, igual la pregunta es tonta, pero eso se puede hacer, o las BS se tienen que crear a base de código desde Andoid Studio?
Hola Socu te respondí por correo tu duda y gracias por la felicitación que tu también tengas un buen año, con respecto a la duda de la BD, déjame decirte que android puede conectarse a casi cualquier gestor de BD por ejemplo se me ocurre que podrías usar postgresql y su gestor PgAdmin que es un gestor en windows y linux se le puede poner contraseña para que nadie mas vea o toque tu BD.
Gracias voy a ver que hay sobre PostgreSQL y PgAdmin, a ver si admite poner archivos jpg, lo que he visto por algun video es que android studio no admite base de datos con mas de 1 Mb, no se si esto es asi, lo digo porque si le voy a poner fotos la base de datos pesara mucho mas de 1 Mb.
Hola de nuevo Socu, me temo que has entendido mal ninguna BD guarda las imágenes, las imaegenes quedan guardadas en tu webservices y solo la dirección de las imágenes se guardan en la BD, asi como esta este tutorial, como veo que aun eres novato te invito a la sección de aprender fácil que esta en nuestro menu, te apuesto que después de eso entenderás muchas cosas y no tendrás problemas con nuestros ejercicios.
Hola Alex, mil gracias por su colaboración. Feliz año, me sirvió mucho el código, saludos desde Bucaramanga (Colombia).
Hola, no Alex, bueno creo que androfast eres tu Alex, como no hay un sitio o foro donde preguntar, lo hice aquí que se habla del tema, no tiene nada que ver con lo que explicas aquí, igual me he expresado mal, pero lo que busco es crear un archivo de BD en Windows para ponerlo luego dentro de Android Studio, nada de poner la BD en un servidor para que se tenga que conectar a internet para buscar información, aunque tampoco tengo un servidor, y luego si la BD contiene imágenes y no se pueden poner dentro de la BD porque tienen que estar en el servidor, pues en su lugar no sé si se pueden poner en la carpeta “assets”, por otro lado he buscado información sobre PostgreSQL y no he conseguido encontrar nada como poner el archivo de BD dentro de Android Studio, sí que hay como crear la BD, pero nada más, igual en videotutoriales que este en inglés se dice como, pero yo no tengo ni idea de inglés.
en el menú de sección de aprender fácil sí que la he repasado y descargado las paginas para poder verlas luego cuando no tenga conexión a internet, pero lo que busco hacer no he conseguido sacarlo de ahí por eso te he preguntado por correo alguna cosa, como por ejemplo algo que acabo de ver, es como cambiar el icono a una aplicación, lo que intento también es cambiar el nombre que aparece en el icono de la aplicación, sí que consigo cambiarlo, pero a la vez se cambia el nombre que tengo puesto en el Toolbar, y quiero que tengan nombres diferentes, he visto mucha información, pero tampoco lo he conseguido. Bueno no sigo, que me parece que me he extendido un poco, jeje.
Hola buenas…tengo una duda sin resolver. ¿Para montar una imagen en un ImageView desde el web service, es necesario la descarga de la foto o se puede «linkar» desde el servidor al terminal o al revés?. Si es imprescindible descargar la foto, en un ListView con muchos item con una foto cado uno ¿no será demasiado «pesado» o llenará en exceso de imágenes la memória del terminal? Espero haberme explicado bien. Un saludo.
Lo genial de programar es que los limites de hacer algo están en tu imaginación, pero lo mas normal al tratar las imágenes es la siguiente: las imágenes están guardadas en una carpeta de la web services y en la base de datos solo esta el nombre de la ruta de dicha imagen. He listado 50 imágenes en un listview sin problemas, habría que saber cuantas imágenes querrás listar tu?
Gracias por tu respuesta, pero no iba por ahí la pregunta. Por ejemplo: la app de Facebook o instagram están muy nutridas de imágenes. Esa cantidad de imágenes las ves en tu terminal, pero no están en tu terminal ¿o si?. Es como en una web que presenta imágenes mudiante url, pero esas imágenes no están en el server que aloja esa web que las visualiza. Es la duda que tengo.
Reitero el agradecimiento por tu rápida respuesta.
Un saludo.
Las empresas grandes como las que comentas usan servidores de archivos a gran escala para guardar dichas imágenes. Y luego solo son llamados hacia la app.
Ja, ja, ja…nada, que no lo acabo de tener claro. Vengo de PHP, y Java me está volviendo loco. Tan sólo el hecho de tener que «tipar» las variables me causa más de un quebradero de cabeza. Así que manos al teclado y al lío.
Gracias por tus respuestas.
Creo que una imagen vale mas que unas cuantas palabras y si aun así no me dejo entender he fallado como el profe Andro jaja
Según la imagen me tomo una foto con mi celular por ejemplo, esta por medio de su aplicación hace conexión con su webservices y la almacena en cualquier servidor de archivos de su pertenencia, luego puedo ver esa misma imagen desde cualquier tipo de aplicación que tenga acceso a consultar su servidor.
Hola, como podría mostrar una fruta de ese listview al hacer click y que me rediriga a un activity
Hola Jennifer usa bundle para lograr lo que deseas:
intent.putExtras(bundle);
startActivity(intent);
Hola amigo, siendo la pregunta de arriba como podría mostrar los datos en otra actividad al seleccionar un item del listview
Podrías hacer el tutorial, me ayudarías mucho y gracias por el aporte que brindas
Hola, tu código es una buena fuente de apoyo pero al tratar de usar PicassoClient no me lo reconoce, porque será?
Jennyfer no sabría que decirte nunca he usado PicassoClient