Cursussen/Courses Codesnippets     Top 
B4A-JSON - B4A app code


1. Initializations
Declare the variables:
Sub Globals
	Private ipaddress As String = "192.168.1.190"	' ip address from PC/laptop
	Private url As String
	Private postvars As String
	Private cbx1 As B4XComboBox
	Private cbx2 As B4XComboBox
	Public catlst As List
	Public subcatlst As List
	Public itemlst As List
	Public catidlst As List
	Public subcatidlst As List
	Public itemidlst As List
	Private clv1 As CustomListView
	Private B4XLoadingIndicator3 As B4XLoadingIndicator
	Private RTCS As ResizingTextComponent
	Private lbl1 As Label
	Private lbl2 As Label
	Private pnlitem As Panel
	Private pnlnote As Panel
	Private MediaPlayer1 As MediaPlayer
	Private source As String
End Sub
The ipaddress is set to the local IP address from your PC or laptop where you run the web server on. Depending how you are connected to your local network this address may vary.
The url and postvars strings are used as arguments to the HttpJob PostString method. See also in the Read JSON section.
The HttpJob object is defined in the OkHttpUtils2 library. So add it to the list in the Library Manager pane.
Initialize the variables:
Sub Activity_Create(FirstTime As Boolean)
	Activity.LoadLayout("Layout")
	Activity.Title = "Thai translations"
	catlst.Initialize
	subcatlst.Initialize
	itemlst.Initialize
	catidlst.Initialize
	subcatidlst.Initialize
	itemidlst.Initialize
	MediaPlayer1.Initialize
	B4XLoadingIndicator3.show
	Sleep(10)
	source = "local"
	Select source
		Case "local"
			url = "http://" & ipaddress & ":443/translations/lists_JSON.php"
			postvars = "B53bLkN2ekAUHRFddzuJ=Ud4wvW4DM74VPhNsUz3y"
			read_json(url, postvars)			
		Case "online"
			' replace / with the correct information
			url = "https://<your website>/<your folder>/lists_JSON.php"
			postvars = "F6vjhe3D4C9gDsRSQdHF=HFPNPPQCk4wkMdESHhhg"
			read_json(url, postvars)		
		Case Else
			xui.MsgboxAsync("Unknown source","JSON source")
			Exit
	End Select
End Sub
The source variable is initialized to 'local' to read the JSON string from the local web server.
If you change the value of the source variable to 'online' then you should edit the url variable to point to your specific online web server.
If you expand the select statement then you could allow as a source for instance a local text file. This requires a call to an additional subroutine. Can you write such a subroutine?


2. Read JSON
Private Sub read_json(strurl As String, strpost As String)
	Dim j As HttpJob
	j.Initialize("",Me)
	j.PostString(strurl,strpost)
	Wait For (j) JobDone (j As HttpJob)
	If j.Success Then
		B4XLoadingIndicator3.Hide
		Log(j.GetString)
		If j.GetString.Length > 0 Then
			'Log(j.GetString)
			' using the parser object
			'Dim parser As JSONParser
			'parser.Initialize(j.GetString)
			'Private tablelst As List = parser.NextArray
			' using the as(JSON).ToList type conversion		
			Dim tablelst As List = j.GetString.as(JSON).ToList 	'ignore
			catlst = tablelst.Get(0)
			subcatlst = tablelst.Get(1)
			itemlst = tablelst.Get(2)
			fill_cbx1
			fill_cbx2
			fill_clv1
		Else
			xui.MsgboxAsync("Empty JSON object!","JSON result")
			Sleep(2000)
			ExitApplication
		End If
	End If
End Sub
In this subroutine the HttpJob object uses the PostString method to send a POST request to the web server. A new thread is used and with the Wait For statement the main thread waits for the response from the web server.
If the receiving of the response was a success (j.Success) then we can start parsing the string containing the JSON object.
Working with JSON objects requires a JSON library. Add it to the list in the Library Manager pane.
You can convert the string using a JSONParser object (see commented lines) or you can use the new type conversion that is available in the new B4A IDE version.
The JSONParser object (parser) needs to be initialized and then you can use the parser.NextArray method to get a local list (tablelst).
In this case it's an array of arrays of arrays (see the Json Tree image in the PHP scripts section).
Note: if the response is a map then you could use parser.NextObject.
In this example we use the new type conversion way. The response string is converted to a JSON type and then converted to a list. (Dim tablelst As List = j.GetString.as(JSON).ToList). This one line replaces the three lines when using the JSONParser object.
The next thing to do is to extract the 3 arrays for the category, subcategory and item information. In the Json Tree image you can see that they have the indexes 0, 1 and 2. With the statement catlst = tablelst.Get(0) we get the category list, with subcatlst = tablelst.Get(1) we get the subcategory list and with itemlst = tablelst.Get(2) we get the item list.


3. Fill Comboboxes
Now that we have the necessary lists we can start filling the comboboxes.
The catidlst list contains the id's from the category records. These id's are used in the fill_cbx2 subroutine to filter out the subcategories belonging to the selected category.
Private Sub fill_cbx1
	catidlst.Clear
	Private lst As List
	lst.Initialize
	For i = 1 To catlst.Size -1
		Private rec As List = catlst.Get(i)
		lst.Add(rec.Get(1))
		catidlst.Add(rec.Get(0))
	Next
	cbx1.SetItems(lst)
	cbx1.SelectedIndex = 0
	fill_cbx2
End Sub

Private Sub fill_cbx2
	subcatidlst.Clear
	Private lst As List
	lst.Initialize
	For i = 1 To subcatlst.Size -1
		Private rec As List = subcatlst.Get(i)
		If rec.Get(2) = catidlst.Get(cbx1.SelectedIndex) Then
			lst.Add(rec.Get(1))
			subcatidlst.Add(rec.Get(0))
		End If
	Next
	cbx2.SetItems(lst)
	cbx2.SelectedIndex = 0
	fill_clv1
End Sub


4. Fill CustomListView
In the fill_clv1 subroutine the item records are filtered using the list of subcategory id's (subcatidlst).
If there is a sound file present (added via the Files Manager pane in the IDE) then a play icon (copied from the FontAwesome list) will be added to the title.
Private Sub fill_clv1
	clv1.Clear
	itemidlst.Clear
	For i = 1 To itemlst.Size -1
		Private rec As List = itemlst.Get(i)
		If rec.Get(3) = subcatidlst.Get(cbx2.SelectedIndex) Then
			Dim title As String = rec.Get(1)
			If File.Exists(File.DirAssets,rec.Get(0) & ".mp3") Then
				title = title  & " "
			End If
			Dim note As String = rec.Get(2)
			Dim p As B4XView = CreateItem(title, note, 400dip)
			clv1.Add(p, rec.Get(0))
			itemidlst.Add(rec.Get(0))
		End If
	Next
End Sub
In the CreateItem subroutine the layout of an item from the CustomListView is used to fill the title label (lbl1), the note panel (pnlnote) and the note label (lbl2).
For the note panel we use the CreateSizingItem subroutine. In this subroutine the height of the note is determined. We use the RTCSSingle layout file and the ResizingTextComponent CustomView class.
Sub CreateItem(Title As String,note As String, pnlHeight As Int) As B4XView
	Dim p As B4XView = xui.CreatePanel("")
	p.SetLayoutAnimated(0, 0, 0, clv1.AsView.Width, pnlHeight)
	p.LoadLayout("Item")
	p.SetLayoutAnimated(0, 0, 0, pnlitem.Width, pnlitem.Height + pnlnote.Height)
	lbl1.Text = Title
	lbl2.Text = note
	Private lblresize As B4XView = CreateSizingItem(pnlnote.width,note)
	lblresize.Color = Colors.ARGB(255,255,255,135)
	pnlnote.AddView(lblresize,0,0,pnlnote.Width,lblresize.height)
	pnlnote.height = lblresize.height
	p.Height = pnlitem.Height + pnlnote.Height
	Return p
End Sub
private Sub CreateSizingItem(wid As Int, txt As Object) As B4XView
	Private p As B4XView = xui.CreatePanel("")
	Activity.AddView(p,0,0,wid,300dip)
	p.LoadLayout("RTCSSingle")
	p.RemoveViewFromParent
	RTCS.SetPadding(20dip,10dip,20dip,10dip)
	RTCS.SetBackColor(Colors.ARGB(100,255,255,135))
	RTCS.SetCorners(10dip)
	RTCS.SetTextFont(xui.CreateFont(Typeface.LoadFromAssets("montserrat-medium.ttf"),24))
	RTCS.Text = txt
	p.Height = RTCS.GetHeight
	Return p
End Sub
The True Type Fonts for the RTCS View can be found in the zip-file from Andrew (see B4A app layouts - RTCSSingle layout).
Or you can use the zip-file download from the section Introduction - App description at the end of the page.


5. Play sound
If the user clicks on an item in the CustomListView and for the value of that item you have added a sound file to the Files Manager pane (<id from the item>. mp3) then that file will be loaded and played with the MediaPlayer.
Private Sub play_sound(id As Int)
	Log(id)
	If File.Exists(File.DirAssets,id & ".mp3") Then
		MediaPlayer1.Load(File.DirAssets, id & ".mp3")
		MediaPlayer1.Play
	End If
End Sub


6. Wrapping up
These are the events subroutines:
Private Sub cbx2_SelectedIndexChanged (Index As Int)
	fill_clv1
End Sub

Private Sub cbx1_SelectedIndexChanged (Index As Int)
	fill_cbx2
End Sub

Private Sub clv1_ItemClick (Index As Int, Value As Object)
	play_sound(Value)
End Sub