Retrieving images from web to scrollview using FlickrView

Asmoro

Active Member
Licensed User
Longtime User
Hi All,

I've been working on a way to get images on a scrollview
instead of standard imageviews from the web using the
FlickrView demo.

But it's getting messy and I can't see the wood for the trees
anymore.

This is what I have:

'main module FlickrView demo:

B4X:
Sub Process_Globals
   Dim MainUrl As String
   MainUrl = "http://www.com/test/"
End Sub

Sub Globals
   Dim ImageIndex As Int
   Dim btnConnect As Button
   Dim ImageView1 As ImageView
   Dim ImageView2 As ImageView
   Dim ImageView3 As ImageView
   Dim ImageView4 As ImageView
   Dim ImageView5 As ImageView
   Dim ImageView6 As ImageView
   Dim ImageView7 As ImageView
   Dim ImageView8 As ImageView
   Dim ImageView9 As ImageView
   Dim ivs() As ImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   ivs = Array As ImageView(ImageView1, ImageView2, ImageView3, ImageView4, _
      ImageView5, ImageView6, ImageView7, ImageView8, ImageView9)
   ResetImagesBackground
   HttpUtils.CallbackActivity = "Main"
   HttpUtils.CallbackJobDoneSub = "JobDone"
End Sub



Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub btnConnect_Click
   HttpUtils.CallbackUrlDoneSub = "" 'don't want to handle this event
   HttpUtils.Download("Main page", MainUrl)
   ProgressDialogShow("Fetching data...")
End Sub

Sub Activity_Resume
   'This is important as it is possible that the activity was in the background when the job has finished.
   If HttpUtils.Complete Then JobDone(HttpUtils.Job)
End Sub

'Usually we will want to have a single JobDone sub for all jobs.
'This allows us to check HttpUtils.Complete flag in Activity_Resume (as shown above).
Sub JobDone(Job As String)
   Select job
      Case "Main page"
         HandleMainPage
      Case "Images"
         ImagesJobDone
   End Select
   HttpUtils.Complete = False
End Sub
'Parse the main page and find the 9 image links
Sub HandleMainPage
   If HttpUtils.IsSuccess(MainUrl) = False Then
      ToastMessageShow("Error downloading main page.", True)
      Return
   End If
   ResetImagesBackground
   start = DateTime.Now
   Dim TextReader1 As TextReader
   TextReader1.Initialize(HttpUtils.GetInputStream(MainUrl))
   Dim pattern, class As String
   class = "<td class=" & QUOTE & "thumbcell" & QUOTE & ">"
   pattern = "img src=\q([^q]+)\q".Replace("q", QUOTE)
   Dim links As List
   links.Initialize
   Dim line As String
   line = TextReader1.ReadLine
   Do While line <> Null
      If line.IndexOf(class) > -1 Then
         Dim link As String
         Dim m As Matcher
         m = Regex.Matcher(pattern, line)
         If m.Find Then
            links.Add("http://www.com/test/" & m.Group(1).Replace("_small","")) 'add the image link
         End If
      End If
      line = TextReader1.ReadLine
   Loop
   TextReader1.Close
   Log("done parsing main page: " & (DateTime.Now - start))
   HttpUtils.CallbackUrlDoneSub = "ImageUrlDone"
   HttpUtils.DownloadList("Images", links)
   ImageIndex = 0
   btnConnect.Enabled = False
   ProgressDialogHide
End Sub

Sub ImageUrlDone (Url As String)
   ivs(ImageIndex).Bitmap = HttpUtils.GetBitmap(Url)
   ivs(ImageIndex).Gravity = Gravity.FILL
   ImageIndex = ImageIndex + 1
   'The SuccessfulUrls map holds all the successful links. We are removing this link from the list
   'to avoid dealing with this link again in ImagesJobDone
   HttpUtils.SuccessfulUrls.Remove(Url)
End Sub
Sub ImagesJobDone
   'In most cases this For loop will not be used, assuming that ImageUrlDone was called for each Url.
   'However if the activity was paused during the download it is possible that we have missed some calls.
   'So here we make sure that all downloaded images are visible.
   For i = 0 To HttpUtils.SuccessfulUrls.Size - 1
      ivs(ImageIndex + i).Bitmap = HttpUtils.GetBitmap(HttpUtils.SuccessfulUrls.GetKeyAt(i))
      ivs(ImageIndex + i).Gravity = Gravity.FILL
   Next
   btnConnect.Enabled = True
End Sub

Sub ResetImagesBackground
   For i = 0 To Activity.NumberOfViews - 1
      If Activity.GetView(i) Is ImageView Then Activity.GetView(i).Color = Colors.Black
   Next
End Sub

'Show the second activity with the chosen image.
Sub img_Click
   Dim iv As ImageView
   iv = Sender
   Dim bd As BitmapDrawable
   bd = iv.Background
   Activity2.bmp = bd.Bitmap
   StartActivity(Activity2)
End Sub

And the scrollview module:

B4X:
Sub Process_Globals
   Dim Bitmaps As List
End Sub

Sub Globals
   Dim LbResults As Label
   Dim ScrollView1 As ScrollView
   Dim iv3 As ImageView
   Dim Panel2 As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
   
                                    
   ProgressDialogShow("Loading images")
   LoadImages
   ProgressDialogHide
   
   Activity.LoadLayout("results")                            
   ScrollView1.Panel.Height = 300dip * Bitmaps.Size          
   For i = 0 To Bitmaps.Size - 1
      Dim iv As ImageView                            
      iv.Initialize("iv")                              
      Dim bd As BitmapDrawable
      bd.Initialize(Bitmaps.Get(i))
      iv.Background = bd                               
      ScrollView1.Panel.AddView(iv, 5dip, 5dip + i * 300dip, ScrollView1.Width - 10dip, 290dip)  
   Next
   
End Sub

Sub LoadImages

   Bitmaps.Initialize
   Dim f As String

   If File.Exists(Main.ImageFolder, "") = False Then
      ToastMessageShow("Images not found:" & CRLF & Main.ImageFolder, True)
      Return
   End If
   For i = 0 To Main.Files.Size - 1
      f = Main.Files.Get(i)
      If f.ToLowerCase.EndsWith(".jpg") Then
         Dim b As Bitmap
         b.InitializeSample(Main.ImageFolder, f, 300dip, 300dip) 
         Bitmaps.Add(b)
         If Bitmaps.Size > 100 Then Exit 
      End If
   Next
   ToastMessageShow(Bitmaps.Size & "  images found", False)
End Sub

Sub iv_Click

   Dim iv As ImageView
    iv = Sender
    Dim bd As BitmapDrawable
    bd = iv.Background
    showpics.Bitmap1 = bd.Bitmap
   
   StartActivity(showpics)
   
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

If someone's willing to give me a hint or direction, I would appreciate it.

Thanks for now.
 

Asmoro

Active Member
Licensed User
Longtime User
Here you are.

The latest achievement to reach the goal is in the test prog.

Somehow the connection between the image urls and the scrollview
didn't go well.

Hope you can find the problem.

Thanks for now.
 
Last edited:
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Hi All,

First to say, best wishes 2012 to all of you and may
your dreams comes true.

Secondly, does anyone succeed my testprog to work?

Ideas are running empty where to start to look at.
Unfortunately, there's no info around about making link with webimages
displaying on a scrollview.

I made another testprog, now with 2 buttons, each
connected with their corresponding sites with error links.
 
Last edited:
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Hi Klaus,

Thousand thanks for your effort and contribution.

I never will guess the way how you managed it, as I'm watching your
code deeply.:sign0188:

You're truly a scrollview guru.:D

One question though, did you change some things in http utils/and service modules?

Btw, this example could be useful for the ScrollView examples summary
as well, don't you?
If it's worthwile I'll delete the test url etc.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
One question though, did you change some things in http utils/and service modules?
No, I didn't.

I never will guess the way how you managed it, as I'm watching your
code deeply
Compare both codes, you will find the differences.

Btw, this example could be useful for the ScrollView examples summary
as well, don't you?
If it's worthwile I'll delete the test url etc.
From the ScrollView point of view there is almost no difference with the Flickr project. And as you remove your site there will be no reference anymore to the images.

Best regards.
 
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Hi Klaus,

I'm working on the testprog to have more than one button
to connect corresponding links.

I made a little progress and it did work a bit with some errors,
but I have the feeling that the coding could be written much
better and much tidier.

So if I have two buttons like:

bntConnect1 -->url: "http://www.testtest.bugs3.com/test/"
bntConnect2 -->url: "http://www.testtest.bugs3.com/test2/"

and the code is:

B4X:
Sub Process_Globals
   Dim MainUrl, MainUrl2 As String
   MainUrl = "http://www.testtest.bugs3.com/test/"
   MainUrl2= "http://www.testtest.bugs3.com/test2/"
   'Dim ImageFolder As String
   Dim Files As List
   Dim Bitmaps As List   
   Dim Images As List
   Dim PhoneOrient As Phone
End Sub

Sub Globals
   Dim iv As ImageView 
   Dim btnConnect1 As Button
   Dim lblComment As Label
   Dim btnConnect2 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
   PhoneOrient.SetScreenOrientation(1)
   Activity.LoadLayout("1")
   
   Bitmaps.Initialize
   Images.Initialize
   
   HttpUtils.CallbackActivity = "Main"
   HttpUtils.CallbackJobDoneSub = "JobDone"
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnConnect1_Click
   lblComment.Visible = True
   lblComment.Text = "Connection..."
   btnConnect1.Visible = False
   HttpUtils.CallbackUrlDoneSub = "" 'don't want to handle this event
   HttpUtils.Download("Main page", MainUrl)
'   ProgressDialogShow("Fetching data...")
   lblComment.Text = "Fetching data..."
End Sub
Sub btnConnect2_Click
   lblComment.Visible = True
   lblComment.Text = "Connection..."
   btnConnect2.Visible = False
   HttpUtils.CallbackUrlDoneSub = "" 'don't want to handle this event
   HttpUtils.Download("Main page", MainUrl2)
'   ProgressDialogShow("Fetching data...")
   lblComment.Text = "Fetching data..."
End Sub

Sub Activity_Resume
   'This is important as it is possible that the activity was in the background when the job has finished.
   If HttpUtils.Complete Then JobDone(HttpUtils.Job)
End Sub

'Usually we will want to have a single JobDone sub for all jobs.
'This allows us to check HttpUtils.Complete flag in Activity_Resume (as shown above).
Sub JobDone(Job As String)
   Select job
      Case "Main page"
         HandleMainPage
      Case "Images"
         ImagesJobDone
   End Select
   HttpUtils.Complete = False
End Sub
Sub JobDone2(Job As String)
   Select job
      Case "Main page"
         HandleMainPage2
      Case "Images"
         ImagesJobDone2
   End Select
   HttpUtils.Complete = False
End Sub

'Parse the main page and find the image links
Sub HandleMainPage
   If HttpUtils.IsSuccess(Mainurl) = False Then
      ToastMessageShow("Error downloading main page.", True)
      Return
   End If
   ResetImagesBackground
   start = DateTime.Now
   Dim TextReader1 As TextReader
   TextReader1.Initialize(HttpUtils.GetInputStream(MainUrl))
   Dim pattern, class As String
   class = "<td class=" & QUOTE & "thumbcell" & QUOTE & ">"
   pattern = "img src=\q([^q]+)\q".Replace("q", QUOTE)
   Dim links As List
   links.Initialize
   Dim line As String
   line = TextReader1.ReadLine
   Do While line <> Null
      If line.IndexOf(class) > -1 Then
         Dim m As Matcher
         m = Regex.Matcher(pattern, line)
         If m.Find Then
            links.Add("http://www.testtest.bugs3.com/test/" & m.Group(1).Replace("_small","")) 'add the image link
            lblComment.Text = links.Size & " images found"
            Images.Add(m.Group(1))
            DoEvents
         End If
      End If
      line = TextReader1.ReadLine
   Loop
   TextReader1.Close
   Log("done parsing main page: " & (DateTime.Now - start))
   HttpUtils.CallbackUrlDoneSub = "ImageUrlDone"
   HttpUtils.DownloadList("Images", links)
   ImageIndex = 0
'   btnConnect1.Enabled = True
   ProgressDialogHide
End Sub
Sub HandleMainPage2
   If HttpUtils.IsSuccess(Mainurl2) = False Then
      ToastMessageShow("Error downloading main page.", True)
      Return
   End If
   ResetImagesBackground
   start = DateTime.Now
   Dim TextReader2 As TextReader
   TextReader2.Initialize(HttpUtils.GetInputStream(MainUrl2))
   Dim pattern, class As String
   class = "<td class=" & QUOTE & "thumbcell" & QUOTE & ">"
   pattern = "img src=\q([^q]+)\q".Replace("q", QUOTE)
   Dim links As List
   links.Initialize
   Dim line As String
   line = TextReader2.ReadLine
   Do While line <> Null
      If line.IndexOf(class) > -1 Then
         Dim m As Matcher
         m = Regex.Matcher(pattern, line)
         If m.Find Then
            links.Add("http://www.testtest.bugs3.com/test2/" & m.Group(1).Replace("_small",""))'add the image link
            lblComment.Text = links.Size & " images found"
            Images.Add(m.Group(1))
            DoEvents
         End If
      End If
      line = TextReader2.ReadLine
   Loop
   TextReader2.Close
   Log("done parsing main page: " & (DateTime.Now - start))
   HttpUtils.CallbackUrlDoneSub = "ImageUrlDone"
   HttpUtils.DownloadList("Images", links)
   ImageIndex = 0
'   btnConnect2.Enabled = True
   ProgressDialogHide
End Sub


Sub ImageUrlDone (Url As String)
   Bitmaps.Add(HttpUtils.GetBitmap(Url))
   lblComment.Text = "loading images"
   'The SuccessfulUrls map holds all the successful links. We are removing this link from the list
   'to avoid dealing with this link again in ImagesJobDone
   HttpUtils.SuccessfulUrls.Remove(Url)
End Sub

Sub ImagesJobDone
   'In most cases this For loop will not be used, assuming that ImageUrlDone was called for each Url.
   'However if the activity was paused during the download it is possible that we have missed some calls.
   'So here we make sure that all downloaded images are visible.
'   For i = 0 To HttpUtils.SuccessfulUrls.Size - 1
'      iv.Bitmap = HttpUtils.GetBitmap(HttpUtils.SuccessfulUrls.GetKeyAt(i))
'      iv.Gravity = Gravity.FILL
'   Next
   lblComment.Visible = False
   btnConnect1.Visible = True
   StartActivity(result)
End Sub
Sub ImagesJobDone2
   'In most cases this For loop will not be used, assuming that ImageUrlDone was called for each Url.
   'However if the activity was paused during the download it is possible that we have missed some calls.
   'So here we make sure that all downloaded images are visible.
'   For i = 0 To HttpUtils.SuccessfulUrls.Size - 1
'      iv.Bitmap = HttpUtils.GetBitmap(HttpUtils.SuccessfulUrls.GetKeyAt(i))
'      iv.Gravity = Gravity.FILL
'   Next
   lblComment.Visible = False
   btnConnect2.Visible = True
   StartActivity(result)
End Sub

Sub ResetImagesBackground
   For i = 0 To Activity.NumberOfViews - 1
      If Activity.GetView(i) Is ScrollView Then Activity.GetView(i).Color = Colors.Black
   Next
End Sub

How would you do it to make this code working for
multiple buttons.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
You don't need to duplicate the routines, you can use the same for the different urls.
I would put the urls in a String array and work with an index to select the current url.

You have different options:
- use different Buttons, with the same event name and use the Tag property as the index.
- use a Spinner and a Button, the spinner to select and the button to run the index is given by the position of the selection in the spinner.

B4X:
Sub Process_Globals
    Dim MainUrl(2) As String
    MainUrl(0) = "http://www.testtest.bugs3.com/test/"
    MainUrl(1) = "http://www.testtest.bugs3.com/test2/"
    Dim URLIndex As Int
    'Dim ImageFolder As String
    Dim Files As List
    Dim Bitmaps As List    
    Dim Images As List
    Dim PhoneOrient As Phone
End Sub
B4X:
Sub btnConnect_Click
    Dim btn As Button
    btn = Sender
    URLIndex = btn.Tag
    lblComment.Visible = True
    lblComment.Text = "Connection..."
    btnConnect1.Visible = False
    HttpUtils.CallbackUrlDoneSub = "" 'don't want to handle this event
    HttpUtils.Download("Main page", MainUrl(URLIndex))
'    ProgressDialogShow("Fetching data...")
    lblComment.Text = "Fetching data..."
End Sub
B4X:
Sub HandleMainPage
    If HttpUtils.IsSuccess(Mainurl(URLIndex)) = False Then
        ToastMessageShow("Error downloading main page.", True)
        Return
    End If
    ResetImagesBackground
    start = DateTime.Now
    Dim TextReader1 As TextReader
    TextReader1.Initialize(HttpUtils.GetInputStream(MainUrl(URLIndex)))
    Dim pattern, class As String
    class = "<td class=" & QUOTE & "thumbcell" & QUOTE & ">"
    pattern = "img src=\q([^q]+)\q".Replace("q", QUOTE)
    Dim links As List
    links.Initialize
    Dim line As String
    line = TextReader1.ReadLine
    Do While line <> Null
        If line.IndexOf(class) > -1 Then
            Dim m As Matcher
            m = Regex.Matcher(pattern, line)
            If m.Find Then
                links.Add(Mainurl(URLIndex) & m.Group(1).Replace("_small",""))'add the image link
                lblComment.Text = links.Size & " images found"
                Images.Add(m.Group(1))
                DoEvents
            End If
        End If
        line = TextReader1.ReadLine
    Loop
    TextReader1.Close
    Log("done parsing main page: " & (DateTime.Now - start))
    HttpUtils.CallbackUrlDoneSub = "ImageUrlDone"
    HttpUtils.DownloadList("Images", links)
    ImageIndex = 0
'    btnConnect2.Enabled = True
'    ProgressDialogHide
End Sub
Code proposal, not tested.

Best regards.
 
Last edited:
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Thanks for your advise, it looks way much better than mine.:sign0098:

I will try it a.s.a.p. and let you know the findings.

Ciao
 
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Hi Klaus,

I tried it and made the implementation, but didn't work.

I guess I don't understand you completely what you meant.

But anyway, underneath the testprog to look at it.
 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User

Attachments

  • FlickrViewerWebimagesTest2Buttons2.zip
    12.2 KB · Views: 227
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Hi Klaus,

Great, testing time....

Actually, I'm not familiar with memory problems yet.

How come you have memory problems with this prog,
as I don't remember that I have something similar with
their problem. (no canvas here, etc)

Unless has something to do with my (big) test images.
But these were resized by the code of vb1992 making
it smaller in the end.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
The problem is the number of bitmaps.
I added the index of the image to load to the display.
When loading a second set of images the program loads a certain number of images and stops.
When loading the new set the memory for the 'old' bitmaps is not freed yet so I added agrahams code to force a 'recycle' of the no more used bitmaps.
I tested it with the Emulator.

Best regards.
 
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Ok, now I get it.

Hmm... time to think about how to erase all kinds of caching
during or after the app use then.
 
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Hi Klaus,

I was implementing your working FlickrView2Buttons testprog in a new testprog.

It's a little bit embarrasing, but after a dozens of time with analyzing and reprogramming the whole thing, still didn't work as it should be.

So would you mind to analyze what I did something wrong.

Thanks for now.
 

Attachments

  • WebTest.zip
    13 KB · Views: 210
Upvote 0

klaus

Expert
Licensed User
Longtime User
Here you are:
- for the two buttons in the selecting activity you missed to add the Tag properties 0 and 1 and you missed to set the EventName the same, 'btnTest', for both!
- in result you added a Dim Bitmaps() that already does exist in settings so you initiate a new object and loose the previous one. In result you must refer to the Bitmaps loaded in settings with settings.Bitmaps().
- in HttpUtilsServices you changed tis line 19: from the original
If TempFolder = "" Then TempFolder = File.DirInternalCache
to
If TempFolder = "" Then TempFolder = File.DirRootExternal & "/tmp/"
why ?
I changed it in my previous code to
If TempFolder = "" Then TempFolder = File.DirRootExternal
because it raised an error, but looking at the original file I now set to the original one.

I find your entry to the program complicated.
Why having
- a first activity to call selection
- then a second activity to do the selection ?

As a user I always have this motto: the less 'clicks' to get anything the better.

Best regards.
 

Attachments

  • WebTest1.zip
    13 KB · Views: 201
Upvote 0

Asmoro

Active Member
Licensed User
Longtime User
Thanks for explaining to me.

- for the two buttons in the selecting activity you missed to add the Tag properties 0 and 1 and you missed to set the EventName the same, 'btnTest', for both!

Yes, I figured that (much) later on by continuing testing the prog, and set the EventName...:signOops:, I forgot.

- in result you added a Dim Bitmaps() that already does exist in settings so you initiate a new object and loose the previous one. In result you must refer to the Bitmaps loaded in settings with settings.Bitmaps().

I did that once I got an error saying I have to "initialize" that.:confused:

- in HttpUtilsServices you changed tis line 19: from the original
If TempFolder = "" Then TempFolder = File.DirInternalCache
to
If TempFolder = "" Then TempFolder = File.DirRootExternal & "/tmp/"
why ?
I changed it in my previous code to
If TempFolder = "" Then TempFolder = File.DirRootExternal
because it raised an error, but looking at the original file I now set to the original one.

No error in my case, that's why I left the way it was.

I find your entry to the program complicated.
Why having
- a first activity to call selection
- then a second activity to do the selection ?

As a user I always have this motto: the less 'clicks' to get anything the better.

Logically yes, I agree with you.
But I have a so called "homepage" with 3 buttons, each has different function. The testprog that you'd analyzed is one of the three.

It'll be clear once the app is finished and ready to show on the B4A. (I hope)
 
Last edited:
Upvote 0
Top