Cross platform code in Xojo
At the training day before our Xojo conference, we showed how to make a little REST web API with a Xojo web project and provide data to desktop, console, iOS and Android applications. And all use very similar and almost identical code.
There are little differences like iOS has tables with sections and cell data objects while android uses value and detail texts for the rows. But we were impressed on how much is so similar. Let us show you the similarities and differences.
Open database
Let's start with opening a database in a web project. For the sample, we use the example database coming with the EddiesElectronics project, but you can use whatever SQLite database you like or connect to a database server.
In the web project, we add code in the Opening event:
Show Table in Web
First we like to show the Products table in the Web project by running a SQL select statement to give us the rows. We loop over the rows and query the field values to add them to the listbox.
Don't forget the MoveToNextRow, because otherwise you get an endless loop.
Provide web API
In the web project, we add a HandleURL event to the app class to process API calls. Currently we only use the path "api/product" in the URL to go to the branch of the code to handle product requests. If you later add more calls, you may do a dictionary to lookup the function to call or similar.
Similar to the loop above, but in each iteration we create a new JSONItem, put the values in from the fields and then append that to an array JSONItem. Once we got the rows, we return the JSON array as a string back to the caller using the write method and pass status code 200 for success. Don't forget to return true to notice Xojo, that you handled the request.
Console App
Let us quickly make a console helper application to query the web service synchronously and show the data. The SendSync method sends the request wire the URL to the web API running in the web app on the same computer. We let the request take 60 seconds, so it should work even for a slow server on the other side of the globe. The result gets parsed as JSON and we can loop over the entries and show it:
Alternative you can do a loop with DoEvents to have events run and use the asynchronous event based method to get the call. That is better if you run multiple requests in parallel.
Desktop App
In the desktop application project we send the request in the opening event and it runs asynchronously in the background.
Later we get the content received event with the result. There we can again accept the content and parse it as JSON. We list the values into a DesktopListbox control.
As you may notice, we dropped an URLConnection on the window and just use it there. That is the easier mode in some cases. But in most cases you may use "new" keyword to make a new object at runtime. To catch the event you would connect with addHandler or subclass the URLConnection class.
iOS App
In the iOS project we use a iOSMobileTable on the screen. There in the Opening event we fire connection to query the data and the code looks exactly like the desktop application:
When we get the ContentReceived, we do similar to the desktop project. We accept the result and parse the JSON. But since the iOSMobileTable control has sections to group items, we add at least an empty section title. Once we have the section, we can again loop over JSON and add the values to the table. But we need to create a cell object with the text to show and the detail text.
The code above uses ToString with locale parameter. We cache this locale value in a local variable above the loop to make the loop a little bit faster.
Android App
The Android project does the same as the iOS project, but a bit different. Let's start with the Opening event and you can look for the difference:
Yes, it's the IP address. While iOS connects via localhost to the host Mac, on Android we are in a virtual machine and need to connect to the host computer over the local area network. My Mac got the 192.168.2.159 IP and thus I connect to the web app this way.
Once we get the ContentReceived event, we have similar code like in the iOS project, but without the section.
As you see we cache locale again. But to add something to the AndroidMobileTable, we just call AddRow and pass the main text and the detail text as parameters. Someday we hope Xojo Inc. brings us an unified MobileTable control to do perfect cross platform code.
What's next?
If you like to make this a real project, please don't forget to change a few things:
You will need some kind of authentication for the web API. Maybe just check authorization header and let the user of the web api pass a kind of token or let them pass username and password.
The web app may show a login screen and let the admin review current records. It is quite handy to have an admin interface to see how many clients are connected or what records have been recently created.
We skip a lot of error checking to keep the examples small. All the URLConnections report errors via Error event and we ignore them above in the example. Also we should check if the result contains actual JSON and is the answer we expect. We just handle it as an array of records.
The database connection should be per session for the web users and per call for the web API calls, so you have proper error state per connection.
Let us know if you have questions and feel free to join a future training session.