B4AServer

A very useful tool which can provide three services between an android device and a PC on the same network. I have tested with XP. You can:

1. Send files from Android device to PC
2. Receive files from PC to Android device
3. Start an application on the PC from the Android device

These actions can stand alone or be done one after another in any combination. A typical example: send an argument to the PC with a text file; initiate an application on the PC which uses the passed argument to extract data from a database; send the result back to the Android device as a text file.

B4AServer cannot be used to transfer large files (e.g. MP3 streaming) because the complete file is sent as a single “packet”

B4aserver consists of three components:

1. a client on the Android device which uses two boilerplate modules: B4AServer.bas and B4AServerService.bas

2. a board server on any LAMP server using b4a_server.php and a mySQL database

3. A java based server on the PC

The transfers are done between the PC and the Android device. The board server is an adjudicator and minimises firewall problems. For example: Andoid wants to send a file to PC. Android tells board server that it wants to send file. PC is polling the board server on a regular basis and reads that Andoid is trying to send. PC initiates the download directly from Android. Board server cancels the notification.

The files we need are kept in two zip files. Googling ‘b4aserver-device.zip’ will show the download for both it and b4aserver-desktop.zip. Unzip the device file and copy two files b4aServer.bas and b4aServerService.bas to a convenient location. These are the two modules which must be loaded into each applicable B4A program. Unzip the desktop zip file. I dumped the contents into a folder c:\b4aserver.

In this folder you will find the Java application b4aserver.jar which sets up the desktop server. b4aserver.jar is run from the batch file run.bat and you will need the Java runtime environment to run this application. If you open a terminal and enter ‘java’ (without parentheses) you should be able to see whether you have the Java runtime installed. If not, you need to download and install. You will be looking for something like jre-7u21-windows-i586.exe to download. Google ‘java download’ will get you close.

b4a_server.php is a blank php script which we will use when we set up our own board server. To get started, B4A has kindly provided access to the script residing on its website. They stress that this should be used for development only and that availability is not guaranteed. If you look in config.properties, you will see the line:
BoardUrl=http://b4aserver.basic4ppc.com/b4a_server.php
This defines the location of the board server on the B4A website.

#This is the unique server name you choose.
ServerName=test1
#Folder for files that can be downloaded to a device
InputFolder=files
#folder for uploaded files
OutputFolder=files
#number of devices that can connect at the same time
WorkerThreads=5
#link to the board server
BoardUrl=http://b4aserver.basic4ppc.com/b4a_server.php
#Interval measured in seconds. The desktop server polls the board server every x seconds.
CheckInterval=5
#list of shell commands
Shell.Print="c:\\program files\\PrintHTML\\printhtml.exe" printername="novapdf" header="" footer=""
Shell.Dir=cmd.exe /c dir files

While we have this file open, note the second line:
ServerName=test1
There is nothing important in the name test1. It merely gives the remote board server a name to attach to your desktop to avoid confusion with other desktops which may be accessing the same board server.

The line: ‘CheckInterval=5’ defines the frequency in seconds with which the desktop server will check on the board server. It cannot have a value of less than 1.

InputFolder and OutputFolder as set up define the subdirectory ‘files’ where the desktop server expects to find the files it needs to down- and up-load. In our case ‘c:\b4aserver\files’.

Open a terminal and navigate to the directory. Enter ‘run’ and the desktop server should start.

b4aserver

1. Send a file to Desktop Server.

Now we can turn our attention to the application for the Android device. Open Basic4Android and save your new project to its own directory (in this example I use a directory called ‘demo’). Project, Package name and change to b4a.b4aserverdemo. Change applicationname in the Project Attributes Region on the screen to ‘B4AServerDemo’. Incorporate the two modules we downloaded earlier. Project, Add existing Module and find both b4aServer.bas and b4aServerService.bas from where you saved them. They should appear in the module list on the right.

Under Sub Activity_Create add:

B4AServer.Initialize("http://b4aserver.basic4ppc.com/b4a_server.php", "test1", "Main")

“test1″ is the servername as defined in the properties file.

We will now programatically make a small text file called hello.txt containing a line of text and save it to File.DirDefaultExternal so add to the end of Activity_Create:
——————————————
File.WriteString(File.DirDefaultExternal,”hello.txt”,”Hello”)
——————————————
Follow this line with:
——————————————-
B4AServer.SendFile(File.DirDefaultExternal,”hello.txt”)
——————————————-
which sends the file from the source we have saved it.

To get all this to run we will need to add references to a few libraries. Click on the libraries tab on the right and check HTTP, Network and RandomAccessFile.

Save the file, run and install to the device. I use B4A-Bridge in preference to emulators. Making sure that the desktop server is still running, run the application. The application should show a blank screen (we have not defined any layout) with a blue header bar. If you look at the files subdirectory on the B4AServer dirctory on the PC (in my case c:\b4aserver\files) you should see that the file ‘hello.txt’ has been copied from Android to PC. You can now back-out of the application on Android.

That was easy. Now we are going to send the file right back to Android.

2. Receive a file from the Desktop Server

We will need a global variable so add to sub Globals:
——————————————-
dim demoTask as int
——————————————-
This will allow us to identify the incoming data file.

Add the following below the sendfile line:
——————————————-
demoTask = b4aserver.receivefile(“hello.txt”)
——————————————–
Save, run and install again. When we run the program on Android there is no simple indication of the file received. Use File Manager to go to the root directory of the SD card and you will see a numbered file (i.e. filename 2 or 3 or somesuch). Android won’t let you read this file because it cannot recognise the (non-existent) extension. Use the long-click and add the extension ‘.txt’ to make for example 3.txt. A short click will allow you to confirm that the file does indeed contain ‘hello’. Picking up the data from the returned file is not straightforward because a typical application will not know the task number which was returned.

We can get this information from the tasks result.id. Create a new sub as follows:

Sub TaskComplete(Result As TaskResult)
    If Result.Success Then
        If Result.Id = demoTask Then
            Msgbox("Task: " & Result.id,"")
        End If
    End If
End Sub

If a task has a successful result, we check that it is the task relating to the upload (Result.id = demoTask). To show what is going on, put up a Msgbox with the id value.

Now we are in a position to open the text file and read its contents. Replace the above TaskComplete sub with:

Sub TaskComplete(Result As TaskResult)
Dim reader1 As TextReader
Dim sLine As String

If Result.Success Then
   if result.id = demoTask Then
     reader1.Initialize(File.OpenInput(File.DirRootExternal,Result.id))
      sLine = reader1.ReadLine
      Msgbox("Content of returned file: " & sLine,"")
   End if
End If
End Sub

This loads the file of the task and puts the content in a message box.

Job done. In a transactional environment the returned files can build up in the SDCard root directory so it is best to delete them as soon as possible with something like:
—————————————-
File.Delete(File.DirRootExternal,Result.id)
—————————————-

3.Running an application on the Desktop Server

Now we can look at running an application on the desktop server. Open the supplied config.properties file and you will notice two shell commands listed at the end. We are going to add a third. Add the line:
————————————-
Shell.LoadNotepad=”notepad”
————————————-

Save the config.properties. We have to close the desktop server (Ctrl-C) and restart with run.bat to register the change.

Now add this line to the app as the last line of activity_create:

B4AServer.Shell("LoadNotepad", Null)

Save,run and the notepad application should start on the desktop server after closing the Msgbox.

4. Tidy up the tasks

Not important for this tutorial but in the real world you would have to allow for tidying up the board server after the application had been paused. The supplied B4AServerExample uses the following in activity_resume:

'Raise events for tasks that completed while our activity was paused
For i = 0 To B4AServer.TasksFinishedWhilePaused.Size - 1
   Dim Result As TaskResult
   Result = B4AServer.TasksFinishedWhilePaused.Get(i)
   TaskComplete(Result)
Next
B4AServer.TasksFinishedWhilePaused.Clear

5. Using your own domain as Board Server.

Finally we will look at using your own domain as the board server. I am using a commercial ISP domain and this can confuse the naming. Public ISPs will put some kind of prefix on your database and user names to distinguish from others that they administer. You will need to run phpMyAdmin or equivalent on your site. Create a database (I used the name b4aserver) and create a user and password. I used “b4a” and “password” for example. You do not have to create any tables as these are created by b4a_server.php as needed.

I wrote a small script as an aid to getting the correct parameters to access the database. Copy the following to a text processor and save it as testB4aServer.php

<html>
<head>
<title>MySQL Connection Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>

<?php
$dbh=mysqli_connect("localhost","id_b4a","password","id_b4aserver");
  if (!$dbh) {
    echo "Could not connect to the server";
  }else{
    echo "Successfully connected to the server";
  }
?>

</body>
</html>

The host will typically be “localhost” and the password will be as you entered. The database and user names will typically have a prefix related to your domain. I demonstrate this above with a prefix “id_”.

Change your parameters, save and copy the php file to your domain root (normally public_html). Use a browser to run the script with something like http://www.mydomain.co.uk/testB4aServer.php and you will be told whether a connection can be made or not. Repeat until you get the right answer.

When you are sure of the parameters, substitute them in the four definition lines at the top of b4a_server.php and copy this file to the same root directory of your ISP.

You can now change the BoardURL in config.properties on the desktop server to reflect the new address (e.g. http://www.mydomain.co.uk/b4a_server.php) and similarly change the B4AServer.Initialize line in your application to reflect the new site.

6. The complete application code

That’s it. The complete app should look like this:

#Region  Project Attributes 
	#ApplicationLabel: B4AServer Demo
	#VersionCode: 1
	#VersionName: 
	'SupportedOrientations possible values: unspecified, landscape or portrait.
	#SupportedOrientations: unspecified
	#CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes 
	#FullScreen: False
	#IncludeTitle: True
#End Region

Sub Process_Globals
End Sub

Sub Globals
	Dim demoTask As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
	B4AServer.Initialize("http://b4aserver.basic4ppc.com/b4a_server.php", "test1", "Main")
	File.WriteString(File.DirDefaultExternal,"hello.txt","Hello") 'create text file
	B4AServer.SendFile(File.DirDefaultExternal,"hello.txt") 'send text file
	demoTask = B4AServer.ReceiveFile("hello.txt") 'receive text File
	B4AServer.Shell("LoadNotepad", Null) 'run application on desktop server
End Sub

Sub Activity_Resume
	
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub TaskComplete(Result As TaskResult)
	Dim reader1 As TextReader
	Dim sLine As String
	
	If Result.Success Then
		If Result.id = demoTask Then
			reader1.Initialize(File.OpenInput(File.DirRootExternal,Result.Id))
			sLine = reader1.ReadLine
			Msgbox("Content of returned file: " &amp; sLine,"")
		End If 
	End If
End Sub
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: