Spanish [SOLUCIONADO]B4A-Cargar imagen desde url

Seneca

Active Member
Licensed User
Hola.

En el mensaje #9 de este hilo Erel pone un código completo de una descarga de archivo, incluido el Jobdone. Adáptalo según tus necesidades.

Saludos.

B4X:
Sub Process_Globals
   
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   For Each s As String In Array As String("save.jpg", "Button-Add-icon.png", "ruta.jpg", _
      "excel.png")
      Dim job As HttpJob
      job.Initialize(s, Me)
      job.Download("http://www..mx/uploads/" & s)
   Next
End Sub

Sub JobDone (Job As HttpJob)
   Log("JobName = " & Job.JobName &" -Image Download Name = "& ", Success = " & Job.Success)
   If Job.Success = True Then
      'is this really needed ???
       Dim out As OutputStream
       out = File.OpenOutput(File.DirDefaultExternal, Job.JobName ,False )
       File.Copy2(Job.GetInputStream, out)
       out.Close
       Activity.SetBackgroundImage(Job.GetBitmap)
   Else
      Log("Error: " & Job.ErrorMessage)
      ToastMessageShow("Error: " & Job.ErrorMessage, True)
   End If
   Job.Release
End Sub
 

ferpahud

Active Member
Licensed User
Hola.

En el mensaje #9 de este hilo Erel pone un código completo de una descarga de archivo, incluido el Jobdone. Adáptalo según tus necesidades.

Saludos.

B4X:
Sub Process_Globals
  
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   For Each s As String In Array As String("save.jpg", "Button-Add-icon.png", "ruta.jpg", _
      "excel.png")
      Dim job As HttpJob
      job.Initialize(s, Me)
      job.Download("http://www..mx/uploads/" & s)
   Next
End Sub

Sub JobDone (Job As HttpJob)
   Log("JobName = " & Job.JobName &" -Image Download Name = "& ", Success = " & Job.Success)
   If Job.Success = True Then
      'is this really needed ???
       Dim out As OutputStream
       out = File.OpenOutput(File.DirDefaultExternal, Job.JobName ,False )
       File.Copy2(Job.GetInputStream, out)
       out.Close
       Activity.SetBackgroundImage(Job.GetBitmap)
   Else
      Log("Error: " & Job.ErrorMessage)
      ToastMessageShow("Error: " & Job.ErrorMessage, True)
   End If
   Job.Release
End Sub
En este caso descarga una sola imagen, pero si yo necesito descargar una lista de imagenes? El hilo lo continue en un tema nuevo, porque creo q ya se habia desviado un poco el asunto.... en este nuevo hilo explique lo siguiente:

Priemor actualizo la base de datos, descargo de una base de datos online todos los registros y los guardo en una bd local. Luego, con este metodo recorro la base de datos local y guardo las imagenes que existen dentro de dicha db:
B4X:
Sub imagenesCargadas
'Con lo siguiente consultas la BD y guardas en la lista lstImagenesIconos el nombre de todas las imagenes de los comercios
lstImagenesIconos.Initialize
Dim UnaImagen As String
c=s.ExecQuery("SELECT imagen FROM comercios")
If c.RowCount>0 Then
    For i=0 To c.RowCount-1
        c.Position=i
        UnaImagen=c.GetString("imagen")
        lstImagenesIconos.Add(UnaImagen)
    Next
    End If
End Sub

Luego, de esa lista de imagenes, controlo si existen en dirassets, armo una lista con las que no existen en dirassets, y luego de esa lista controlo que imagenes existen en dirInternal:
B4X:
Sub imagenesPendientes
    Dim UnaImagen As String
    Dim UnaImagenProvisoria As String
    lstImagenesPendientesProvisorias.Initialize
    lstImagenesPendientes.Initialize
'Con el siguiente For-next recorres la lista de imágenes y compruebas cuáles de ellas las tienes ya descargadas y creas una nueva lista con las que te falten
For Numero = 0 To lstImagenesIconos.size - 1
     UnaImagen = lstImagenesIconos.Get(Numero) 'Recupera de la Lista de imágenes el nombre de cada una
     Log(UnaImagen&" que muestra?")
     'Comprueba si existe la imagen del botón y en caso contrario manda la guarda en la lista de imágenes faltantes

    'Comprueba si el archivo existe
     If Not(File.Exists(File.DirAssets,UnaImagen)) Then
         Log(UnaImagen & " - No existe")
         lstImagenesPendientesProvisorias.Add(UnaImagen)
     End If
Next

For i = 0 To lstImagenesPendientesProvisorias.Size - 1
    UnaImagenProvisoria = lstImagenesPendientesProvisorias.Get(i)
    If Not (File.Exists(File.DirInternal,UnaImagenProvisoria)) Then
        lstImagenesPendientes.Add(UnaImagenProvisoria)
    End If
Next
End Sub

Con las imagenes que no estan en dirAssets, ni en dirInternal, armo una nueva lista, esta lista contiene las imágenes a descargar.

Dentro del JobDone, que descarga la bd externa para actualizar las nuevas imagenes, llamo a un metodo para descargar las imagenes:
B4X:
Case "GetComercios"
                Dim ListaDatos As List
                ListaDatos = parser.NextArray 'returns a list with maps
                If ListaDatos.Size == 0 Then
                   'Algun mensaje.
                Else
                  s.BeginTransaction
                  s.ExecNonQuery("DELETE FROM comercios")
                  For i = 0 To ListaDatos.Size - 1
                       Dim Datos As Map
                       Datos = ListaDatos.Get(i)
                       s.ExecNonQuery2("INSERT INTO comercios VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)", Array As String(Datos.Get("id_comercio"), Datos.Get("id_rubro"), Datos.Get("comercio"), Datos.Get("imagen"), Datos.Get("descuento"), Datos.Get("direccion"), Datos.Get("latitud"), Datos.Get("longitud"), Datos.Get("telefono"), Datos.Get("correo_electronico"), Datos.Get("web"), Datos.Get("orden_listado"), Datos.Get("cantidad_ingresos")))
                  Next
                          'ToastMessageShow("Comercios actualizados", False)
                          imagenesCargadas
                          imagenesPendientes
                          descargarImagenes
                          s.TransactionSuccessful
                          s.EndTransaction
                End If
        End Select

El metodo que descarga la imagen:
B4X:
Sub descargarImagenes
    hilo.Initialize("hilo",Me)
    For Each imagenItem In lstImagenesPendientes
        hilo.Download("http://centrocomercialva.com.ar/imagenes/" & imagenItem)
        Log(imagenItem & " - Descargada")
        Dim out As OutputStream =File.OpenOutput(File.DirInternal, imagenItem, False)
        out.Close '<------ very important
    Next
End Sub

En otra pantalla, quiero listar los comercios y me da un erro de "Error loading bitmap". EL codigo para listarlos es el siguiente:
B4X:
Sub listarComercios
    c=s.ExecQuery("SELECT id_comercio,descuento,comercio,direccion,imagen FROM comercios WHERE comercios.id_rubro='" & Main.rubroElegido & "'")
    ListView1.Clear
    If c.RowCount>0 Then
        For i=0 To c.RowCount-1
            c.Position=i
            imagen=c.GetString("imagen")
            If( File.Exists(File.DirAssets,imagen)) Then
                ListView1.AddTwoLinesAndBitmap2(c.GetString("comercio"), c.GetString("descuento"),LoadBitmap(File.DirAssets,c.GetString("imagen")),c.GetString("id_comercio"))
            Else
                Log(imagen)
                ListView1.AddTwoLinesAndBitmap2(c.GetString("comercio"), c.GetString("descuento"),LoadBitmap(File.DirInternal,imagen),c.GetString("id_comercio"))
            End If
        Next
    End If
End Sub

Cuando cargo un nuevo comercio en la base de datos externas, al ejecutar por primera vez la app me aparece el log que puese para saber si detecta la imagen que no exite, y tambien aparece el log de "imagen descargada", que puse para saber si la descarga. Luego si la ejecuto de nuevo, la detecta como que no exite, pero no la descarga...
 

Seneca

Active Member
Licensed User
Hola.

El ejemplo que te puse más arriba no descarga una imagen, como tú comentas, sino cuatro (save.jpg", "Button-Add-icon.png", "ruta.jpg", _"excel.png").

El metodo que descarga la imagen:
B4X:
Sub descargarImagenes
    hilo.Initialize("hilo",Me)
    For Each imagenItem In lstImagenesPendientes
        hilo.Download("http://centrocomercialva.com.ar/imagenes/" & imagenItem)
        Log(imagenItem & " - Descargada")
        Dim out As OutputStream =File.OpenOutput(File.DirInternal, imagenItem, False)
        out.Close '<------ very important
    Next
End Sub

Este código está mal. Has mezclado en una sola rutina el .downlodad con el JobDone, y esto así no funciona. JobDone debe ser una rutina que ha de existir sí o sí,y justo con ese nombre (JobDone). Cada ejecución de .download provocará que se ejecute un evento JobDone. Es decir, tú mandas descargar 3 imágenes ejecutando 3 veces el .download. Cada uno de estos .download provocarán una ejecución de la rutina JobDone, en la cual lo primero que se hace es comprobar si la descarga del archivo se ha podido efectuar (If Job.Success = TrueThen...) El que la descarga haya sido correcta no quiere decir que ya lo tengas guardado en tu dispositivo. Por ero, en caso de que haya sido correcta, lo siguiente es guardar el archivo (out = File.OpenOutput(File.DirDefaultExternal, Job.JobName ,False ......)

Te recomiendo que ejecutes el ejemplo que te indiqué más arriba paso a paso para que entiendas cómo funciona esto del JobDone. La verdad es que es bastante simple. Pero si no entiedes el proceso que sigue esta librería complicado es que llegues a poder adaptarlo a tus necesidades.

Saludos.
 

rscheel

Well-Known Member
Licensed User
Longtime User
Estimado como le comento @Seneca su codigo esta mal comenzando con que no debe usar
File.DirInternal, si no que debe usar File.DirDefaultExternal con ello la informacion de tu app queda en la Carpeta Android/Data/NombredeApp(Ej. com.example.b4a)/files
 

Seneca

Active Member
Licensed User
En eso no me había fijado. Creo que si se toman en cuenta todas las indicaciones que se han dado en este y en el otro hilo este asunto estaría totalmente resuelto. Pienso que ejecutar paso a paso los distintos ejemplos publicados también es básico para entender/aprender.
 
Top