You are on page 1of 115

Contents

1. B4A Cheatsheet ...................................................................................................... 4


Debug with a Toastmessage ............................................................................................. 4
Design resources and graphics ......................................................................................... 4
API Interfaces .................................................................................................................... 4
Dates................................................................................................................................. 4
Getting Date from Sql database......................................................................................... 4
Read text file from External SD Card. ................................................................................ 4
Write text to a text file to SD Card...................................................................................... 4
How to open a webpage with WebView. ............................................................................ 4
Using Begin/End transaction - along with TransactionSuccessful greatly improves "writing"
speed in SQL..................................................................................................................... 4
"The application ... has stopped unexpectedly. Please try again." ..................................... 4
Adding menu items ............................................................................................................ 4
Use #Region ... #End Region. ........................................................................................... 5
Panel arrays ...................................................................................................................... 5
Ctrl + Space = auto complete ............................................................................................ 5
Tool tip information ............................................................................................................ 5
LogCat - logs ..................................................................................................................... 5
Open a PDF ...................................................................................................................... 5
Open an Excel file ............................................................................................................. 5
Running the Emulator through a proxy via the Command prompt ...................................... 5
Send data to Android calendar .......................................................................................... 6
Create a Glow, Blur, DropShadow effect on text ................................................................ 6
Built in buttons and images................................................................................................ 6
Free database hosting ....................................................................................................... 6
Getting two lines in a listview ............................................................................................. 6
File Locations and working ................................................................................................ 6
Write / Read to files ........................................................................................................... 7
2. Project Download content using HTTP - dictionary ................................................. 8
HttpRequest ...................................................................................................................... 8
HttpResponse.................................................................................................................... 9
3. Project Metservice weather app ............................................................................ 10
Adding more cities to the weather app using Spinner. ..................................................... 13
4. Project The BikeFit calculator ................................................................................ 15
Create the Database ....................................................................................................... 15
SQL in the code............................................................................................................... 17
Create the layout ............................................................................................................. 18
Activity Create code......................................................................................................... 21
Load the Database code.................................................................................................. 22
Listview Click Event ......................................................................................................... 23
Delete and Update - Database commands ...................................................................... 24
Add New Record to the Database ................................................................................... 24
Code for calculate............................................................................................................ 25
The Modules tab .............................................................................................................. 26
Easily find repeated code ................................................................................................ 26
Basic For Android Monday, 11 June 2012 Page 1
The Results Activity ......................................................................................................... 27
The Results2 Activity ....................................................................................................... 28
The Results Layout using 2 panels .................................................................................. 29
The Help screen .............................................................................................................. 30
5. Project: Online Database Communication system................................................. 34
How to create an online Database ................................................................................... 34
Establish a connection string ........................................................................................... 36
Sending data to the database .......................................................................................... 37
Retrieving data from the database ................................................................................... 37
Uploading your PHP script............................................................................................... 39
Android Communication Program Basic setup ................................................................. 40
Android Communication Program Timestamp and Limit ............................................... 43
Using Timestamp ............................................................................................................ 43
Using Limit ...................................................................................................................... 44
Cutting out the unwanted text .......................................................................................... 44
Deleting data from your database. ................................................................................... 45
6. Project: GPS Program ........................................................................................... 49
Create the graphic Compass ........................................................................................... 49
Create the GPS ............................................................................................................... 50
GPS LocationChanged .................................................................................................... 52
Activity Pause and Resume code .................................................................................... 53
The Orientation_SensorChanged sub.............................................................................. 54
GPS on Google maps using Intents .............................................................................. 55
7. Project: GPS and the net SQL: Record your position online ................................. 56
Create a new database table ........................................................................................... 56
Create a new PHP script ................................................................................................. 57
Getting satellites .............................................................................................................. 59
Retrieving data from the database and displaying distance to saved GPS location ......... 60
8. Project: Getting an address from a Geolocation using XML .................................. 63
Geolocation ..................................................................................................................... 66
XML parser...................................................................................................................... 66
9. Getting an error in your hc_ResponseSuccess? Fix the taskID. ........................... 67
10. Project: Creating a Weather Widget ...................................................................... 68
The Service Module......................................................................................................... 69
Designing the Temperature Widget ................................................................................. 76
11. Project: Alarm scheduler sends email to contacts ................................................. 79
Date and Time ................................................................................................................. 80
Write to a file ................................................................................................................... 82
Read from a file to a list ................................................................................................... 82
Sending an SMS ............................................................................................................. 83
12. Project: Text to Speech Program........................................................................... 85
Text to speech stripped for other programs .................................................................. 87
13. Project: Capture all SMS messages entering your phone ..................................... 88
Logs and Toastmessageshow are crucial to debugging .................................................. 88
Working with Service and Activity Modules ...................................................................... 89
Basic For Android Monday, 11 June 2012 Page 2
Saving and Reading to files ............................................................................................. 89
The Activity (main) code .................................................................................................. 89
Code for the Service Activity(sms) ................................................................................... 94
The Activity(smstest) ....................................................................................................... 97
Designing the Widget ...................................................................................................... 98
14. Project: Voice Recognition program ...................................................................... 99
15. Project: Voice recognition in SMS messages program. ....................................... 101
Create a transparent layout a floating button .............................................................. 101
The Voice Recognition Activity Module .......................................................................... 103
16. Maps Hashmap for Java, Hashtables for .net ................................................... 107
17. Use Map to save multiple data to a single file ..................................................... 108
18. Project: Recipe selector using JSON................................................................... 109
JSON Overview ............................................................................................................. 109
Recipe Program construction ........................................................................................ 111
How to make a hyperlink that opens the web browser ................................................... 114

Basic For Android Monday, 11 June 2012 Page 3


1. B4A Cheatsheet
Debug with a Toastmessage Write text to a text file to SD Card.
Toastmessage is a timed popup useful to File saved to SDCARD/Android/data/ your
show you whats happening in your code. com file name

ToastMessageShow("message File.WriteString(File.DirDefaultExter
here",false) ' true=3sec , false=2 nal, "mytextfile.txt", "text to
sec write")

Design resources and graphics


How to open a webpage with WebView.
http://developer.android.com
1. add Webview to designer.
http://www.androidpatterns.com/ 2. add button to designer.
3. generate members.
http://jgilfelt.github.com/android-actionbar
Button1_Click
Nine patch images nine-patch-images-tutorial Dim UserURL As String
UserURL = "http://www.google.com.au/"
API Interfaces WebView1.LoadUrl(UserURL)
End Sub
http://www.programmableweb.com/
http://cloudmade.com/
Using Begin/End transaction - along with
Dates TransactionSuccessful greatly improves
Dates values are stored as the number of "writing" speed in SQL.
milliseconds since 1 January, 1970. This value My code went from 12 seconds to
is too large for an Int. It must be saved in a milliseconds in writing records.
Long variable. SQL1.BeginTransaction
Dim now As Long Try
now = DateTime.Now 'block of statements like:
For i = 1 to 1000
SQL1.ExecNonQuery("INSERT INTO table1
Getting Date from Sql database VALUES(...)
The date from my SQL database comes in as Next
yyyy/MM/dd SQL1.TransactionSuccessful
Catch
Here is a simple way to display in the required Log(LastException.Message) 'no
format. changes will be made
End Try
Dim TheDate As Long SQL1.EndTransaction
DateTime.DateFormat = "yyyy-MM-dd"
TheDate=
DateTime.DateParse(Cursor1.GetString( "The application ... has stopped
"Dob")) unexpectedly. Please try again."
DateTime.DateFormat = "dd/MM/yyyy" Some errors are not caught by Basic4android
Text= DateTime.Date(TheDate)
and then you see this message. To find the
Read text file from External SD Card. cause of the error you should check the
unfiltered logs in the Logs tab (right pane).
Folder SDCARD/Android/data/ your app
The filtered logs will usually not show any
name
message about this error.
Dim savedtext As String Adding menu items
savedtext =
File.ReadString(File.DirDefaultExtern
Adding menu items to activity is done by
al, "mytextfile.txt") calling Activity.AddMenuItem or
AddMenuItem2.

Basic For Android Monday, 11 June 2012 Page 4


Usually you will want to call it in Sub Log(whatever you want)
Activity_Create.
Open a PDF
Use #Region ... #End Region. Sub OpenPDF(FileName As String)
to create custom collapsible sections in your Dim i As Intent 'Requires a
code. Very handy for hiding a large blocks of reference to the Phone library
source code i.Initialize(i.ACTION_VIEW,
#Region My collection of functions FileName)
Sub SomeThing() i.SetType("application/pdf")
End Sub
i.WrapAsIntentChooser("Choose PDF
Sub Another() Viewer")
End Sub StartActivity(i)
#End Region End Sub

Panel arrays Open an Excel file


Dim panels(8) As Panel Sub OpenExcel(FileName As String)
Defines 8 Panels. Dim i As Intent 'Requires a
panels.Length = number of items, number of reference to the Phone library
Panels. i.Initialize(i.ACTION_VIEW,
FileName)
The Panel items go from i.SetType("application/vnd.ms-
panels(0), panels(1), panels(2), panels(3), excel")
panels(4), panels(5), panels(6), i.WrapAsIntentChooser("Choose
panels(7) 8 items with indexes from 0 to 7 so Excel Viewer")
panels.Length - 1 . StartActivity(i)
So End Sub
Dim panels(8) As Panel
For i = 0 To panels.Length 1 Running the Emulator through a proxy via
is correct and necessary the Command prompt
c:\Android\android-
Ctrl + Space = auto complete sdk\tools>emulator.exe -avd
Pressing Ctrl + Space activates the auto test -http-proxy
complete feature which will then show you a http://Username:PW@10.6.0.254
list with the available keywords, variables, :3128
modules, methods, subs, properties and fields. This c:\Android\android-sdk\tools> has to be
The list includes a description for most items. done first then attach the rest. Test = avd
Pressing Ctrl + Space after typing the first few name, IP address:port 10.6.0.254:3128
letters will usually select the required item
automatically.
Tool tip information
While writing methods parameters, a tool tip
will be opened with the method signature and
description.
The tool tip might hide some important code
that you now need.
LogCat - logs
The LogCat tab displays the device built-in
logs. These logs are very useful for debugging.
You can log messages with the Log keyword.
In order to start displaying the logs you press
on the Connect button.

Basic For Android Monday, 11 June 2012 Page 5


Send data to Android calendar Next
Sub ListView1_ItemClick(Position As
Sub Activity_Create(FirstTime As Int, Value As Object)
Boolean) Dim lvd As ListViewData
Dim Intent1 As Intent lvd = Value
Intent1.Initialize(Intent1.ACTION_ ...
MAIN,"com.androi d.calendar") End Sub
Intent1.SetComponent("com.android.
calendar/.LaunchActivity")
File Locations and working
StartActivity(Intent1)
End Sub There are several important locations where
you can read or write files.
Create a Glow, Blur, DropShadow effect on
text File.DirAssets
Dim Obj1 As Reflector The assets folder includes the files that were
Obj1.Target = Label1 added with the file manager. These files are
args(0) = 3 'Radius of the
Blur/GlowDropShadow read-only. You cannot create new files in
types(0) = "java.lang.float" this folder (which is actually located inside
args(1) = 3
types(1) = "java.lang.float"
the apk file).
args(2) = 3
types(2) = "java.lang.float" File.DirInternal / File.DirInternalCache
args(3) = Colors.ARGB(255,0,0,255) These two folders are stored in the main
' Color of th Glow/Blur
types(3) = "java.lang.int"
memory and are private to your application.
Obj1.RunMethod4("setShadowLayer", Other applications cannot access these
args, types) files.The cache folder may get deleted by the
Built in buttons and images OS if it needs more space.
Go to File.DirRootExternal
http://developer.android.com/reference/androi The storage card root folder.
d/R.drawable.html images
http://androiddrawables.com/ put the number File.DirDefaultExternal
in code below The default folder for your application in the
SD card. It will be created if required. The
Dim bd As BitmapDrawable folder is: <storage
bd = p.GetResourceDrawable(17301555) card>/Android/data/<package>/files/
Msgbox2("Message", "OK",
"","",bd.Bitmap)
File.WriteString - Writes the given text to a
Free database hosting new file.
http://www.000webhost.com/ File.ReadString - Reads a file and returns it
content as a string.
Getting two lines in a listview File.WriteList - Writes all values stored in a
Sub Globals list to a file. All values are converted to string
Type ListViewData (FirstRow As type if required. Each value will be stored in
String, SecondRow As String)
End Sub its own line. Note that if a value contains the
new line character it will saved over more than
For i = 0 to 100
Dim lvd As ListViewData one line and when you read it, it will be read
lvd.Initialize as multiple items.
lvd.FirstRow = "abc" File.ReadList - Reads a file and stores each
lvd.SecondRow= "def"
ListView1.AddTwoLines2(lvd.FirstRow, line as an item in a list.
lvd.SecondRow, lvd) File.WriteMap - Takes a map object which

Basic For Android Monday, 11 June 2012 Page 6


holds pairs of key and value elements and File.WriteString(File.DirInte
stores it in a text file. The file format is not too rnalCache,
"nettalk.txt",result)
important unless the file is supposed to be
'get it back from the file
edited manually. This format makes it easy to
reader.Initialize(File.OpenIn
edit it manually. One common usage of put(File.DirInternalCache,
File.WriteMap is to save a map of "settings" to "nettalk.txt"))
a file. Dim name As String
File.ReadMap - Reads a properties file and name = reader.ReadLine
returns its key/value pairs as a Map object.
Note that the order of entries returned might be
different than the original order.

Write / Read to files


'write it to a file

Basic For Android Monday, 11 June 2012 Page 7


2. Project Download content using HTTP - dictionary
The basic steps in getting content from the net to your phone are quite simple.

In this project we are going to access the online dictionary at


http://dictionary.reference.com/ enter a term and get the results.

First add the Http library. Here is the basic documentation on it


http://www.basic4ppc.com/android/help/http.html

Create a layout with an Edittext box named WordBox and a button named SearchButton.

HttpRequest
Holds the target URL and other data sent to the web server. The initial time out is to 30000
milliseconds (30 seconds).

Sub Process_Globals
Dim hc As HttpClient
Dim req As HttpRequest
End Sub

Sub Globals
'define the views on the layout, a text box and a button
Dim WordBox As EditText
Dim SearchButton As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)


'load the layout
Activity.LoadLayout("Main")
hc.Initialize("hc")
End Sub

'#### Controls ####


Sub SearchButton_Click
req.InitializeGet("http://dictionary.reference.com/browse/" &
WordBox.Text)
hc.Execute(req, 1)
End Sub

Basic For Android Monday, 11 June 2012 Page 8


HttpResponse
An object that holds the response returned from the server. The object is passed in the
ResponseSuccess event. You can choose to read the response synchronously or
asynchronously. It is important to release this object when it is not used anymore by calling
Release.

'#### Routines ####


Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int)
Dim SearchWord As String
SearchWord = Response.GetString("UTF8") 'Get the whole page

'The line below finds <div class="pbk"><span class="pg">


SearchWord = SearchWord.Replace(QUOTE, "'") 'Replace double quotes with
single quotes for easy handling.
SearchWord = SearchWord.SubString(SearchWord.IndexOf("<div
class='pbk'><span class='pg'>") + 34) 'Add 34 so we grab the definition
after the tag (there are 34 characters in the above string when you count
to the right) You can add 34 to the 0 substring start below instead
SearchWord = SearchWord.SubString2(0, SearchWord.IndexOf("</span>")) 'Grab
only the definition enclosed
Msgbox(WordBox.Text & " is a " & SearchWord, "") 'Voila!!
End Sub

Sub hc_ResponseError(Response As HttpResponse, Reason As String,


StatusCode As Int, TaskId As Int)
If Response <> Null Then
Msgbox("Error: " & Response.GetString("UTF8"), "Connection Error")
Response.Release
End If
End Sub

Basic For Android Monday, 11 June 2012 Page 9


3. Project Metservice weather app
Similar to the above exercise this exercise downloads the current temperature from the
metservice and extracts the temp from it.

The heart of it is cutting out the temperature from the code.

Improve this code by:

1. Allowing people to change the city to another one.


2. We will make it into a widget so it stays on the front of the phone
later.

Sub Process_Globals
Dim hc As HttpClient 'download the page
Dim hcimage As HttpClient 'download the image
Dim req As HttpRequest
Dim reqimage As HttpRequest
End Sub

Sub Globals
Dim temp As String
Dim btnweather As Button
Dim edtweather As EditText
Dim lbltemperature As Label
Dim img As Bitmap
Set a default start city when there is nothing in the DB
Dim selectedcity As String :selectedcity ="Christchurch"
Dim townpath As String
Dim label1 As Label holds the temp
Dim imgtemp As ImageView
Dim pic As String 'holds the image
End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("main")
hc.Initialize("hc")
hcimage.Initialize("hcimage")
End Sub

Sub btnweather_click
strplace = "christchurch" 'note its lower case
townpath = "http://m.metservice.com/towns/"& strplace
'Log(townpath)
req.InitializeGet(townpath)

Basic For Android Monday, 11 June 2012 Page 10


hc.Execute(req, 1)
End Sub

Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int)


Dim temp As String
temp = Response.GetString("UTF8") 'Get the whole page

'Cut beginning and end to get the code for the temp itself
temp = temp.SubString(temp.IndexOf("<div class=" & QUOTE & "summary" &
QUOTE & ">")) 'cut to first occurance off
temp = temp.SubString2(21, temp.IndexOf("</ul></div></div>")) ' find last
occurance

temp = temp.Replace(QUOTE,"'") ' replace double with single quotes


edtweather.Text = temp 'show the downloaded code so you can work on it.

Dim temperature As String 'pull the temperature from the code


temperature = temp
temperature = temperature.SubString(temperature.IndexOf("ul'><h2>"))
temperature = temperature.SubString2(8, temperature.IndexOf("<span "))
lbltemperature.Text = temperature

pic = temp 'pull the pic from the code


pic = pic.SubString(pic.IndexOf("wx-icons/")) 'start position
pic = pic.SubString2(9, pic.IndexOf("' width")) ' 6 is the number from
counting the letters above
pic = pic.Trim

'looking for the image, is it already in the cache?


If File.Exists(File.DirInternalCache, pic) Then
'if so then load it
imgtemp.Bitmap = LoadBitmap(File.DirInternalCache, pic)
Log("image in cache")
Else 'otherwise go and get it from the net
Getimage run the get image sub
End If

Dim strtime As String 'pull the time from the code


strtime = temp
Dim timecolon As String
timecolon = strtime.IndexOf(":") 'find the colon between the time eg
11:23am
strtime = strtime.SubString2(timecolon -2, timecolon +5) 'take 2 off the
colon and add 5 on to get the whole time 11:23am
label1.Text = strtime
End Sub

Basic For Android Monday, 11 June 2012 Page 11


Sub getimage 'this gets the image from the net
Dim imagepath As String
imagepath = "http://m.metservice.com/sites/all/themes/mobile/images/wx-
icons/"& pic
reqimage.InitializeGet(imagepath)
hcimage.Execute(reqimage, 1)
End Sub

Sub hcimage_ResponseSuccess(Response As HttpResponse, TaskId As Int)


If you successfully get the image then run this code its sitting in the
cache so get it out
Response.GetAsynchronously("ImageResponse", _
File.OpenOutput(File.DirInternalCache, pic, False), True, TaskId)
End Sub
when the image has stopped downloading (useful for big images)
Sub ImageResponse_StreamFinish (Success As Boolean, TaskId As Int)
If Success = False Then
Msgbox(LastException.Message, "Error")
Return
End If
load it into the image bitmap
imgtemp.Bitmap = LoadBitmap(File.DirInternalCache, pic)
End Sub

typical error reporting when the image was unable to be downloaded


Sub hcimage_ResponseError(Response As HttpResponse, Reason As String,
StatusCode As Int, TaskId As Int)
If Response <> Null Then
Msgbox("Error: " & Response.GetString("UTF8")& "Cannot find ",
"Connection Error")
Response.Release
ProgressDialogHide
ToastMessageShow("Image not loading",True)
End If
End Sub

typical error reporting when the temp was unable to be downloaded


Sub hc_ResponseError(Response As HttpResponse, Reason As String,
StatusCode As Int, TaskId As Int)
If Response <> Null Then
Msgbox("Error: " & Response.GetString("UTF8")& "Cannot find ",
"Connection Error")
Response.Release
ProgressDialogHide
ToastMessageShow("bugger",True)

Basic For Android Monday, 11 June 2012 Page 12


End If
End Sub

Adding more cities to the weather app using Spinner.


Create a Spinner, Dim SPcity As Spinner and a variable to hold the city Dim
selectedcity As String in Globals.

Create a sub to add the cities to the spinner

Sub addCity
'add more cities
SPcity.Add("Christchurch")
SPcity.Add("Auckland")
SPcity.Add("Wellington")
SPcity.Add("Dunedin")
SPcity.Add("Hamilton")
End Sub

At the end of Sub Activity_Create add the following code to load the spinner with the
cities Give it a default value SPcity.SelectedIndex = 1 so it loads a city at startup. AddCity
will load the cities above to the spinner.

addCity
SPcity.SelectedIndex = 1
Activity.Title="Mothership for weather app for " & selectedcity
This is the click event on the spinner, passing the value of what you clicked on to the
selectedcity variable. It also turns on a button to save the city to a text file.

Sub SPcity_ItemClick (Position As Int, Value As Object)


'pass the value you have selected to the variable
selectedcity = Value
btnsavecity.Enabled = True
End Sub

Change the Sub btnweather_click button click event so that it loads the spinner value. Note
that it has to be lower case for the url to work.

strplace = selectedcity.ToLowerCase 'note its lower case


townpath = "http://m.metservice.com/towns/"& strplace

If you want to save it so that it will open at that city later, and when you create a widget then
you need to save it to a text file. That is really easy.

Sub btnsavecity_click

Basic For Android Monday, 11 June 2012 Page 13


'save the city you has selected to a text file
File.WriteString(File.DirInternal, "WeatherCity.txt",selectedcity)
End Sub

Change the btnweather_click code to open the file that has been saved.

The first time you run it there is no file to draw from. So If File.Exists checks that the file is
there. If not it just uses the value that was given in the Dim selectedcity As String
:selectedcity ="Christchurch"

Sub btnweather_click
If File.Exists(File.DirInternal, "WeatherCity.txt") Then
selectedcity = File.ReadString(File.DirInternal, "WeatherCity.txt")
End If
strplace = selectedcity 'note its lower case
townpath = "http://m.metservice.com/towns/"& strplace
'Log(townpath)
req.InitializeGet(townpath)
hc.Execute(req, 1)
End Sub

Basic For Android Monday, 11 June 2012 Page 14


4. Project The BikeFit calculator

Create the Database


Go to Firefox/Tools/ Addons. Add in the SQLite manager

After you have installed SQLite manager in to Firefox open a new database and call it
Bikefit.

Create a new table using right click Create table from the Tables(0)

Click on ADD

Add the following fields. Also call the table bikefit (or any name you want).

Read about SQLlite datatypes here http://www.sqlite.org/datatype3.html

Basic For Android Monday, 11 June 2012 Page 15


Save the file to the Files folder of your program, or move it there later.

Create some data to use as an example

Close out from your program and rename the file itself from bikefit.sqlite to bikefit.sql. (I
dont know why, considering that Android uses sqlite files and not sql, but it must be a bug
somewhere in the SQL Library ), and make sure its saved in your files folder.

Basic For Android Monday, 11 June 2012 Page 16


SQL in the code
We are going to use the SQL library so need to load it in. There are two
types in this library.

An SQL object gives you access to the database. The Cursor object
allows you to process queries results.

Usually you will want to declare the SQL object as a process global
object. This way it will be kept alive when the activity is recreated. SQLite
stores the database in a single file. When we initialize the SQL object we
pass the path to a database file (which can be created if needed).

First we define our database variables.

Sub Process_Globals
Dim SQL1 As SQL
Dim cursor1 As Cursor

Now we need to start coding for it. In the Activity Sub, which runs when the program first
begins, we need to copy the database from the Assets folder to the Internals folder as files
cant be written to in the Assets folder.

Files distributed as part of an app cannot be written to in the default location. To move the
file(s) to a storage area which allows writing to the file, add the file to the app in
Activity_Create add the following code:

Sub Activity_Create(FirstTime As Boolean)


If File.Exists(File.DirInternal,"bikefit.sql") = False Then
File.Copy(File.DirAssets,"bikefit.sql",File.DirInternal,"bikefit.sql")
End If

If SQL1.IsInitialized = False Then


SQL1.Initialize(File.DirInternal, "bikefit.sql", False)
End If

Basic For Android Monday, 11 June 2012 Page 17


Create the layout
There are a number of ways to create your layout. The most obvious is to make a panel
and attach the objects to it.

Create the panel pnlbg first, The other objects will be stuck to the panel and can be
manipulated with the panel later. At this stage size is not an issue as it can be set
programmatically.

Labels just holding text dont need to be explicitly named as they wont be in the code.

Open the Designer and the Abstract Designer and click on the Status to connect it to the
emulator

Then you can see the design in the emulator and adjust it from there as well as using the
Abstract designer to find the names of the Views. If you are lucky enough to have your
phone plugged in you can see the layout on the phone and move it around by hand as well.

Basic For Android Monday, 11 June 2012 Page 18


In the Designer you can see the Views and their properties. Firstly set the pnlbg panel with
the values in the properties. Each of the Views you add to your layout then attaches to this
panel.

Basic For Android Monday, 11 June 2012 Page 19


Once you have made your layout you need to generate the
members. This mostly a shortcut way to declare the variables
that you are going to use.

Go Tools, in the Designer window and then click Generate


Members

This will create the Dims in Sub Globals

Sub Globals
'These global variables will be redeclared each time the activity is
created.
'These variables can only be accessed from this module.
Dim edtarm As EditText
Dim edtseam As EditText
Dim edtshoulder As EditText
Dim edtsternum As EditText ' height

Dim panelbg As Panel


Dim btncalculate As Button 'run
Dim btndelete As Button 'delete
Dim btnsave As Button ' change
Dim btnnew As Button 'save new

Dim bmp As Bitmap you need to add this for later

Dim btnarm As Button


Dim btnseam As Button
Dim btnshoulder As Button
Dim btnsternum As Button

Dim LVdb As ListView

Basic For Android Monday, 11 June 2012 Page 20


Activity Create code
After you have created your layout it needs to be added to the Sub
Activity_Create(FirstTime As Boolean) so that its loaded when the program runs.
You can replace Main with the name of whatever your layout is.

Activity.LoadLayout("Main")

We can also add the rest of the code that needs to run when the program is first created.

At the beginning of an object's life, the Java virtual machine (JVM) allocates enough
memory on the heap to accommodate the object's instance variables. When that memory is
first allocated, however, the data it contains is unpredictable.

If the memory were used as is, the behaviour of the object would also be unpredictable. To
guard against such a scenario, Java makes certain that memory is initialized, at least
to predictable default values, before it is used by any code.

Initialization is important because, historically, uninitialized data has been a common source
of bugs. The Java language, has built-in mechanisms that help you ensure proper
initialization of the memory occupied by a newly-created object. With proper use of these
mechanisms, you can prevent an object of your design from ever being created with an
invalid initial state.

Earlier we defined a bitmap image (Dim bmp As Bitmap). And now we have to initialise it
bmp.Initialize(File.DirAssets, "android48.png")

For our Edittext boxes we can specify what type of keyboard will be used. In this case we
only want numbers to be added to the boxes.

edtarm.InputType = edtarm.INPUT_TYPE_NUMBERS
Finally we want a title to appear at the top of the layout.

Activity.Title="Bike Fit: Sizing calculator"

All the code added to Activity_Create.

bmp.Initialize(File.DirAssets, "android48.png")

'uses only the numeric keyboard


edtarm.InputType = edtarm.INPUT_TYPE_NUMBERS
edtseam.InputType = edtseam.INPUT_TYPE_NUMBERS
edtshoulder.InputType = edtshoulder.INPUT_TYPE_NUMBERS
edtsternum.InputType = edtsternum.INPUT_TYPE_NUMBERS

Activity.Title="Bike Fit: Sizing calculator"

Basic For Android Monday, 11 June 2012 Page 21


Load the Database code
Now that we have the Views loaded into the layout we can start to write the code that loads
the database into the Listview. The ListView control is a very powerful control. It allows you
to show short or long lists in a very "sleek" way. Read more about it here.

First we get the data from the database and pass it to Cursor1 which we defined earlier.
Cursor is just the name of the object that holds the data from the database, it might also be
thought of as a datatable.

Pass the data to cursor1

cursor1 = SQL1.ExecQuery("SELECT * FROM bikefit")


Then we make a For next loop, starting at 0 and ending with the rowcount 1 (because we
started at 0 instead of 1)

For i = 0 To cursor1.RowCount 1
Then we just get the data we want and pass it as a long line of data, to the
Listview.AddSingleLine

LVdb.AddSingleLine(cursor1.GetString("ID")& " : "


&cursor1.GetString("Name")& " " & cursor1.GetLong("Sternum")& " " &
cursor1.GetLong("Inseam")& " " & cursor1.GetLong("Arm")& " " &
cursor1.GetLong("Shoulder"))
We then set the details for that line and finish with the next

LVdb.SingleLineLayout.ItemHeight = 40 etc
All code.

Sub DBload
LVdb.Clear'need to clear the list
cursor1 = SQL1.ExecQuery("SELECT * FROM bikefit")
For i = 0 To cursor1.RowCount - 1
cursor1.Position = i

LVdb.AddSingleLine(cursor1.GetString("ID")& " : "


&cursor1.GetString("Name")& " " & cursor1.GetLong("Sternum")& " " &
cursor1.GetLong("Inseam")& " " & cursor1.GetLong("Arm")& " " &
cursor1.GetLong("Shoulder"))
LVdb.SingleLineLayout.ItemHeight = 40
LVdb.SingleLineLayout.Label.TextSize = 20
LVdb.SingleLineLayout.label.TextColor = Colors.Black
LVdb.SingleLineLayout.label.Color = Colors.White
Next
End Sub
Finally add DBload to the VERY END of Sub Activity_Create So that it runs at
startup.

Basic For Android Monday, 11 June 2012 Page 22


Listview Click Event
When we click on an item in the listview we want those numbers to be passed to the edittext
boxes in the layout. This is a Short Click event, there is also a Long Click event

Value is the data of the line that is being clicked. Value As Object It is passed to the idvalue.

idvalue = Value

We want to get the place of the first : and pass that number to countit. Then using Substring
we get the ID number by starting at 0 and going to the countit number.

countIt = idvalue.IndexOf(":") 'find location of separator


idvalue = idvalue.SubString2(0,countIt) 'find first part of label text

Now we have the ID of the row we can put it back into the database to pull out the values
again and pass them to the edittext boxes. We also could carry on using the code above to
find the next : and then getting the number from there as well.

Sub lvdb_ItemClick (Position As Int, Value As Object)' click on the entry


in the list

Dim idvalue As String


idvalue = Value
countIt = idvalue.IndexOf(":") 'find location of sperator
idvalue = idvalue.SubString2(0,countIt) 'find first part of label text
ID = idvalue
cursor1 = SQL1.ExecQuery("SELECT * FROM bikefit where ID = '" & ID & "' ")
For i = 0 To cursor1.RowCount - 1
cursor1.Position = i
edtarm.text=cursor1.getString("Arm")
edtseam.text=cursor1.getString("Inseam")
edtshoulder.text=cursor1.getString("Shoulder")
edtsternum.text=cursor1.getString("Sternum")
Next
End Sub

Basic For Android Monday, 11 June 2012 Page 23


Delete and Update - Database commands
Clicking on the listview row selected the ID for that row, as seen above, then when you have
that number you can easily delete the row or save it back to the database if you changed it.

Sub btndelete_click
SQL1.ExecNonQuery("DELETE FROM bikefit where ID = '" &ID & "' ")
DBload
End Sub

Saving the row by taking the text from the edittext boxes.

Sub btnsave_click
SQL1.ExecNonQuery("UPDATE bikefit set Sternum ='"& edtsternum.text &"',
Inseam ='"& edtseam.text &"', Arm ='"& edtarm.text &"' , Shoulder = '"&
edtshoulder.text &"' WHERE ID = " & ID)
DBload
End Sub

Add New Record to the Database


Adding a new record uses the Dialogs library to enter the name. This
means someone else did all the hard work for you.

This library contains several modal, that is blocking, dialogs by which the user can enter
data. Presently they are an InputDialog for text, a TimeDialog for times, a DateDialog for
dates, both a ColorDialog and a ColorPickerDialog for colors, a NumberDialog for
numbers,a FileDialog for folders and file names and a CustomDialog.

Sub btnnew_click ' save new


Dim dialog As InputDialog
dialog.Input = ""
dialog.HintColor = Colors.ARGB(196, 255, 140, 0)
Dim ret As Int
ret = DialogResponse.CANCEL
ret = dialog.Show("Enter Your name", "Bike Fit", "Save", "Exit", "", bmp)

Dim strname As String ' name of person


strname = dialog.Input

If strname = "" OR edtarm.text = "" OR edtseam.text = "" OR


edtshoulder.text = "" OR edtsternum.text ="" Then
Msgbox("You have to enter all fields","Missed data field")
Else

'Grab the last ID number which is the highest number


cursor1 = SQL1.ExecQuery("SELECT ID FROM bikefit ")
If cursor1.RowCount > 0 Then
For i = 0 To cursor1.RowCount - 1
Basic For Android Monday, 11 June 2012 Page 24
cursor1.Position = i
Dim NewID As Int
NewID = cursor1.GetInt("ID")
Next
End If

NewID = NewID +1 ' add 1 to the ID number to make a new ID field


SQL1.ExecNonQuery("INSERT INTO bikefit VALUES('" & NewID & "','" & strname
& "','" & edtsternum.text & "','" & edtseam.text & "','"& edtarm.text
&"', '" & edtshoulder.text & "')")

DBload
End If
End Sub

Code for calculate


Under the Sub Process_Globals define the following variables. They are defined here
because they will be used in other activities, Results, and Results2

Dim helpselect As Int


Dim lngsternum As Long
Dim lnginseam As Long
Dim lngarm As Long
Dim lngshoulder As Long
Dim ID As Int ' ID of each entry

The click event for the Run Button. Pass the data from the text boxes to the variables.

This loads the next activity called results that we make next.

StartActivity("results")

Sub btncalculate_click
lngsternum = edtsternum.Text
lnginseam = edtseam.Text
lngarm = edtarm.Text
lngshoulder = edtshoulder.Text

StartActivity("results")
End Sub

Basic For Android Monday, 11 June 2012 Page 25


The Modules tab
The modules tab on the right is really handy to use. The top section
shows you the activities in your project, while the bottom shows each
sub in your activity.. Just click on the Sub to go to that part of the code.

Easily find repeated code


If you are looking for all the places where a piece of your code, be it a
variable or view etc is repeated in your activity just double click on it to
select it. Then down the right you will see light blue lines. Scroll down to
the lines with the scrollbar and each duplicate entry will show up. Its a
really good tool.

Basic For Android Monday, 11 June 2012 Page 26


The Results Activity
In order to show the results of the bikefit, the 4
fields from the Main layout page, we will create 2
Activities to hold the code. This might be overkill, I imagine we could have the code for the
results all on one activity, but this is to show how you can share a layout between Activities.

So we will have two activities, Results and Results2, they will both

Create a new activity and call it results

There are no process Globals as all the results are kept in this activity. You might want to
create the layout first and then generate these views using the generate tool.

Sub Globals
Dim lblhandlebar As Label
Dim Lblreach As Label
Dim btnback As Button
Dim btnnext As Button
Dim pnlHelp As Panel
Dim pnlhelp2 As Panel
End Sub

The Result and Results2 Activities uses one layout named results which has two panels
on it. pnlHelp and pnlHelp2. PnlHelp.Visible is set to True to show it for the results activity
while the second panel is set to .visible = False to hide it.

In the next Activity Results2, the panel visibility is reversed.

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("results")
pnlHelp.Visible = True
pnlhelp2.Visible = False
pnlHelp.Top=0
pnlHelp.Left=0
pnlHelp.Height=Activity.Height
pnlHelp.Width=Activity.Width
Activity.Title="Bike Fit: Handlebar and Reach"
result
End Sub

The sub that calculates the results and passes it to the label

Sub result
lblhandlebar.text = (Main.lngshoulder * 0.875)&"cm" 'handlebar
Lblreach.text = ((((Main.lngsternum - Main.lnginseam) + Main.lngarm) / 2)
+ 4) &"cm"
End Sub

Basic For Android Monday, 11 June 2012 Page 27


Sub btnnext_click
StartActivity("results2")
End Sub

Sub btnback_click
Activity.Finish
End Sub

The Results2 Activity


Sub Globals
Dim lblframe As Label
Dim lblsaddle As Label
Dim pnlHelp As Panel
Dim pnlhelp2 As Panel
Dim btnback2 As Button
Dim btnnext2 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("results")

pnlHelp.Visible = False
pnlhelp2.Visible = True
pnlhelp2.Top=0
pnlhelp2.Left=0
pnlhelp2.Height=Activity.Height
pnlhelp2.Width=Activity.Width

Activity.Title="Bike Fit: Frame and Saddle"


result
End Sub

Sub result
lblframe.text = (Main.lnginseam * 0.67)&"cm" 'frame
lblsaddle.text = (Main.lnginseam * 0.883)&"cm" 'saddle
End Sub

Sub btnnext2_click
StartActivity("results")
Basic For Android Monday, 11 June 2012 Page 28
btnback2_click
End Sub

Sub btnback2_click
Activity.Finish
End Sub

The Results Layout using 2 panels


This layout uses two panels, and the Views for each Activity are stuck on their panel. Then
the panels are either made visible or invisible.

Here are the Views to be added to each panel. This is taken directly from the Sub Globals
Create the panel first then make sure you stick the views on them.

Results Activity Results2 Activity


Dim pnlHelp As Panel Dim pnlhelp2 As Panel
Dim lblhandlebar As Label Dim lblframe As Label
Dim Lblreach As Label Dim lblsaddle As Label
Dim btnback As Button Dim btnback2 As Button
Dim btnnext As Button Dim btnnext2 As Button

Basic For Android Monday, 11 June 2012 Page 29


The Help screen
One layout with changing data depending on the case statement in the Activity.

In the Main Activity need to make a variable to hold the help number that will be accessed
later from the Help Activity. Therefore it needs to be declared in the Process Globals sub of
the Main Activity.

Sub Process_Globals
Dim helpselect As Int
In the Main activity add the code to activate each of the help buttons. We could use the
Sender property to get the value of the helpselect, which is smaller, however its nice to be
lazy sometimes.

Sub btnarm_click
helpselect = 1
StartActivity("help")
End Sub
Sub btnseam_click
helpselect = 3
StartActivity("help")
End Sub
Sub btnshoulder_click
helpselect = 4

Basic For Android Monday, 11 June 2012 Page 30


StartActivity("help")
End Sub
Sub btnsternum_click
helpselect = 5
StartActivity("help")
End Sub

Create a new Activity and call it Help.

In the designer create a new layout called Help and layout the fields something like this.

Generate your Views into the Help Activity you made earlier, it should look something like
below. Its pretty obvious.

Sub Globals
Dim imgbox As ImageView
Dim lblhelp As Label
Dim lbltitle As Label
Dim panel1 As Panel
Dim btnclose As Button
Dim imgarm As Bitmap
Dim imgheight As Bitmap
Dim imgsternum As Bitmap
Dim imgshoulder As Bitmap
Dim imginseam As Bitmap
Dim lblcalc As Label
End Sub

Basic For Android Monday, 11 June 2012 Page 31


In Sub Activity_Create we need to create the select statement that will load which of the 4
help information clicked on by the button.

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("help")

Select Main.helpselect

Case 1 'arm
lbltitle.Text ="Measure your arm length"
lblhelp.text = "Measure from your shoulder to your knuckles. "
imgarm.Initialize(File.DirAssets,"arm.jpg")
imgbox.Bitmap = imgarm
lblcalc.Text ="This helps give your reach. (((sternum - inseam) + arm) /
2) + 4)"
Activity.Title="Bike Fit: Arm measuring"

Case 2 'height
lbltitle.Text ="Measure your height"
lblhelp.text = "In your socks or bare feet, stand with your heels and
buttocks against the wall Measure from the ground to the top of your head"
imgheight.Initialize(File.DirAssets,"height.jpg")
imgbox.Bitmap = imgheight
lblcalc.Text ="???"

Case 3 'seam
lbltitle.Text ="Measure your inner leg"
lblhelp.text = "Wear your cycling shorts, and take the measurements in
bare feet. Place a book OR other solid Object up against the top of your
inner leg pelvic bone AND measure from the top of that To the Floor."
imginseam.Initialize(File.DirAssets,"inseam.jpg")
imgbox.Bitmap = imginseam
lblcalc.Text ="Frame size = inseam * 0.67, Saddle height = inseam *
0.883"
Activity.Title="Bike Fit: Inseam measuring"

Case 4 'shoulder
lbltitle.Text ="Measure your shoulder width"
lblhelp.text = "Measure your shoulder width by the outside of the bony
protrusions at the top of your shoulders"
imgshoulder.Initialize(File.DirAssets,"shoulder.jpg")
imgbox.Bitmap = imgshoulder
lblcalc.Text ="Handle Bar width = shoulder * 0.875"
Activity.Title="Bike Fit: Shoulder measuring"

Case 5 'sternum
lbltitle.Text ="Measure from your sternum to the floor"

Basic For Android Monday, 11 June 2012 Page 32


lblhelp.text = "In your socks or bare feet, stand with your heels and
buttocks against the wall. Measure from the ground to the sternum notch
at the top of your ribcage / bottom of your neck."
imgsternum.Initialize(File.DirAssets,"sternum.jpg")
imgbox.Bitmap = imgsternum
lblcalc.Text ="Used to calcualte Reach and Frame height, Saddle height"
Activity.Title="Bike Fit: Sternum measuring"
End Select
End Sub

Sub btnclose_click
'StartActivity("Main")
Activity.Finish
End Sub

Basic For Android Monday, 11 June 2012 Page 33


5. Project: Online Database Communication system
This program connects to an internet server and allows the user to send and receive data,
particularly text in this case. This requires 3 parts, the Android program, a PHP interface,
and a web based database in SQL.

Android PHP script Database

First thing we need is a web based database to hold our data.

How to create an online Database


The steps below are not specific just to this website, but to any webhost using the Cpanel,
MySql and PHPAdmin programs which is a very high proportion of them.

1. Go here and create an account and WRITE YOUR DETAILS DOWN


2. Once you are logged in go to your
account and click on Go to CPanel

3. Scroll down to MySQL and click on it

4. Create a new Database using your names and pws


5. Keep a record of the details you get, you
will need them soon.

$mysql_host = "mysql8.000webhost.com";
$mysql_database = "a5858161_test";
$mysql_user = "a5858161_gary";
$mysql_password = "PW";

6. Go back to CPanel and click on PHP


MyAdmin

7. Click to enter your database

Basic For Android Monday, 11 June 2012 Page 34


8. Create a new table for your database. It
doesnt matter how many fields, you can
add them easily when needed later (as we
will)

9. Create the following fields

10. Once created click on Insert


11. Add some sample data to your database to have something to work with

Under Browse you can see the added data

12. Go back to Insert and add some more rows set

Insert another new row so that you stay in the same window

You should now have a simple database with some data

Creating a PHP script to provide access to your database.


Basic For Android Monday, 11 June 2012 Page 35
Android cannot directly access the internet based database so needs to go through a script.
This can be written in a number of languages such as PHP or ASP, we will use PHP as its
easy and very popular.

PHP can be written in many programming systems, even as simple as notepad. I use
Komodo Edit from http://www.activestate.com/komodo-edit however you might have another
program.

There are two ways to create your PHP page, one is to act to let Android pass directly
through and do whatever it wants to the database. This leaves the database open to
hacking and attacks, as any device can access the PHP script when you know the path so
its not a secure option.

The other way is to put your SQL code in the PHP page in functions and control what the
program does by controlling the function allowed to run. So you can stop people deleting
data by not having a delete function in the PHP code, or restricting it.

This is by far the best option. This is the code below, its quite easy to follow when you get it.

PHP starts and ends with <?php to ?> . Everything between these tags is seen as PHP
code.

Establish a connection string


This passes your DB details to 3 connection variables (created with a $ in front) which are
then passed to the connection string to gain access to the database. These 3 variables
could be named anything its the mysql_connect(Server, Username, Password) that is
the key here.

When you have a connection to the database you need to select the table in that database
you want. mysql_select_db("Table")

$mysqlDatabaseName = "mysql8.000webhost.com";
$mysqlUsername = "a5858161_gary";
$mysqlPassword = "PW";

mysql_connect($mysqlDatabaseName, $mysqlUsername, $mysqlPassword) or


die(mysql_error());
mysql_select_db("a5858161_test") or die(mysql_error());

Once this works then you can pass whatever SQL statements you want to the database and
get replies.

Basic For Android Monday, 11 June 2012 Page 36


Sending data to the database
In this case we send the data from the phone to the PHP of.

"http://android-
dsed.host22.com/netdb.php?action=add&name=me&deviceID=deviceID&text=inputtext

The code in the PHP scans the url we send and extracts from it the values we want to pass
to the database, name, device and text.

Action is used to tell the PHP which function we are to run, Add or Getall. We can create
any number of functions and run them this way.

So here we run the Action function and get the name, device, text from the string passing it
to the variables $name, $deviceID, $text.

if($action == "add"){
$name = $_GET['name'];
$deviceID = $_GET['deviceID'];
$text = $_GET['text'];

Then we run an SQL query and pass those three variables into the database.

mysql_query("INSERT INTO webDB


(name, deviceid, text) VALUES('$name', '$deviceID', '$text') ") or die(mysql_error());
The or die(mysql_error()) is just to give an escape in case the query doesnt work, like Try
/ Catch.

Retrieving data from the database


When retrieving data from the database we just use a straight SQL statement again.

$result = mysql_query("SELECT name, text, deviceID FROM webDB") or die(mysql_error());


Data is formatted by line when it returns with "\r\n" being a line break. The string is
concatenated with a . (as opposed to a & or + that we are used to).

while($row = mysql_fetch_array($result)){
echo $row['name'];
echo "\r\n".$row['text'];
echo "\r\n".$row['deviceID']."\r\n";

This will return from In the Android code we use reader.readline to return the following in
the DB the same order as left.
Me name = reader.ReadLine
Message linetext = reader.ReadLine
DeviceID postdeviceID = reader.ReadLine

Basic For Android Monday, 11 June 2012 Page 37


Here is the full PHP code, save it as netdb.php or any other name you can remember.

<?php
$mysqlDatabaseName = "mysql8.000webhost.com";
$mysqlUsername = "a5858161_gary";
$mysqlPassword = "PW";

mysql_connect($mysqlDatabaseName, $mysqlUsername, $mysqlPassword) or


die(mysql_error());
mysql_select_db("a5858161_test") or die(mysql_error());

if(isset($_GET['action'])){
$action = $_GET['action'];
}

if($action == "add"){
$name = $_GET['name'];
$deviceID = $_GET['deviceID'];
$text = $_GET['text'];

mysql_query("INSERT INTO webDB


(name, deviceid, text) VALUES('$name', '$deviceID', '$text') ")
or die(mysql_error());
}

if($action == "getall"){
$result = mysql_query("SELECT name, text, deviceID FROM webDB" ) or
die(mysql_error());

//DATA OUT TO PROGRAM


while($row = mysql_fetch_array($result)){
echo $row['name'];
echo "\r\n".$row['text'];
echo "\r\n".$row['deviceID']."\r\n";
}
}
?>

Basic For Android Monday, 11 June 2012 Page 38


Uploading your PHP script
Now we have a php script acting as a gateway to the database we need to upload it on to
the server. Thats easy.

Go to File Manager in your CPanel

Go to the Public_html folder in your account.

Then upload your file to that folder.

Done!

Check your php is working by typing in the path to the DB as well as the Getall action.

Your path will have another name, instead of android-dsed below. This should return the
sample data you have in your database.

http://android-dsed.host22.com/netdb.php?action=getall

It wont look much, just raw data on your screen something like this although I have more
data in my Database.

Basic For Android Monday, 11 June 2012 Page 39


Android Communication Program Basic setup
The coding for this program is remarkably easy. At this stage its just
a simple system but has a myriad of potential uses. Think of this as a
bare bones system to be further developed to meet the needs.

The code is commented. Replace the Android-DSED in

req.InitializeGet("http://android-
dsed.host22.com/netdb.php?&action=getall")
with the path to your own path

Test that the path is correct by putting your path http://android-


dsed.host22.com/netdb.php?&action=getall in the browser If its
OK it will return the data from your database in the browser itself.

The android code below is commented to make it easy to follow.

Basically you make a connection using HTTpClient, (Dim httpC As


HttpClient ) then make a request using HTTpRequest (Dim Req As
HttpRequest).

This returns an HttpResponse which is either successful Sub


httpC_ResponseSuccess or not Sub httpC_ResponseError.

All the rest is window dressing to make it work.

When you add your text you cant have any spaces between the words as they break the
URL that being sent. So

inputtext = inputtext.Replace(" ", "_")


is added to the code to replace the spaces with an underscore

When the text is returned to the phone we want to get rid of those underlines again to make
it look nice. So use

'strip out the underscores


result = result.Replace("_"," ")
As a result it looks like ordinary text leaves the phone and ordinary text is shown back on
the phone.

Sub Process_Globals
Dim httpC As HttpClient 'the Connection client
End Sub

Sub Globals
Dim pnlbg As Panel ' background panel
Basic For Android Monday, 11 June 2012 Page 40
Dim btnsubmit As Button ' Send to DB
Dim btncallDB As Button ' Retrieve from DB
Dim txtinput As EditText ' Text entry field
Dim lvoutput As ListView ' Show the messages from the DB
Dim reader As TextReader ' reading the text from the DB

Dim phoneInfo As PhoneId


Dim deviceID As String
deviceID = phoneInfo.GetDeviceId ' getting the Phone ID

End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("main")
httpC.Initialize("httpC")
'keeps it transparent when you scroll to see the text
lvoutput.ScrollingBackgroundColor = Colors.Transparent
End Sub
Nothing here for these two subs
Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)


End Sub

click event getting data from the DB


Sub btncallDB_Click
Dim req As HttpRequest ' requesting net data

req.InitializeGet("http://android-
dsed.host22.com/netdb.php?&action=getall") create the connection string
httpC.Execute(req, 1) send the request
ProgressDialogShow("Fetching all data...") make a progress dialog
that give the viewer something to look at
End Sub

Sub httpC_ResponseSuccess (Response As HttpResponse, TaskId As Int)


lvoutput.Clear clear the list box so it loads the new data in fresh

Dim result As String 'download results


result = Response.GetString("UTF8")
'strip out the underscores
result = result.Replace("_"," ")
'write it to a file
Basic For Android Monday, 11 June 2012 Page 41
File.WriteString(File.DirInternalCache, "nettalk.txt",result)
'get it back from the file
reader.Initialize(File.OpenInput(File.DirInternalCache, "nettalk.txt"))

'read it line by line to a string called line,


Dim name As String
name = reader.ReadLine this loads the username "me" echo $row['name'];

Dim i As Int :i = 0'dimension a counter just to show in the scrollview

Do While name <> Null 'run a loop while there is a line


i = i+1

'returns the message text echo "\r\n".$row['text'];


Dim linetext As String
linetext = reader.ReadLine

'returns the DeviceID text echo "\r\n".$row['text'];


Dim postdeviceID As String
postdeviceID = reader.ReadLine

'Set up the listview formatting and adds name and then text
lvoutput.SingleLineLayout.Label.TextSize = 16
lvoutput.SingleLineLayout.ItemHeight = 35
lvoutput.SingleLineLayout.Label.TextColor = Colors.Black
lvoutput.AddSingleLine(i&" "& name & " "& linetext)
name = reader.ReadLine 'passes only to the ME text
Loop

reader.Close
ProgressDialogHide stop the progress dialog box
lvoutput.SetSelection(0)
End Sub

Sub lvoutput_ItemClick(Position As Int, Value As Object)


Msgbox(Value, "Message") 'click on the message shows it in a msgbox
End Sub

Sub httpC_ResponseError (Response As HttpResponse, Reason As String,


StatusCode As Int, TaskId As Int)
Msgbox("Error connecting to score server"&CRLF&CRLF&Reason,"Error
("&StatusCode&")")
ProgressDialogHide
End Sub

Basic For Android Monday, 11 June 2012 Page 42


'SUBMIT MESSAGE
Sub btnsubmit_click

Activity.Title = "Submitted"
Dim inputtext As String
inputtext = txtinput.Text

If inputtext <>"" Then 'if there is something in the textbox


inputtext = inputtext.Replace(" ", "_")

ProgressDialogShow("Submitting data...")
Dim req As HttpRequest 'create a DB request

sendrequest = "http://android-
dsed.host22.com/netdb.php?action=add&name=me&deviceID="

req.InitializeGet(sendrequest & deviceID &"&text=" & inputtext)


httpC.Execute(req, 1)

Else 'if empty show an error message


ToastMessageShow("Put a message in first", False)
End If
txtinput.Text = "" 'clear the text box
End Sub

Android Communication Program Timestamp and Limit


So you got it to work, and it looks OK, however there are some major flaws.

1. How do you know when a message was sent?


2. How do you limit how many messages are returned? Every time you click Read All
the entire database is sent to you which will quickly become a pain in the neck.
3. How do we get the listview to show the data with the most recent entry at the top?

Using Timestamp
To solve the first one we could send a time with your message which gets stored on the net,
however the problem with this is that if someone else is in another part of the world that
timestamp will be different to yours.

Lets make a timestamp that is on the server so that all messages are tagged with the same
timezone.

Go back to PhpAdmin, and open your database and find the Add New Field area, it appears
in a number of windows.

Basic For Android Monday, 11 June 2012 Page 43


Create a new field called Timestamp

The TIMESTAMP data type is used for values that contain both date and time parts.
TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

If the column is auto-updated, it is automatically updated to the current timestamp when the
value of any other data in the row is changed from its current value.

We can use the Timestamp as an index field as well if we want and we can perform time
calculations from it to get all the posts in the last 24 hours for example.

Using Limit
We can limit how many records are returned with the Limit command. In your PHP getall
code set the limit to 10 (LIMIT 10 ), or whatever number you wish.

Using our new Timestamp order the records by Timestamp and in reverse order (ORDER
BY TIMESTAMP DESC)

if($action == "getall"){
$result = mysql_query("SELECT name, text, deviceID FROM scoreTable
ORDER BY TIMESTAMP DESC LIMIT 10 " ) or die(mysql_error());

Save and upload your new PHP script to the server.

Cutting out the unwanted text


Notice that when you return the data to the phone it comes back with
two unwanted lines of code at lines 7 and 8 in the image.

We can easily remove this using indexof and substring commands


from our earlier exercise. Go ahead and make the changes.

Basic For Android Monday, 11 June 2012 Page 44


Deleting data from your database.
This is easy in theory but takes more work than you think.
First make a new button on your layout and call it Btndelete.
Declare the following under Sub Globals

Dim btndelete As Button


Dim message As String holds the message string
Firstly we need to get a field to identify the row of data. The
best field for this, being the easiest, is the ID field.

In your PHP we need to call down the ID field as well so we


can use it int eh delete query. In the code below I have
added ID, and echo $row['ID']; to get the ID field into your
program.

if($action == "getall"){
$result = mysql_query("SELECT ID, name, text, deviceID FROM webDB
ORDER BY TIMESTAMP DESC LIMIT 10" ) or die(mysql_error());

//DATA OUT TO PROGRAM


while($row = mysql_fetch_array($result)){
echo $row['ID'];
echo "\r\n".$row['name'];
echo "\r\n".$row['text'];
echo "\r\n".$row['deviceID']."\r\n";
}
}

Now that it is being returned. We need to put it into the program.

Since we now have an ID field lets rebuild the following sub using ID as the main control.

As well we can do some housework.

'strip out the end text with the annoying text at the end
Dim Endstring As Int
Endstring = result.IndexOf("<!")
result = result.SubString2(0, Endstring)

Full code.

Sub httpC_ResponseSuccess (Response As HttpResponse, TaskId As Int)


lvoutput.Clear
'download results
Dim result As String
result = Response.GetString("UTF8")

Basic For Android Monday, 11 June 2012 Page 45


'strip out the end text with the annoying text at the end
Dim Endstring As Int
Endstring = result.IndexOf("<!")
result = result.SubString2(0, Endstring)

'strip out the underscores


result = result.Replace("_"," ")

'write it to a file
File.WriteString(File.DirInternalCache, "nettalk.txt",result)
'get it back from the file
reader.Initialize(File.OpenInput(File.DirInternalCache, "nettalk.txt"))

'Starts the download Get back the ID echo $row['ID'];


Dim ID As String
ID = reader.ReadLine

'run a loop while there is a still an ID - it gets the next ID at the end
of the loop
Do While ID <> Null

'read it line by line to a string called line this loads the user name
"name" echo $row['name'];
Dim name As String
name = reader.ReadLine

'returns the message text echo "\r\n".$row['text'];


Dim linetext As String
linetext = reader.ReadLine

'returns the message text echo "\r\n".$row['text'];


Dim postdeviceID As String
postdeviceID = reader.ReadLine

'adds name and then text otherwise will be on seperate lines


lvoutput.SingleLineLayout.Label.TextSize = 16
lvoutput.SingleLineLayout.ItemHeight = 35
lvoutput.SingleLineLayout.Label.TextColor = Colors.Black
lvoutput.AddSingleLine(ID &": "& name & " "& linetext & " " &
postdeviceID)

ID = reader.ReadLine
Loop
reader.Close
ProgressDialogHide
lvoutput.SetSelection(0)
End Sub

Basic For Android Monday, 11 June 2012 Page 46


We now have the Device ID of the phone showing as well. If
you are just using the Emulator it comes up blank (no phone).
Later we can use the device ID to make the Me only show for
your phone.

Once we can see the data on your screen we need to find a


way to delete out the fields we want.

As we have a touch device the easiest way is to touch the


entry you dont want.

The Listview Itemclick is the event that a touch on the text raises so this will be changed
adding message = Value to the variable so that message holds the string that is raised
when you click on it. We have to declare it under Globals as well Dim message As String

Sub lvoutput_ItemClick(Position As Int, Value As Object)


message = Value
Msgbox(Value, "Message") 'click on the message shows it in a msgbox
End Sub

Finally we need to add the code under the Delete Button. First it looks in the message for

the : eg in .

We want what is left of the : to get the ID number (4 or 5).

IndexOf returns the number of where the : is stripstring = IDdelete.IndexOf(":")

This number is then put into IDdelete = IDdelete.SubString2(0, stripstring) which has the
following Substring2(startnumber, endnumber) So it starts at 0 and ends at the number of
the : Of course the end number will vary depending on how many numbers in the ID eg: 4,
or 32, or 45342345.

Basic For Android Monday, 11 June 2012 Page 47


Sub btndelete_click

Dim IDdelete As String


IDdelete = message
'need to strip the message back to the first ID, by using the indexof
Dim stripstring As Int
stripstring = IDdelete.IndexOf(":")
IDdelete = IDdelete.SubString2(0, stripstring)

'this shows me in the code if I have it right


Log(IDdelete)

Dim req As HttpRequest ' requesting net data

req.InitializeGet("http://android-
dsed.host22.com/netdb.php?&action=delete&ID="&IDdelete)
httpC.Execute(req, 1)
ProgressDialogShow("deleting message...")
End Sub

In the webDB.php add the following code, anywhere outside of the other functions.

First it looks for the action delete. When it finds that it pulls out the ID which is then passed
to $deleteID and run in the SQL.

//delete messages
if($action == "delete"){
$deleteID = $_GET['ID'];
mysql_query("DELETE FROM webDB WHERE ID = '$deleteID'" ) or
die(mysql_error());
}

Basic For Android Monday, 11 June 2012 Page 48


6. Project: GPS Program
Creating a GPS system involves two parts, the first is getting the GPS subsystems to work
on the phone, this is pretty easy. The second part is
getting the rotating arrow in the compass to work. This is
also easy but requires accepting some design voodoo is
going on.

Start with a new project

Set your Orientation to portrait, otherwise it will change


all the time when you wave your phone around.

Create the graphic Compass


Create an imageview named IVcompass

Set it with the values for dimensions


shown in the image. They will be seen in
the code with

Dim x, y, h, w As Int

Use the Add Images to add in the


compass and the arrow and then add the
compass (the circular background
image) to the Image

File. Save the layout as Main.

Basic For Android Monday, 11 June 2012 Page 49


The difficulty with the compass is that the background image is static but the Arrow itself
rotates depending on the GPS bearings.

Its getting that rotation of the Arrow that is the issue, we need to create a zone for the
Arrow to rotate with the rectangle object and using canvas.

Sub Process_Globals
'create a bitmap to hold the compass and the arrow
Dim imgcompass, imgArrow As Bitmap
Dim Rect1 As Rect
End Sub

Sub Globals
Dim IVcompass As ImageView 'the compass background
Dim Canvas1 As Canvas
Dim Bitmap1 As Bitmap
End Sub

Sub Activity_Create(FirstTime As Boolean)


Dim x, y, h, w As Int
Activity.LoadLayout("main.bal")
'set the compass and arrow
imgArrow.Initialize(File.DirAssets, "arrow.png")
imgcompass.Initialize(File.DirAssets, "compass.png")
Canvas1.Initialize(IVcompass)
w=IVcompass.Width
h=IVcompass.Height
Bitmap1.Initialize3(Canvas1.Bitmap)
Rect1.Initialize(0,0,w,h)
Canvas1.DrawBitmap(imgArrow, Null, Rect1)
End Sub

This should give a centred arrow on the Compass background.

Create the GPS


Import and activate the GPS and Phone Libraries.

There are three relevant objects.

The main one is GPS. The GPS manages the connection and events.

The second is Location.

A Location is a structure that holds the data available regarding a specific "fix". The data
includes the latitude and longitude coordinates, the time (expressed as ticks) of this fix
and other information like bearing, altitude etc

Basic For Android Monday, 11 June 2012 Page 50


The Location also includes other functionalities like calculating the distance and bearing
to another location and methods to convert the coordinates string formats.

Usually you will work with Location objects passed to you in the LocationChanged events.
However you can also initialize such objects yourself (this is useful for calculating distance
and bearing between locations).

The last one is GPSSatellite. This is a structure that holds information regarding the
currently known satellites. It is passed to you in GPSStatus event.

We are also going to create a location to save out GPS to called Dim SETloc As Location
and another using the Compass Dim Compass As PhoneSensors to show the direction
North Dim NPloc As Location

Lets create a new GPS and some storage places to record locations. Dim SETloc As
Location and Dim NPloc As Location so we can always find North again. To keep track of
the current location Dim Currentloc As Location. The locations are generated in the
LocationChanged sub later on.

Sub Process_Globals
'Create the GPS
Dim GPS1 As GPS
Dim SETloc As Location 'SET LOCATION
Dim NPloc As Location 'NORTH POLE
Dim Currentloc As Location 'CURRRENT LOC FROM THE GPS
Dim Compass As PhoneSensors
Dim GPSbearing, Compassbearing As Float
Dim Latitude, Longitude, lastlat, lastlon As Double

Under Activity Create lets initialise the GPS

If FirstTime Then
'North pole
NPloc.Initialize2("90:00:00", "00:00:00") 'North Pole
SETloc.Initialize()
SETloc = NPloc 'first time pass NP to Setloc to point north
Compass.Initialize(Compass.TYPE_ORIENTATION)
GPS1.Initialize("GPS")
Currentloc.Initialize() create a location to hold current location
End If

Basic For Android Monday, 11 June 2012 Page 51


GPS LocationChanged
The main part of the GPS is the LocationChanged sub.

Sub GPS_LocationChanged (Loc As Location)


This gives us the Location object named here loc. The heart of
the GPS

Loc can be broken down to all sorts of


properties such as Latitude and
Longitude.

We will need to pass these values back to


the screen so make 3 labels

Dim lblaccalt As Label


Dim lbllonlat As Label
Dim lblspeed As Label

As loc is stuck inside of that sub if you want to use it anywhere


else in the program you need to pass it to another Location
variable. In this case we pass it to Currentloc. This holds all of the
properties of the Loc

Currentloc = Loc

You can pass the Lat and Lon in 2 ways Decimal values or Hours,
minutes etc. You need decimal to pass to google maps, but people
like to see minutes on the screens for their GPS systems. This
'textlon = Loc.Longitude gives decimal and textlat =
Loc.ConvertToMinutes(Loc.Latitude) gives minutes, you choose
for what you need.

'textlon = Loc.Longitude
'textlat = Loc.Latitude

textlat = Loc.ConvertToMinutes(Loc.Latitude)
textlon = Loc.ConvertToMinutes(Loc.Longitude)

All code

Sub GPS_LocationChanged (Loc As Location)


'This Is the main event. Loc holds the data for the new fix.
Longitude = Loc.Longitude

Basic For Android Monday, 11 June 2012 Page 52


Latitude = Loc.Latitude ' Store the new latitude position in this string
Currentloc = Loc ' make a new location called Current LOC give it
current data

Dim degrees As Float


'bearing is the direction
If GPSbearing <> Loc.BearingTo(SETloc) Then ' change the compass to point
to the setLOC
GPSbearing = Loc.BearingTo(SETloc)
degrees = (GPSbearing - Compassbearing)
Canvas1.DrawBitmap(Bitmap1, Null, Rect1)
Canvas1.DrawBitmapRotated(imgArrow, Null, Rect1, degrees)
Activity.Invalidate()
End If

'work out speed


Dim locspeed As Double
locspeed = Loc.Speed * 3.6 '= kmh
lblspeed.Text = "Speed = " & Round2(locspeed ,2) &" KPH"

Dim textalt, textacc As Double


Dim textlat, textlon As String

'textlon = Loc.Longitude
'textlat = Loc.Latitude

textlat = Loc.ConvertToMinutes(Loc.Latitude)
textlon = Loc.ConvertToMinutes(Loc.Longitude)
textalt = Loc.Altitude
textacc = Loc.Accuracy

lbllonlat.Text =" Lat - " & textlat & CRLF & " Lon - " & textlon
lblaccalt.Text ="Altitude - " & Round2(textalt, 0) & " Meters" & CRLF &
"Accuracy - " & Round2(textacc, 0) & " Meters"
End Sub

Activity Pause and Resume code


The GPS turns off when you leave the activity, this is to save the battery. When you restart
the program, or reenter this activity it is turned on again. Obviously there might be times
when you dont want it turned off.

Sub Activity_Pause (UserClosed As Boolean)


'turn off the GPS to save the battery
GPS1.Stop
End Sub

Basic For Android Monday, 11 June 2012 Page 53


Sub Activity_Resume
'start listening for GPS - turn it on
If GPS1.GPSEnabled = False Then 'turn on your GPS
ToastMessageShow("Please enable the GPS device", True)
'Will open the relevant settings screen.
StartActivity(GPS1.LocationSettingsIntent)
Else
'Listen to GPS with no filters.
'The Start method receives two values which are the minimum time
(milliseconds) AND the minimum distance (meters) between events. An event
will be raised when at least one of these criterions are met. This can
help saving battery. In our case we are passing 0 AND therefore will get
all fix events.
GPS1.Start(0,0)
End If
Compass.StartListening("Orientation")
End Sub

The Orientation_SensorChanged sub


Orientation_SensorChanged is used to expose the changes in the GPS to the arrow on the
compass. The code is trying to limit the compass reading to +/- 360 in quarter degrees units
by using an integer value for x where x Is the value of the compass bearing * 4, rather than
using the raw GPS values and so smoothing it out and saving on battery and CPU.

The If statement, If Compassbearing <> x/4.0 Then checks if the stored value for the
bearing has changed (that Is, has the bearing changed by more than a degree); If so, it
updates the stored value and moves the arrow.

Sub Orientation_SensorChanged(Values() As Float)


Dim degrees As Float, x As Int

x = ((2880 + Values(0) * 4) Mod 2880) - 1440


If Compassbearing <> x/4.0 Then
Compassbearing = x/4.0

degrees = GPSbearing - Compassbearing


Canvas1.DrawBitmap(Bitmap1, Null, Rect1)
Canvas1.DrawBitmapRotated(imgArrow, Null, Rect1, degrees)
Activity.Invalidate()
End If
End Sub

Basic For Android Monday, 11 June 2012 Page 54


GPS on Google maps using Intents
We are going to add the Google map link as a menu item. You can easily use a button but
menus are good to develop

Add the following to Sub Activity_Create

Activity.AddMenuItem("Google Map Location", "Googlemap")

Then at the bottom of the code have a click event for that menu item. Sub Googlemap_click

Intent objects are messages which you can send to the OS in order to do some external
action in the phone. We want to open the Google maps on the cell phone.

Firstly you have define a new intent, Dim Intent1 As Intent

Then initialise it with the options you want Initialize (Action As String, Uri As String)

Intent1.Initialize(Intent1.ACTION_VIEW,URI)

Gets or sets the Intent action. Other actions are .

ACTION_APPWIDGET_UPDATE As String
ACTION_CALL As String
ACTION_EDIT As String
ACTION_MAIN As String
ACTION_PICK As String
ACTION_SEND As String
ACTION_VIEW As String

Then we need a SetComponent (Component As String). Explicitly sets the component that
will handle this intent.

Intent1.SetComponent("googlemaps")
The Intent object should finally be started with StartActivity keyword StartActivity(Intent1)

Sub Googlemap_click
Dim Intent1 As Intent
URI= "geo:" & Latitude & "," & Longitude & "?q=" & Latitude & "," &
Longitude

Intent1.Initialize(Intent1.ACTION_VIEW,URI)
Intent1.SetComponent("googlemaps")
StartActivity(Intent1)

'streetview works as well


' URI= "google.streetview:cbll=" & Latitude & "," & Longitude & "&cbp=1"
'google.streetview:cbll= Latitude, Longitude
&cbp=1,yaw,,pitch,zoom&mz=mapZoom
End Sub

Basic For Android Monday, 11 June 2012 Page 55


This should give you a start with working with GPS. From here
you could make a DB and save GPS locations then show the
distance between them and current position.

7. Project: GPS and the net SQL: Record


your position online
Now we have two programs that can come together to make
something interesting. What if we were able to save our latitude
and longitude to an SQL database table on the net? Then we, or
someone else, could download those coordinates, and run them
through the Google maps to see where we are, or were. This is
easy to do.

Check back with the earlier program to get the finer details of what
we must do.

Here are the steps.

Create a new database table


1. Create a new table in your SQL database named GPSLocation make 5 fields

Set them as below.

You now have 2 tables in your database

Basic For Android Monday, 11 June 2012 Page 56


Create a new PHP script
We could use the same PHP script we made before but lets make a new one so we can
keep it with our program in the same folder to make it easier updating. Copy and paste your
webDB.php file and save it as GPSLocation.php into your project.

Add a new function addgps

if($action == "addgps"){
$lat = $_GET['lat'];
$lon = $_GET['lon'];
$deviceID = $_GET['deviceID'];

mysql_query("INSERT INTO GPSlocation


(lat, lon, deviceid) VALUES('$lat', '$lon', '$deviceID') ")
or die(mysql_error());
}

We are using the INSERT command and this will make a new entry each time it saves.
However you might want to consider using an UPDATE command which will just change the
single saved GPS location if you only want to record the current location.

UPDATE table_name
SET column1=value, column2=value2,...
WHERE some_column=some_value

Use the Submit code from the last exercise to submit this to the DB.

First define the following under Sub Process_Globals

Dim phoneInfo As PhoneId


Dim deviceID As String
deviceID = phoneInfo.GetDeviceId ' getting the Phone ID
Dim httpC As HttpClient 'the Connection client

Initialise the HTTPC under Sub Activity_Create(FirstTime As Boolean)

httpC.Initialize("httpC")

Click on the HTTP library and the Phone Library to add it to the project.

Add the Menu button code to the Activity_Create

Activity.AddMenuItem("Upload Location", "uploadlocation")

Basic For Android Monday, 11 June 2012 Page 57


Create a new sub, Sub uploadlocation_click that is the click event of the menu item
above, add the code full version below to it. And try it.

The 'sendrequest1 comment can be used to check if the php script is working, without
having to see if the rest is OK. Just change the request to req.InitializeGet(sendrequest1).

Here you can clearly see the 3 code blocks of Sending, Sub httpC_ResponseSuccess, and
Sub httpC_ResponseError needed to work with HTTP.

'SUBMIT GPS
Sub uploadlocation_click
variables to hold the lat and lon locations
Dim lat, lon As Double
lon = Currentloc.Longitude
lat = Currentloc.Latitude
Just a dialog to tell the user something is working
ProgressDialogShow("Submitting GPS ...")
Make a request
Dim req As HttpRequest

sendrequest = "http://android-
dsed.host22.com/gpslocation.php?action=addgps&lat="
'sendrequest1 = "http://android-
dsed.host22.com/gpslocation.php?action=addgps&lat=456&lon=123&deviceID=123
456"
Sending the request
req.InitializeGet(sendrequest & lat & "&lon=" & lon &"&deviceID=" &
deviceID)
httpC.Execute(req, 1)
Check to see what is going is OK
Activity.Title = lat &" "&lon &" " & deviceID
End Sub

Sub httpC_ResponseSuccess (Response As HttpResponse, TaskId As Int)


show a message
ToastMessageShow("Success GPS uploaded", False)
Turn the dialog off
ProgressDialogHide
End Sub

Sub httpC_ResponseError (Response As HttpResponse, Reason As String,


StatusCode As Int, TaskId As Int)
Msgbox("Error connecting to score server"&CRLF&CRLF&Reason,"Error
("&StatusCode&")")
ProgressDialogHide
End Sub

Basic For Android Monday, 11 June 2012 Page 58


Your Database will show the details right. If your
program hasnt picked up the location it will return 0.
Thats still OK its just a GPS issue rather than a coding
issue (hopefully).

Getting satellites
Sub GPS_GpsStatus (Satellites As List)
'This event allows you To display information about the currently
available satellites. Note that Not all satellites in the List are
actually used For calculating the last fix. So it Is possible that the
List will include several satellites but still the reception Is Not good
enough For a fix.

Dim SatCount As Int


SatCount = 0
For i = 0 To Satellites.Size - 1
'loop through counting satellites
Dim Satellite As GPSSatellite
Satellite = Satellites.Get(i)
If Satellite.UsedInFix = True Then SatCount = SatCount + 1
Next

lblsatt.Text = "Satellites In View: " & Satellites.Size & " Used: " &
SatCount

End Sub

Basic For Android Monday, 11 June 2012 Page 59


Retrieving data from the database and displaying distance to saved GPS location

We have the GPS location saved in the database and


now we want it back in the phone.

First we need the PHP code to call. I kept it simple by


using the same structure as the last exercise but changing the limit to 1. ORDER BY
TIMESTAMP DESC LIMIT 1 This means it takes the most recent entry only.

if($action == "getgps"){
$result = mysql_query("SELECT lat, lon, deviceID FROM GPSLocation ORDER BY
TIMESTAMP DESC LIMIT 1" ) or die(mysql_error());
//DATA OUT TO PROGRAM
while($row = mysql_fetch_array($result)){
echo $row['lat'];
echo "\r\n".$row['lon'];
echo "\r\n".$row['deviceID']."\r\n";
}
}

In Sub Activity_Create(FirstTime As Boolean) create a new menu item to use as


the click event.

We also want to create a new Location named SavedLocation that will allow me to get
distance and bearing from the current location to the saved location.

In Globals create the Location object Dim savedlocation As Location, and initialise it
in Activity Create below.

Activity.AddMenuItem("Download to GoogleMaps", "downloadgps")


savedlocation.Initialize()

Basic For Android Monday, 11 June 2012 Page 60


Then in a new click event for the menu I put the following which by now is quite
straightforward calling the getgps function in the gpslocation.php above.

'GET THE GPS BACK INTO THE PHONE FROM THE DB


Sub downloadgps_click
Dim req As HttpRequest ' requesting net data

req.InitializeGet("http://android-
dsed.host22.com/gpslocation.php?&action=getgps")

'(req, 2) means it has a taskid of 2 see in the Sub httpC_ResponseSuccess


httpC.Execute(req, 2)
ProgressDialogShow("Fetching all data...")
End Sub

The result that is returned comes in via the httpC_ResponseSuccess. The pattern is the
same as the previous example. Read the data in line by line to a datafile, read it out to the
variables.

When we get the Lat and Lon, pass them to the savedlocation.Latitude to be used later. The
deviceID is downloaded but not used at this point. After getting the data we close the
reader with reader.Close.

Using the previous code for the GoogleMaps we pass the data to the maps. Finally with our
new SavedLocation we can see the distance from current GPS location to that point.

Sub httpC_ResponseSuccess (Response As HttpResponse, TaskId As Int)


'(req, 1) means that taskID = 1 the upload function only
If TaskId = 1 Then
ToastMessageShow("Success GPS uploaded", False)
ProgressDialogHide

Else
'Any other function with a taskID of 2 - the download function
Dim result As String result from the database being passed in
result = Response.GetString("UTF8")
'write it to a file
File.WriteString(File.DirInternalCache, " gpsdownload.txt",result)
'get it back from the file
reader.Initialize(File.OpenInput(File.DirInternalCache, "
gpsdownload.txt"))

Dim latgps As String make a latitude variable to hold lat


latgps = reader.ReadLine read the data to the variable
savedlocation.Latitude = latgps save it also to the savedlocation object

Dim longps As String

Basic For Android Monday, 11 June 2012 Page 61


longps = reader.ReadLine
savedlocation.Longitude = longps

Dim deviceID As String


deviceID = reader.ReadLine

reader.Close
Dim Intent1 As Intent
URI= "geo:" & latgps & "," & longps & "?q=" & latgps & "," & longps

Intent1.Initialize(Intent1.ACTION_VIEW,URI)
Intent1.SetComponent("googlemaps")
StartActivity(Intent1)

Activity.Title = "Distance to location " &


Currentloc.DistanceTo(savedlocation)& " in meters"
End Sub

Here is a pic of the Google maps showing the saved location at and the current location
with the blue Arrow. (Note this this pre earthquake so there are far more buildings and cars).
You can see on the title bar that the distance is 80.2 meters to the saved location.

As the distance has a ridiculous amount of decimal spaces in it lets round it off to 2 decimal
places. Round2(distloc, 2) is the primary code for this.

Dim distloc As Long


distloc = Currentloc.DistanceTo(savedlocation)
distloc = Round2(distloc, 2)

Activity.Title = "Dist to saved location " & distloc & " meters"

Basic For Android Monday, 11 June 2012 Page 62


8. Project: Getting an address from a Geolocation using
XML
As well as returning a map reference from lat and lon you can also use Google to return the
actual address of the place as well.

Instead of adding this ability to the last exercise I have left it as a stand alone project so that
you can add it in yourself, and see how it works. (Otherwise the code gets mixed up and
you never know what does what). Its your job to add it in.

The data that is returned comes down in an XML format and has to be parsed using
XMLSAX. SAX (Simple API for XML) is an event-based sequential access parser API
developed by the XML-DEV mailing list for XML documents to return XML to a useable
structure.

The edtgeo text field is only there so you can see the output returned from Google. You can
see in the code where it looks for the <formatted Address> field and extracts it to show in
the Message Box below.

If Name = "formatted_address" Then


'then pass the address details to the items list
Address = Text.ToString
Items.Add(Address)

Basic For Android Monday, 11 June 2012 Page 63


Here is all the code and the libraries on the right

Sub Process_Globals
Dim GPS1 As GPS
Dim Parser As SaxParser 'Parser library
Dim hc As HttpClient 'Required to connect to the Internet
Dim req As HttpRequest
End Sub

Sub Globals
Dim lblLon As Label
Dim lblLat As Label
Dim lblSpeed As Label
Dim Button1 As Button
Dim edtgeo As EditText

Dim gLatitude As Float


Dim gLongitude As Float

Dim Address As String 'Variable to save the Address parsed


Dim Items As List 'A list to hold parsed items
End Sub

Sub Activity_Create(FirstTime As Boolean)


If FirstTime Then
GPS1.Initialize("GPS")
End If

Activity.LoadLayout("1") ' the layout is called 1 instead of main, just


for variety
Parser.Initialize
hc.Initialize("hc")
Items.Initialize
'this formats up the text box to make it as big as possible.
edtgeo.Width = Activity.Width ' the width of the phone
edtgeo.Top = 250 ' 250 from the top to show the button etc
edtgeo.Left = Activity.left ' left hand side
edtgeo.Height = Activity.Height - 250 ' height of the phone - the 250
End Sub

Sub Activity_Resume
If GPS1.GPSEnabled = False Then
ToastMessageShow("Please enable the GPS device.", True)

Basic For Android Monday, 11 June 2012 Page 64


StartActivity(GPS1.LocationSettingsIntent) 'Will open the relevant
settings screen.
Else
GPS1.Start(0, 0) 'Listen to GPS with no filters.
End If
End Sub

Sub Activity_Pause(UserClosed As Boolean)


GPS1.Stop
End Sub

Sub GPS_LocationChanged(Location1 As Location)


gLatitude = Location1.Latitude
gLongitude = Location1.Longitude

'show the lat and lon on the labels


lblLat.Text = "Latitude = " & gLatitude
lblLon.Text = "Longitude = " & gLongitude
lblSpeed.Text = "Speed = " & Location1.Speed

'when you get a GPS fix then make the button show
If Location1.Latitude <> 0 AND Location1.Longitude <> 0 Then
Button1.Visible = True
End If
End Sub

Sub GPS_UserEnabled(Enabled As Boolean)


'just shows you have GPS enabled
ToastMessageShow("GPS device enabled = " & Enabled, True)
End Sub

Sub Button1_Click
Items.Clear 'Empty the list
edtgeo.Text = "" ' empty the text box
'send the request to the server
req.InitializeGet("http://maps.googleapis.com/maps/api/geocode/xml?latlng=
" & gLatitude & "," & gLongitude & "&sensor=true")
hc.Execute(req, 1)
End Sub

Basic For Android Monday, 11 June 2012 Page 65


If you get a result back then save it to a text file - File.OpenOutput(File.DirDefaultExternal,
"Geo.xml", False).

'GetAsynchronously (EventName As String, Output As java.io.OutputStream, CloseOutput


As Boolean, TaskId As Int) As Boolean

'EventName As String = GetGeoLocation


'Output As java.io.OutputStream = File.OpenOutput(File.DirDefaultExternal,
"Geo.xml", False)
'CloseOutput As Boolean = true
'TaskId As Int = taskID

Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int)


Response.GetAsynchronously("GetGeoLocation",File.OpenOutput(File.DirDefaul
tExternal, "Geo.xml", False), True, TaskId)
End Sub

Sub hc_ResponseError(Response As HttpResponse, Reason As String,


StatusCode As Int, TaskId As Int)
If Response <> Null Then
Msgbox("Connection Error", "")
Response.Release
End If
End Sub

Geolocation
'when the GetGeoLocation from the Response above has finished
Sub GetGeoLocation_StreamFinish(Success As Boolean, TaskId As Int)
Dim in As InputStream
'read the file into the input stream variable
in = File.OpenInput(File.DirDefaultExternal, "Geo.xml")
edtgeo.Text= File.ReadString(File.DirDefaultExternal, "Geo.xml")

'parse it through the parser and name the event as "Parser"


Parser.Parse(in, "Parser")' below are the start and end events of the
parsing. Close the input stream
in.Close
'show the items list that is filled below in the Parser_EndElement
Msgbox(Items.Get(0), "")
End Sub

XML parser
The last two are happening at the start and the end of Parser.Parse(in, "Parser")

Sub Parser_StartElement(Uri As String, Name As String, Attributes As


Attributes)
End Sub

Basic For Android Monday, 11 June 2012 Page 66


Sub Parser_EndElement(Uri As String, Name As String, Text As
StringBuilder)
'if there is Activity result (> -1)
If Parser.Parents.IndexOf("result") > -1 Then
'if the name (the string being parsed above) has in it formatted address
If Name = "formatted_address" Then
'then pass the address details to the items list
Address = Text.ToString
Items.Add(Address)
End If
End If
End Sub

9. Getting an error in your hc_ResponseSuccess? Fix the


taskID.
If you are adding in new code that calls the internet into your program you may / will get an
error that we havent covered so far.

Each call to the internet via the HTTP used the code similar to hc.Execute(req, 1). The 1 is
the taskID that is passed to the hc_ResponseSuccess. You see it being passed as TaskId
As Int.

Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int).

Multiple calls to the net all return through the same subroutine above and regardless of what
they do will work with every line of text in there. To prevent errors occurring, which they will,
we need to change our taskID for each request.

So 3 calls to the net for different processes will look like this.

hc.Execute(req, 1).

hc.Execute(req, 2).

hc.Execute(req, 3).

Then in your hc_ResponseSuccess bracket your response code with the appropriate taskID

Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int).


If taskID = 1 then
End if
If taskID = 2 then
End IF
If taskID = 3 then
End if

Basic For Android Monday, 11 June 2012 Page 67


10. Project: Creating a Weather Widget
Widgets are the little programs that run on the front of your phone. They are active
programs, and more than just shortcuts that open the program.

Widgets are created and managed in another process, different than the process that your
application is running in. So its not just a front end of your
program and they run when your program has turned off. They
use a Service Module rather than the Activity Module that we
are used to. Each widget is tied to their own Service Module.
Through this module the widget is created and updated.

In this case we are making the Widget alongside the same


temperature program we made previously, but it could be in
a new program. The program only shares the text file that holds
the city selected.

The home screen application (the front of your phone) hosts your widgets and means that it
is not possible to directly access the widgets views. Instead we use a special object named
RemoteViews which gives us indirect access to the widget views.

Widgets do not support all views types. The following views are supported:

- Button (default drawable)


- Label (ColorDrawable or GradientDrawable)
- Panel (ColorDrawable or GradientDrawable)
- ImageView
- ProgressBar (both modes)

All views only support the Click event.

To make a widget we have to add a Service module. Note that the service module
handling the widget is a standard service. Design the widget layout with the designer.

Basic For Android Monday, 11 June 2012 Page 68


The Service Module
Create a Service module by going Project / Service Module. Name it ServiceWidget

A Service Module is good for scheduling a repeating task. By calling StartServiceAt you
can schedule your service to run at a specific time. You can call StartServiceAt in Sub
Service_Start to schedule the next time and create a repeating task (for example a task
that checks for updates every couple of minutes).

You can also run a service after the phone boots by checking Project - Service properties -
Start At Boot your service will run after boot is completed.

The Service Module has familiar areas to the Activity Module we have used to date.

Sub Process_Globals is the place to declare the service global variables. There is no
Globals sub like in Activity as Service doesn't support Activity objects. Sub process globals
should only be used to declare variables.

Note that Process_Global variables are kept as long as the process runs and are accessible
from other modules.

Sub Service_Create is called when the service is first started. This is the place to initialize
and set the process global variables. Once a service is started it stays alive until you call
StopService or until the whole process is destroyed.

Sub Service_Start is called each time you call StartService (or StartServiceAt). When
this subs runs the process is moved to the foreground state. Which means that the OS will
not kill your process until this sub finishes running. If you want to run some code every
couple of minutes / hours you should schedule the next task with StartServiceAt inside this
sub.

Sub Service_Destroy is called when you call StopService. The service will not be running
after this sub until you call StartService again (which will run Sub Service_Create followed
by Sub Service_Start).

Basic For Android Monday, 11 June 2012 Page 69


A Standard template for a Widget in the Service Activity

Sub Process_Globals
Dim rv As RemoteViews
End Sub

Sub Service_Create
rv = ConfigureHomeWidget("LayoutFile", "rv", 0, "Widget Name")
End Sub

Sub Service_Start (StartingIntent As Intent)


If rv.HandleWidgetEvents(StartingIntent) Then Return
End Sub

Sub rv_RequestUpdate
rv.UpdateWidget
End Sub

Sub rv_Disabled
StopService("")
End Sub

Sub Service_Destroy

End Sub

The code below is in the order that it can be placed on the Service Activity

Open your weather program and add a Service Module to it. Then add in the code.

'Service module
Sub Process_Globals
Dim rv As RemoteViews
Dim hc, hcimage As HttpClient
Dim req, reqimage As HttpRequest
Dim temp, strplace, townpath, pic, selectedcity, temperature As String
Dim oldtemp As Short : oldtemp = 0 ' holds the old temperature
End Sub

Basic For Android Monday, 11 June 2012 Page 70


ConfigureHomeWidget("wlayout", "rv", 0, "Temp Widget 26-4")

The four parameters are: layout file, event name, update interval and the widget name.
Widget name = the name that will appear in the widgets List.

Event name sets the subs that will handle the RequestUpdate AND Disabled events.

You can configure the widget and set it to update every 24 hours (1440 minutes). The
interval, measured in minutes, defines how often will the widget request To update itself. Set
To 0 To disable automatic updates. Updating the widget too often will have a bad impact on
the battery. The minimum value Is 30 minutes. We can use a timer to get a shorter interval.

Sub Service_Create
rv = ConfigureHomeWidget("wlayout", "rv", 0, "Temp Widget 26-4")
hc.Initialize("hc")
hcimage.Initialize("hcimage")
GetTemp
End Sub

This checks the Intent message that caused this Service To start and is responsible for
raising the events related to the widget. It returns True If an event was raised.

Sub Service_Start (StartingIntent As Intent)


If rv.HandleWidgetEvents(StartingIntent) Then Return
End Sub
The widget raises two events. RequestUpdate is raised when the widget needs to update
itself. It will fire after adding the widget to the screen, after the device has booted, based on
the scheduled updating interval (If set) or after the application was updated.

Sub rv_RequestUpdate
GetTemp
End Sub

Sub rv_Disabled
StopService("")
End Sub

Sub imgNext_Click click event of the image


GetTemp
End Sub

Sub panel1_click click event of the panel


GetTemp
End Sub

Basic For Android Monday, 11 June 2012 Page 71


This is the main sub of the widget. I will comment it throughout the code. This is mostly the
same code as we used in our earlier exercise.

Sub GetTemp
we call the selected city that has been stored in the text file of the
weather program
selectedcity = File.ReadString(File.DirInternal, "WeatherCity.txt")
What if there isnt anything in the text file? Give it a default city
If selectedcity = "" Then
selectedcity = "Auckland"
End If

We want to get two temperatures, the current temp from the internet, and
the old temp from before the update. This means you can tell if the temp
is going up or down.
If temperature <>"" Then if there is a temp then pass it to oldtemp
before getting a new temp
oldtemp = temperature
End If

strplace = selectedcity.ToLowerCase
townpath = "http://m.metservice.com/towns/"& strplace
'Just to show its updating make the temp in the label go away and make a
message show
rv.SetText("lbltemperature", "")
rv.SetText("lbltime", "Updating ...")
Update the widget
rv.UpdateWidget
req.InitializeGet(townpath)
hc.Execute(req, 1)
End Sub
Sub Service_Destroy
End Sub

Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int)


Dim temp As String
temp = Response.GetString("UTF8") 'Get the whole page

'Cut beginning and end to get the code for the temp itself
temp = temp.SubString(temp.IndexOf("<div class=" & QUOTE & "summary" &
QUOTE & ">")) 'cut to first occurrence of
temp = temp.SubString2(21, temp.IndexOf("</ul></div></div>")) 'find last
occurance of
temp = temp.Replace(QUOTE,"'") ' replace double with single quotes

'pull the city from the code


Dim city As String

Basic For Android Monday, 11 June 2012 Page 72


city = temp
'start at the 4th letter and end with the /h1
city = city.SubString2(4, city.IndexOf("</h1>"))

temperature = temp 'pull the temperature from the code


temperature = temperature.SubString(temperature.IndexOf("ul'><h2>"))
temperature = temperature.SubString2(8, temperature.IndexOf("<span "))

Dim shtemp As Short


shtemp = temperature
'get the difference between the old temp and the new temp
Dim updowntemp As Short
updowntemp = shtemp - oldtemp

'set the colors red = up blue = down white no change


Dim temptext As String
If updowntemp > 0 Then
temptext = " Up"
rv.SetTextColor("lbltemperature", Colors.RGB(255,204,225))
Else
temptext = " Down"
rv.SetTextColor("lbltemperature", Colors.RGB(141,197,224))
End If

If updowntemp = 0 Then
temptext = ""
rv.SetTextColor("lbltemperature", Colors.White)
End If

'remote view passes the data to the label


rv.SetText("lbltemperature", temperature)

pic = temp 'pull the pic from the code


pic = pic.SubString(pic.IndexOf("wx-icons/")) 'start position
pic = pic.SubString2(9, pic.IndexOf("' width")) ' 6 is the number from
counting the letters above
pic = pic.Trim

'looking for the image, is it already in the cache?


If File.Exists(File.DirInternalCache, pic) Then
'if so then load it, show the imgnext view and load an image into it
rv.SetVisible("imgnext", True)
rv.SetImage("imgnext", LoadBitmap(File.DirInternalCache, pic))
Else
Getimage 'otherwise go and get it from the net

Basic For Android Monday, 11 June 2012 Page 73


End If

Dim strtime As String 'pull the time from the code


strtime = temp
Dim timecolon As String
timecolon = strtime.IndexOf(":") 'find the colon between the time eg
11:23am
strtime = strtime.SubString2(timecolon -2, timecolon +5) 'take 2 off and
add 5 on to get the whole time 11:23am
rv.SetText("lbltime", strtime & CRLF & city & temptext)
rv.UpdateWidget
End Sub

Sub getimage
Dim imagepath As String 'this gets the image from the net
imagepath = "http://m.metservice.com/sites/all/themes/mobile/images/wx-
icons/"& pic
reqimage.InitializeGet(imagepath)
hcimage.Execute(reqimage, 1)
End Sub

Sub hcimage_ResponseSuccess(Response As HttpResponse, TaskId As Int)


Response.GetAsynchronously("ImageResponse", _
File.OpenOutput(File.DirInternalCache, pic, False), True, TaskId)
End Sub

Sub ImageResponse_StreamFinish (Success As Boolean, TaskId As Int)


If Success = False Then
Msgbox(LastException.Message, "Error")
Return
End If
rv.SetImage("imgnext", LoadBitmap(File.DirInternalCache, pic))
End Sub

Sub hcimage_ResponseError(Response As HttpResponse, Reason As String,


StatusCode As Int, TaskId As Int)

If Response <> Null Then


Msgbox("Error: " & Response.GetString("UTF8")& "Cannot find ", "Connection
Error")
Response.Release
ProgressDialogHide
ToastMessageShow("Image not loading",True)
End If
End Sub

Basic For Android Monday, 11 June 2012 Page 74


Sub hc_ResponseError(Response As HttpResponse, Reason As String,
StatusCode As Int, TaskId As Int)

If Response <> Null Then


Msgbox("Error: " & Response.GetString("UTF8")& "Cannot find ", "Connection
Error")
Response.Release
ProgressDialogHide
ToastMessageShow("bugger",True)
End If
End Sub

Basic For Android Monday, 11 June 2012 Page 75


Designing the Temperature Widget
This is a small layout so will be tricky to show. This is
a NEW LAYOUT. Not part of the existing one that the
Activity used.

It has 5 parts.

Pnlbg a transparent panel to space the widget out from the other widgets

Panel1 a visible graduated


panel

Imgnext a small imageview


to hold the pic

Lbltime holds time and City

Lbltemperature holds the


temperature.

Basic For Android Monday, 11 June 2012 Page 76


This is a white square behind the temperature that is curved like a circle, its hard to make
out unless you see the entire widget.

Basic For Android Monday, 11 June 2012 Page 77


Back on your phone click your menu button (bottom left blank space on mine and click on
Add. Then click on Widgets and drag onto the phone the one we have created.

Basic For Android Monday, 11 June 2012 Page 78


11. Project: Alarm scheduler sends
email to contacts
This program incorporates four main areas,

An alarm which is created with date and time.


The ability to extract your contacts list from your phone
The ability to send SMS messages
Working with Lists

Imagine you wanted to send a message to some people in your contacts list
at a set time every day. This program does that.

There are two Modules, a Main Activity module and a Service Module. The
main module sets up the program while the service module runs when the
alarm time equals the cell phone time.

'Activity module
Sub Process_Globals
Dim alarmHours, alarmMinutes As Int
Dim noti As Notification 'shows in the notification window
End Sub

Sub Globals
Dim SetTime As Button
Dim CancelAlarm As Button
Dim lvphone As ListView
Dim btnSavephone As Button

Dim Panel1 As Panel


Dim btnloadlist As Button
Dim edtmessage As EditText

Dim phonelist As List


Dim listOfContacts As List
End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("main")
getcontacts

listOfContacts.Initialize using a List


phonelist.Initialize
End Sub

Basic For Android Monday, 11 June 2012 Page 79


Date and Time
Main Sub to get the alarm time. (Note that Alarm isnt defined thats because I dont know
what type it is. It still works, just gives a nice red color).

Sub SetTime_Click
Dim td As TimeDialog 'the dialog from the dialog library
td.Hour = alarmHours
td.Minute = alarmMinutes
If td.Show("Select time to activate alarm", "", "Ok", "Cancel", "",
Null) = DialogResponse.POSITIVE Then
alarmHours = td.Hour
alarmMinutes = td.Minute

Dim today As Long


today = DateTime.DateParse(DateTime.Date(DateTime.Now)) 'Sets today at
12:00 AM
alarm = today + td.Hour * DateTime.TicksPerHour + td.Minute *
DateTime.TicksPerMinute
If alarm < DateTime.Now Then alarm = DateTime.Add(alarm, 0, 0, 1)

Log(DateTime.Date(alarm) & " " & DateTime.Time(alarm)) 'check the logs to


see the set date and time

'Calculate time to alarm


Dim h, m As Int
h = Floor((alarm - DateTime.Now) / DateTime.TicksPerHour)
m = ((alarm - DateTime.Now) - h * DateTime.TicksPerHour) /
DateTime.TicksPerMinute

ToastMessageShow("Alarm will start after: " & NumberFormat(h, 2, 0) & "


hour(s) and " & NumberFormat(m, 2, 0) & " minute(s)", True)

'You should schedule the next task with StartServiceAt.Android will


eventually kill your process if you use a timer. By scheduling the Next
task with StartServiceAt you make sure that a new process will be created
when the scheduled time arrives. This Is Not the Case with a regular
Timer.

StartServiceAt(AlarmService, (DateTime.Now+((h*60*60*1000)+(m*60*1000))),
True) ' Schedule AlarmService will start by add
time to DateTime.Now (note that Android use
millisecond)
This sets out the notification features that
appear on the notification front part of your
phone
noti.Initialize
noti.Light = True
noti.Vibrate = False

Basic For Android Monday, 11 June 2012 Page 80


noti.OnGoingEvent = True
noti.Sound = False
noti.Icon = "icon" set your own image if you want
noti.SetInfo("Alarm", "will start at " & DateTime.Date(alarm) & " " &
DateTime.Time(alarm), "")
noti.Notify(1) Displays the notification. Id This id can be used to later
update this notification (by calling Notify again with the same Id),
or to cancel the notification.
End If
End Sub
Turn off the alarm

Sub CancelAlarm_Click
noti.Cancel(1) This cancels the Notification number 1 set above
StopService(AlarmService)
CancelScheduledService(AlarmService)
End Sub
Main sub to get the contacts from the Phone I left the commented out section in case you
want to see whats happening, and grab them yourself

Sub getcontacts
Dim Contacts2 As Contacts2
listOfContacts = Contacts2.GetAll(True,False)

For i = 0 To listOfContacts.Size - 1
Dim Contact As Contact
Contact = listOfContacts.Get(i)
'Logging to check how it works can uncomment
Log(Contact) 'will print the fields to the LogCat
' Dim photo As Bitmap
' photo = Contact.GetPhoto
' If photo <> Null Then Activity.SetBackgroundImage(photo)
' Dim emails As Map
' emails = Contact.GetEmails
' If emails.Size > 0 Then Log("Email addresses: " & emails)
' Dim phones As Map
' phones = Contact.GetPhones
' If phones.Size > 0 Then Log("Phone numbers: " & phones)

If Contact.PhoneNumber <>"" Then If there is a contact number pass it to


the listview so you can see it

lvphone.SingleLineLayout.Label.TextSize = 15
lvphone.SingleLineLayout.ItemHeight = 40
lvphone.AddSingleLine(Contact.DisplayName &": " &Contact.PhoneNumber)
lvphone.ScrollingBackgroundColor =Colors.DarkGray
End If
Next
Basic For Android Monday, 11 June 2012 Page 81
End Sub

This is the click event on the listview. We want to take the value that we click on (the name
and phone number) and add it to our Phonelist as a List object.

Sub lvphone_ItemClick (Position As Int, Value As Object)


pass the value to details and then save it to the phone list. Might be
able to bypass all this and just go phonelist.Add(Value)
Dim details As String
details = Value
Activity.Title = details Show the name at the top as a check
Log(details) Show the name in the logs as a check
phonelist.Add(details)
End Sub

Write to a file
The button save click saves two parts, the message that you want sent, and the phone list
that you have created. These text files are then opened and used by the service when the
alarm is activated.

Note the easy File.WriteString(File.DirInternal, "message.txt", edtmessage.text) structure.


Of Filename "message.txt" and Content. edtmessage.text.

Sub btnSavephone_Click
Check to see if a message has been written and a list has been made
If edtmessage.text <>"" AND phonelist.Size >0 Then
Write the message and list to files to be accessed later
File.WriteString(File.DirInternal, "message.txt", edtmessage.text)
File.WriteList(File.DirInternal, "phonelist.txt", phonelist)
ToastMessageShow("List saved", False)
lvphone.Clear clear the listview screen ready to show its saved
Else
bozo notification
ToastMessageShow("Save a list and write a message first", True)
End If
End Sub

Read from a file to a list


This button allows you to load the list you made to check that its the correct people in it.
This shows how easy a list is to use as well.

Sub btnloadlist_Click
Dim list1 As List
quit if no phonelist (If statements dont need an endif they are only on
one line.)
If File.Exists(File.DirInternal, "phonelist.txt") = False Then Return

Basic For Android Monday, 11 June 2012 Page 82


pass the data to the list
list1 = File.Readlist(File.DirInternal, "phonelist.txt")
Here is the data being looped into the list
Dim j As Int
j = list1.Size make J the size of the list
If j < 0 Then Return
For i = 0 To j-1 add each item to the listview
lvphone.AddSingleLine(list1.Get(i))
Next
End Sub

'Service module
Sub Process_Globals
Dim mp As MediaPlayer ' You need to declare mp as Mediaplayer
Dim noti As Notification make a new notification
End Sub

Sub Service_Create
End Sub

Sending an SMS
In this module the heart is Sms.Send(phonelist, messagetext) which is commented out
so you dont lose all your friends while building it.

Sub Service_Start
mp.Initialize() 'Initialize Mediaplayer
PlayAlarm run the play alarm sub
ToastMessageShow("Emails sent", True) emails sent

'LOAD LIST
Dim list1 As List
Dim messagetext As String
Dim j As Int
Dim phonelist As String
If File.Exists(File.DirInternal, "phonelist.txt") = False Then Return
list1 = File.Readlist(File.DirInternal, "phonelist.txt")

note this is ReadString as its only one word not a list


If File.Exists(File.DirInternal, "message.txt") = False Then Return
messagetext = File.ReadString(File.DirInternal, "message.txt")

j = list1.Size
If j < 0 Then Return
For i = 0 To j-1
the phone list consists of Name: number we only want number to send the
message (although we could use the name in the message field if were
Basic For Android Monday, 11 June 2012 Page 83
wanted). So we have to do our chopping the string at : to get the number
from it
phonelist = list1.Get(i)
phonelist = phonelist.SubString2(phonelist.IndexOf(":")+2,
phonelist.Length)
Log(phonelist) check to see it working
ToastMessageShow(list1.Get(i)&" " & phonelist & " " & messagetext, False)

Dim Sms As PhoneSms


Dim number As PhoneId
Dim senttext As String
'Send (PhoneNumber As String, Text As String)
'Sms.Send(phonelist, messagetext)
Next

noti.Initialize
noti.SetInfo("message sent",messagetext,"")
End Sub
End the Service

Sub Service_Destroy
StopService("") 'Stop this service
CancelScheduledService("") 'Cancel this service
End Sub
Play the alarm

Sub PlayAlarm
mp.Load(File.DirAssets, "sound.wav")
mp.Play
End Sub

Basic For Android Monday, 11 June 2012 Page 84


12. Project: Text to Speech Program
The beauty of this simple little program is not in its novelty value, but that it can be added to
any other program to add functionality and make a point of difference. Imagine you add it to
your Weather Widget, or your GPS locator, so that people can just click on the program and
hear the temperature and location without taking their eyes off the road.

As well it could be the heart of a program for disabled people, and later we will use it to read
emails as well.

Note that the text read is held in the edttext.text field, which
means that any strings can be read as well.

Sub Process_Globals
Dim TTS1 As TTS
End Sub

Sub Globals
Dim barPitch As SeekBar
Dim barSpeechRate As SeekBar
Dim btnSpeak As Button
Dim EditText1 As EditText
Dim spnrLanguages As Spinner
End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("1")
spnrLanguages.AddAll(Array As String("en", "fr", "de"))

'As TTS doesn't support the volume control - you can't


change the volume - you need to use Reflector to get the
Music volume, which is louder I suppose, and use that
instead.
Dim r As Reflector
r.Target = r.GetActivity
r.RunMethod2("setVolumeControlStream", 3,
"java.lang.int")

End Sub

Sub TTS1_Ready (Success As Boolean)


If Success Then
'enable all views
For i = 0 To Activity.NumberOfViews - 1

Basic For Android Monday, 11 June 2012 Page 85


Activity.GetView(i).Enabled = True
Next
btnSpeak_Click 'play first sentence
Else
Msgbox("Error initializing TTS engine.", "")
End If
End Sub

Sub Activity_Resume
If TTS1.IsInitialized = False Then
TTS1.Initialize("TTS1")
End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)


TTS1.Release
End Sub

Sub btnSpeak_Click
If EditText1.Text.Length > 0 Then
TTS1.Speak(EditText1.Text, True)
EditText1.SelectAll
End If
End Sub

Sub barSpeechRate_ValueChanged (Value As Int, UserChanged As Boolean)


If UserChanged Then
TTS1.SpeechRate = Value / 10
End If
End Sub

Sub barPitch_ValueChanged (Value As Int, UserChanged As Boolean)


If UserChanged Then
TTS1.Pitch = Value / 10
End If
End Sub

Sub spnrLanguages_ItemClick (Position As Int, Value As Object)


If btnSpeak.Enabled = False Then Return
If TTS1.SetLanguage(Value, "") = False Then
ToastMessageShow("Language data not found.", True)

Basic For Android Monday, 11 June 2012 Page 86


Return
End If
End Sub

Text to speech stripped for other programs


Here is the stripped down version that you can just drop into your programs. Dont forget to
add the TTS library.

It doesnt have to come off the button click, thats just an example.

Dim TTS1 As TTS

Sub Activity_Resume
If TTS1.IsInitialized = False Then
TTS1.Initialize("TTS1")
TTS1.SetLanguage("en","")
End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)


TTS1.Release
End Sub

Sub Button1_Click
If .yourtext.Text.Length > 0 Then
TTS1.Speak(yourtext.Text, True)
End If
End Sub

Basic For Android Monday, 11 June 2012 Page 87


13. Project: Capture all SMS messages entering your
phone
Imagine that when a text message came into your phone that you didnt have to stop what
you are doing and have to look to see who sent it. Maybe you are driving, working, or busy
elsewhere and want to know if its important or not.

Thats what this program does. It tells you who sent the text message so you can decide if
you need to reply immediately. This is based on the previous lessons and looks at a few of
the many features of the phone you can use in programming.

When a text message comes in the number it comes from is checked against the contacts
list in your phone. If a match is made then it speaks out the name of the person in the
contact list.

For this to work you need to have the Phone library 1.8 installed. To do that
download it from B4A website, and put it into the internal library folder, not the
usual external one. The internal folder is usually at C:\Program Files\Anywhere
Software\Basic4android\Libraries

If you have a Phone library in the external library then you need to delete it as it will
overwrite the internal Phone Library.

Logs and Toastmessageshow are crucial to debugging


Debugging is crucially important and especially so in this exercise. I have used copious
amounts of Logs and Toastmessageshow to see what is happening in the code. What is the
number coming in? How does it change when you strip it? Does it match up with the
contacts? What happens next etc.

You need to do this as well. Debugging IS coding. Not just following this exercise.

Basic For Android Monday, 11 June 2012 Page 88


Working with Service and Activity Modules
This project has 2 main parts. An Activity Module (Main) that
holds the code for the screen above, and a Service Module
(sms) that runs all the time and listens for incoming text
messages. Another Activity module smstext holds a data file,
but its not important

I think of the Activity Module (main). as my test bed, I get the Activity module working first,
and then when its all OK I make the Service Module (sms). Thats because its easier to
think and code in the activity module and to see what you are doing and you can have
sample test data.

In this exercise I copied all the working code from the Activity Module to the Service module,
did final changes and moved the changed code back in to the Activity Module to check it.

Saving and Reading to files


When working with a Service module you need to pass data to it from the Activity module
using text files. So if you make a setting in your activity module, you have to save it as a text
file then upload it into the service module. That way the settings are saved when you turn off
your program and only the service is running.

Saving and reading from text files is really easy, and I use it throughout the code.

Here for example is data held in the details variable being written to a file "from.txt"

From = File.WriteString(File.DirInternal, "from.txt",details)

And here is the data from that "from.txt" file being passed back into the From variable.

From = File.ReadString(File.DirInternal, "from.txt")

Its fast and easy.

The Activity (main) code


'Activity module
Sub Process_Globals
Dim TTS1 As TTS 'text to speech
End Sub

Sub Globals
Dim lvphone As ListView 'the listview holding the contacts
Dim edtmessage As EditText 'messagebox that holds the phone number
Dim Panel1 As Panel ' background panel
Dim Button1 As Button ' the Simulator run button
Dim listOfContacts As List 'holds the contacts list
Dim btnservicestart As Button ' start the service button
Dim btnservicestop As Button 'stop the service button
End Sub

Basic For Android Monday, 11 June 2012 Page 89


Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("main") ' load the main layout
StartService(Sms)

If TTS1.IsInitialized = False Then ' turn on text to speech and set the
language
TTS1.Initialize("TTS1")
TTS1.SetLanguage("en","")
End If

getcontacts ' load the contacts into the listview


End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)


End Sub

Sub MessageReceived (From As String, Body As String) As Boolean


Msgbox("From " & From & " Text " & Body, "Title")
End Sub

'this sumulates a text arriving


Sub Button1_Click
smscopy ' copy of the sms activity code modified for the activity runs
End Sub

'fills the listview with the data from the contact list
Sub getcontacts
'Create a Contacts to hold the contacts from your phone. Contacts2 object
allows you to access the device stored contacts. This type is based on a
new API supported by Android 2.0 and above.This type supersedes Contacts
type.
Dim Contacts2 As Contacts2
'pass the contacts to a list to hold them. Note that each contact has
about 6 or so fields, that at the moment you can't get to
listOfContacts = Contacts2.GetAll(True,False)

'loop through each of the contacts in your new list


For i = 0 To listOfContacts.Size - 1
'for each contact pass it to the Contact object. This object allows you to
extract out each field held in filed, so you can use Contact.phonenumber
and Contact.DisplayName as well as many others.

Basic For Android Monday, 11 June 2012 Page 90


Dim Contact As Contact
Contact = listOfContacts.Get(i)
'Logging to check how it works
Log(Contact) 'will print the fields to the LogCat

'We don't want contacts who don't have a phone number or contacts with
short number such as your phone provider. A 3 digit number will screw with
the next part of the code where we cut the beginning off.
If Contact.phonenumber <>"" AND Contact.phonenumber.Length > 7 Then

'show the name and number from the contacts list in your listview and
format it up to make it easy to read
lvphone.SingleLineLayout.Label.TextSize = 15
lvphone.SingleLineLayout.Label.TextColor = Colors.Black
lvphone.SingleLineLayout.ItemHeight = 40
lvphone.ScrollingBackgroundColor =Colors.Transparent
'data goes in here the name and number separated by a :, this is what we
use to get the name out later.
lvphone.AddSingleLine(Contact.DisplayName &": " & Contact.phonenumber)

End If
Next
End Sub

Clicking on the listview

Sub lvphone_ItemClick (Position As Int, Value As Object)


'strip out the name and leave the number and write it to the FROM text
file. its broken out at the :
Dim details As String
details = Value
details = details.SubString2(details.IndexOf(":")+2, details.Length)
'write the number in the text box
edtmessage.text = details
'write the number to the from.txt file
File.WriteString(File.DirInternal, "from.txt",details)
End Sub

Sub btnservicestop_Click
StopService(Sms) ' stop the service running (turn it off)
End Sub
Sub btnservicestart_Click
StartService(Sms) ' start the service running (turn it on)
End Sub

Basic For Android Monday, 11 June 2012 Page 91


'I called this smscopy as its a copy of the sms main code
Sub smscopy
'this reads the file in from the from.txt. in the sms code it comes in via
the sms message
Dim From As String
From = File.ReadString(File.DirInternal, "from.txt")

'logs and toastmessages to see what is happening


ToastMessageShow("Text from " & From, True)
Log ("From before cut" & From)

'strips out the first numbers of the incoming phone number. The number
coming into the phone can have different prefixes on it to the one stored
in the phone. eg: number in is always 642.. country code and cellphone,
but the number in the contacts can be just cellphone 027.. we need to make
both equal. So stripping out the first numbers down to 7 digits fixes
this. Thats why empty entries and ones with 3 numbers are blocked earlier,
it crashes here. (took me hours to work out).

' From.Length-7 find the length of the number eg: 11, take of 7 and = 4,
so start number for the substring is 4.

'SubString2(startnumber, to end number)


From = From.SubString2(From.Length-7, From.Length)
'show me the chopped number as a check
ToastMessageShow("Chopped from " & From, True)

'same code as above getting the contacts2 list, passing it to a


listofcontacts and a contacts object to extract out the name and number.

Dim listOfContacts As List


Dim Contacts2 As Contacts2
listOfContacts = Contacts2.GetAll(True,False)

For i = 0 To listOfContacts.Size - 1
Dim Contact As Contact
Contact = listOfContacts.Get(i)

'just to see what the counter is doing


Log(i)

Dim phonenumber As String


Dim startphone, endphone As Int

If Contact.phonenumber <>"" AND Contact.phonenumber.Length > 8 Then

Basic For Android Monday, 11 June 2012 Page 92


'this strips out the first numbers of the phone list. its the same as we
did above but I broke it down into its component parts to make it easier
for you to read
phonenumber = Contact.phonenumber
startphone = phonenumber.Length-7
endphone = phonenumber.Length
phonenumber = phonenumber.SubString2(startphone,endphone)
Log ("From after the cut" & From)

If From = phonenumber Then


'a whole bunch of testing going on
' ToastMessageShow("PH " & phonenumber & " From " & From, True)
Log("PH " & phonenumber & " From after cut " & From)
ToastMessageShow("Incoming text from " & Contact.Name, True)

'text to speech finally working


TTS1.Speak("Text from " & Contact.Name, True)

'this text file holds the name and message, it will go on the widget so
you can read it
File.WriteString(File.DirInternal, "body.txt","From " & Contact.Name &"
This is a test message, Its a really long one, I hope you can read it
all")

Else

'ToastMessageShow("No matching contact", True)


Log("PH " & phonenumber & " From after cut " & From)

End If
End If

Next

End Sub

Basic For Android Monday, 11 June 2012 Page 93


Code for the Service Activity(sms)
'Service module
Sub Process_Globals
Dim SI As SmsInterceptor
Dim TTS1 As TTS
'remote view for the widget RV is how the widget communicates with the
service and visa versa as we don't DIM or pass variables
Dim rv As RemoteViews
End Sub

Sub Service_Create
'starting the service in the foreground means it won't get killed by the
Android system - it stays alive
Service.StartForeground(1,"SMSInterceptor running")
'You intercept SMS messages and prevent the messages from being handled by
the default messaging application by initializing SmsInterceptor with
Initialize2 AND setting the Priority parameter To 999 (highest application
priority For Intent filters).

'This then handles the Sub SI_MessageReceived part


SI.Initialize2("SI", 999)
'make sure text to speech is initialised and set the details
If TTS1.IsInitialized = False Then
TTS1.Initialize("TTS1")
TTS1.SetLanguage("en","")'language
End If
Log("Service initialized")

'Widget name - the name that will appear in the widgets List.
rv = ConfigureHomeWidget("smslayout", "rv", 0, "SMS Inteceptor")
End Sub

Sub Service_Start (StartingIntent As Intent)


'setting out the notification features of the phone
Dim noti As Notification 'shows in the notification window
noti.Initialize
noti.Icon = "icon"
'noti.Notify(1)
noti.Sound=False
noti.Vibrate = False
noti.Light = False
'this runs the next Activity (smstext)
noti.SetInfo("SMS Interceptor","Running", "smstext")
Service.StartForeground(1, noti)
ToastMessageShow("SMS inteceptor has started", False)

Basic For Android Monday, 11 June 2012 Page 94


'This code checks the Intent message that caused this service to start in
this case the text message recieved and is responsible for raising the
events related to the widget. It returns true if an event was raised.
If rv.HandleWidgetEvents(StartingIntent) Then Return
End Sub

Sub Service_Destroy
SI.StopListening()
Service.StopForeground(1)
ToastMessageShow("SMS inteceptor has stopped", False)
End Sub

'The heart of the program


Sub SI_MessageReceived (From As String, Body As String) As Boolean
'Body and From are the two parts of the text message that are passed into
the phone from the incoming sms

ToastMessageShow("Text from " & From, True)


Log ("From before cut" & From)

'strips out the first numbers of the incoming phone number


From = From.SubString2(From.Length-7, From.Length)
'ToastMessageShow("Chopped from " & From, True)

Dim listOfContacts As List


Dim Contacts2 As Contacts2
listOfContacts = Contacts2.GetAll(True,False)

For i = 0 To listOfContacts.Size - 1
Dim Contact As Contact
Contact = listOfContacts.Get(i)

'this strips out the first numbers of the phone list


Dim phonenumber As String
Dim startphone, endphone As Int

If Contact.phonenumber <>"" AND Contact.phonenumber.Length > 8 Then

phonenumber = Contact.phonenumber
startphone = phonenumber.Length-7
endphone = phonenumber.Length
phonenumber = phonenumber.SubString2(startphone,endphone)
Log ("From after the cut" & From)

'write a file to open with the widget

Basic For Android Monday, 11 June 2012 Page 95


File.WriteString(File.DirInternal, "body.txt","From " & From & " " & Body)

If From = phonenumber Then


' ToastMessageShow("PH " & phonenumber & " From " & From, True)
Log("PH " & phonenumber & " From after cut " & From)
ToastMessageShow("Incoming text from " & Contact.Name, True)
TTS1.Speak("Text from " & Contact.Name, True)
File.WriteString(File.DirInternal, "body.txt","From " & Contact.Name & " "
& Body)

Else

'ToastMessageShow("No matching contact", True)


Log("PH " & phonenumber & " From after cut " & From)

End If
End If

Next
updateTheWidget
End Sub

'this loads the widget with the updated information


Sub updateTheWidget
Dim message As String
message = File.ReadString(File.DirInternal, "body.txt")
If message <>"" Then
show the message on the lbltext on the widget
rv.SetText("lbltext", message)
Else
rv.SetText("lbltext", "No message")
End If
'update the widget action
rv.updatewidget
End Sub
'click on the panel to update the widget
Sub pnlcolor_click
updatewidgettext
End Sub

Sub updatewidgettext
rv.SetText("lbltext","Working ...")

ToastMessageShow("Click event on lblclick?", True)


Dim message As String

Basic For Android Monday, 11 June 2012 Page 96


message = File.ReadString(File.DirInternal, "body.txt")
If message <>"" Then
show the message on the lbltext on the widget
rv.SetText("lbltext", message)
Else
rv.SetText("lbltext", "No message")
End If
rv.updatewidget
End Sub

Sub rv_RequestUpdate
rv.updatewidget
End Sub
Sub rv_Disabled
StopService("")
End Sub

The Activity(smstest)
This activity is just a tacked on piece, its working code but I think it might be better used
elsewhere. What I was trying to do is when a message is received and the Notification is
activated a text is placed in the Notification window.

This is loaded in with the code from the Service

'this runs the next Activity (smstext)


noti.SetInfo("SMS Interceptor","Running", "smstext")

If we want to see what the message is then we can click on the notification and it will run the
"smstext" activity which loads the messagebox with the message.

Basic For Android Monday, 11 June 2012 Page 97


Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)


If File.Exists(File.DirInternal, "body.txt") = False Then
ToastMessageShow("No message", False)
Else
Dim message As String

message = File.ReadString(File.DirInternal, "body.txt")


Msgbox(message, "latest message")
End If
Activity.Finish
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)


End Sub

Designing the Widget


This widget is almost exactly the same as the last widget we made.

We have the following

Pnlbg transparent background panel


Pnlcolor color panel with curved corners
Lbltext holds the text of the message
IVimage holds the icon.

Basic For Android Monday, 11 June 2012 Page 98


14. Project: Voice Recognition program
This simple little program is easy to create and can add variety and value to your Android
programs.

All it requires is a layout with a button on it. The VR program generates its own interface.
The button doesnt have to be as big as it is it does not affect the VR layout.

We will use this program later back in our last program to allow you to talk in commands to
create text messages mostly by just adding this entire activity as a new activity to the
program.

Designer Running

Google VR Program runs generating


its own interface

Basic For Android Monday, 11 June 2012 Page 99


'Activity module

Sub Process_Globals
Dim VR As VoiceRecognition
Dim TTS1 As TTS
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)


If FirstTime Then
VR.Initialize("VR")
TTS1.Initialize("TTS1")
End If

'load the layout named 1 (just a button)


Activity.LoadLayout("1")

'tells the user if they can use voice recognition


If VR.IsSupported Then
ToastMessageShow("Voice recognition is supported.", False)
Else
ToastMessageShow("Voice recognition is not supported.", True)
End If
'just a text message on the program neat the top
VR.Prompt = "Say your message"
End Sub

Sub Button1_Click
VR.Listen 'calls the voice recognition external activity
End Sub

Sub VR_Result (Success As Boolean, Texts As List)


'Texts is a list object, the VR program creates a list of potential
phrases it hears ie: You say "Today is hot" it lists "Today is not",
"Today is snot" "Today is a lot" etc, then lists it in order of preference
and at Texts.Get(0)gives the most likely choice "Today is Hot".
If Success = True Then
ToastMessageShow(Texts.Get(0), True)
TTS1.Speak(Texts.Get(0), True)
End If
End Sub

Basic For Android Monday, 11 June 2012 Page 100


15. Project: Voice recognition in SMS messages
program.
The addition of voice recognition is actually pretty easy. Rather than writing the code from
scratch and embedding it into the existing program I merely copy it over to a new activity
and then connected it through via the click on the widget icon that loads a button.

First of all lets get it working in your testbed the Main Activity then when all the
bugs are ironed out make a link in your Service (SMS) Module.

Create a transparent layout a floating button


We need a layout for the button to be clicked to activate the voice recognition. Its only one
button on a Layout. The new layout is called Voice.

Go to the manifest Editor Project / manifest Editor

In the manifest editor add the line to the bottom. (Its all one line except for the comment)

'The line below needs to be added to make the activity transparent


SetActivityAttribute(voice1, android:theme,
@android:style/Theme.Translucent.NoTitleBar)
Voice1 is the name of the new Activity we will make, not the name of the layout.

Basic For Android Monday, 11 June 2012 Page 101


When activated the button will appear to float over the top of the window, but in reality it just
has a transparent background.

At this stage we cant test it and see, you will just have to trust me.

Basic For Android Monday, 11 June 2012 Page 102


The Voice Recognition Activity Module
Back in the program go Project / Add New Module / Activity Module. Then create new
Activity Module named Voice1.

This activity module is a copy of the earlier exercise with added sections. The two new parts
are Sub smstextready which loads the SMS reply window ready for a message and Sub
readtext that reads back the incoming SMS message.

'Activity module
Sub Process_Globals
Dim vr As VoiceRecognition ' first time
Dim vrtext As VoiceRecognition ' for message
Dim TTS1 As TTS
End Sub

Sub Globals
'if people get it wrong, lets insult them.
Dim insult As Int :insult = 0
End Sub

Sub Activity_Create(FirstTime As Boolean)

If FirstTime Then
vr.Initialize("VR")
vrtext.Initialize("VR")
TTS1.Initialize("TTS1")
End If
'loading the layout we use with the button on it.
Activity.LoadLayout("voice")
Activity.Color = Colors.Transparent 'Make the Activity transparent
If vr.IsSupported Then
ToastMessageShow("Voice recognition is supported.", False)
Else
ToastMessageShow("Voice recognition is not supported.", True)
End If
End Sub

Sub Button1_Click
vr.Listen 'calls the voice recognition external activity
End Sub

Basic For Android Monday, 11 June 2012 Page 103


Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)


End Sub

In the next section I used message.Contains("reply") which meant that it parses the text
looking for the word reply. This can be used to detect accents as well. Read can be Reed,
or Red etc. Surprisingly it is Case Sensitive, and will not return if you make the words
capital case (well not for me anyway).

This system could be expanded for any number of keywords or phrases. Even to loading an
SMS with a nickname for a person The Old Trout for your Mother in law. Nicknames could
be kept in a database attached to the contacts list.

This part insult = Rnd(1,5) gives a random number between 1 and 5 not including 5.

Sub VR_Result (Success As Boolean, Texts As List)


If Success = True Then
ToastMessageShow(Texts.Get(0), True)
TTS1.Speak(Texts.Get(0), True)

Dim message As String


message = Texts.Get(0)

'if the person says ... then


If message.Contains("reply") Then
smstextready
Else If message.Contains("read")OR message.Contains("reed") OR
message.Contains("red")Then
readtext
Else
'random insult until they get it
insult = Rnd(1,5)

Select insult
Case 1
TTS1.Speak("Please speak clearer. Are you drunk?", True)
Case 2
TTS1.Speak("Don't take drugs and operate a phone. Try again", True)
Case 3
TTS1.Speak("Your breath smells of onions. Please move the phone away
before trying again", True)
Basic For Android Monday, 11 June 2012 Page 104
Case 4
TTS1.Speak("Please don't gargle and talk at the same time. Spit it out
first then try again", True)
End Select
End If
End If
End Sub

In this section we get into the heart of the program. We load 2 text files, which we will have
to make later fromsms.txt and contactname.txt.

Note the If File.Exists(File.DirInternal, which is used to check that there is a file there to
start with. The first time its used there wont be one and the program will crash, its a good
bit of protection.

The Dim i As Intent i.Initialize(i.ACTION_VIEW, "sms:" & number) is part for creating and
accessing an Intent, opening the SMS reply window which is another program. You use
Intents to open other programs on your phone. The action we are going to perform is VIEW
adding the number.

'OPEN THE REPLY WINDOW AND FILL THE NAME


Sub smstextready
Dim number, name As String
'get the smsnumber from the from file for the txtreply part of the program
its the raw phone number
If File.Exists(File.DirInternal, "fromsms.txt")Then
number = File.ReadString(File.DirInternal, "fromsms.txt")
Else
number = File.ReadString(File.DirInternal, "from.txt")
End If

'get the name of the person to send it to and put it in the bar
If File.Exists(File.DirInternal, "contactname.txt")Then
name = File.ReadString(File.DirInternal, "contactname.txt")
Else 'you know you have a mistake when you want to call Howard
name = "Howard the Duck"
End If

Dim i As Intent
'set up the sms window with voodoo
i.Initialize(i.ACTION_VIEW, "sms:" & number)
'put the text into the body

TTS1.Speak("message ready", False)


i.PutExtra("sms_body", "")

Basic For Android Monday, 11 June 2012 Page 105


'start it
StartActivity(i)
End Sub

'READ THE TEXT


Sub readtext
Dim message As String
message = File.ReadString(File.DirInternal, "body.txt")
TTS1.Speak(message, False)
End Sub

Finally we need to create the text files. Back in your Service Module (SMS) Find the
following areas and add the code. We save to a text file to get it back later.

Add File.WriteString(File.DirInternal, "Fromsms.txt",From) here.

'The heart of the program


Sub SI_MessageReceived (From As String, Body As String) As Boolean
'Body and From are the two parts of the text message that are passed into
the phone. write a file to open with the new text in txtreply on voice1
File.WriteString(File.DirInternal, "Fromsms.txt",From)

The contact name for the reply comes under the Sub SI_MessageReceived sub below If
From = phonenumber.

If From = phonenumber Then


File.WriteString(File.DirInternal, "contactname.txt",Contact.Name)

Finally we need a way to start the Voice1 Activity. We are going to do that off the click on
the image the heart is StartActivity("voice1")

Sub ivimage_click
TTS1.speak("Press the Button. Then say Read or Reply", False)
StartActivity("voice1")

End Sub

Basic For Android Monday, 11 June 2012 Page 106


16. Maps Hashmap for Java, Hashtables for .net
Map is a structure that is used frequently in Java. Its listed as an advanced tool but it is very
versatile and useful.

A Map consists of two parts a KEY and a VALUE pair. The key is unique, while the value
can be anything. KEY VALUE are separated by a colon : If you enter a key/value pair and
the collection already holds an entry with the same key, the previous entry will be removed
from the map so it overwrites existing entries.

The idea is to look down the Key field for what you are seeking and take the data from the
value field. This is far faster than looping through all the entries in the ordinary way.

Fetching an item is done by looking for its key. This is usually a very fast operation (O(1)
compared to O(n) in a list).

The key could be a string or a number. The value can be any type of object. Eg:

Lists Phone numbers Date and Time


1:chocolate 345456:Susan 21/2/12-10.32am:meeting
2:apple 545678:Harvey 21/2/12-11.15am:Break
3:orange 434565:Harold 21/2/12-12.00pm:Lunch

Add data to your map with Put

Map1.Put("Key","Value")

Get keys and values back with Map.GetKeyAt(i)) and Map.GetValueAt(i)).and check if the
key exists then get it with If Map.ContainsKey("some key") Then ...

Data has to be looped in and out of a map.

For example

For i = 0 to Map.Size - 1
Log("Key: " & Map.GetKeyAt(i))
Log("Value: " & Map.GetValueAt(i))
Next

Or as we will do later insert the Map into other loops.

For x = 0 To phones.Size 1
mastermapnames.Put(PhoneNum,Contact.DisplayName)
Next

You can have Maps of Maps and Lists of Maps.


Basic For Android Monday, 11 June 2012 Page 107
Here is a good example of saving and retrieving data from two text boxes using a map.

17. Use Map to save multiple data to a single file


Imagine you wanted to save all the text in a range of text boxes to a single file and then load
it back into the program later. It might be an edit option for long text entering, or an offline
option, or even to save a range of drafts. Its actually really easy to do with Maps

This very handy tool is easy to follow and uses PUT to save, and GET to retrieve.

The extra window shows the text file as saved and automatically saves with a data stamp.
This could create options for calling up versions.

Sub Globals
Dim map1 As Map
map1.Initialize
Dim btnsave As Button
Dim EditText1 As EditText
Dim EditText2 As EditText
Dim btnload As Button
Dim EditText3 As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("main")
End Sub

Sub btnsave_Click
map1.Clear'clear the map, empty the data
'put the data in the map (KEY, VALUE)
map1.Put("EditText1", EditText1.Text)
map1.Put("EditText2", EditText2.Text)
File.WriteMap(File.DirInternal, "btnset.set", map1) 'write to file
EditText1.Text = ""'clear text boxes
EditText2.Text = ""
ToastMessageShow("data saved", False)
End Sub
Sub btnload_Click
'load back to map1 as a map (file.Readmap)
map1 = File.ReadMap(File.DirInternal, "btnset.set")
'show back in text boxes
EditText1.Text = map1.Get("EditText1")
EditText2.Text = map1.Get("EditText2")
ToastMessageShow("data loaded", False)
'show the datafile as saved for interest
EditText3.text = File.ReadString(File.DirInternal, "btnset.set")
Basic For Android Monday, 11 June 2012 Page 108
End Sub

18. Project: Recipe selector using JSON


Get an API from this site http://www.programmableweb.com/ to practise on and to see
whats available.

JSON Overview
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for
humans to read and write. It is easy for machines to parse and generate. It is a popular way
of transferring related data from internet databases to applications, and preferred by
Google. The ability to use JSON opens a vast area of data manipulation.

JSON is built on two structures:

A collection of name/value pairs. In various languages, this is realized as an object, a


map, struct, dictionary, hash table, keyed list, or associative array.

An ordered list of values. In most languages, this is realized as an array, vector, list,
or sequence.

An object is an unordered set of name/value pairs. An object begins with { (left brace) and
ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are
separated by , (comma).

An array is an ordered collection of values. An array begins with [ (left bracket) and ends
with ] (right bracket). Values are separated by , (comma).

A value can be a string in double quotes, or a number, or true or false or null, or an object or
an array. These structures can be nested.

Here is a request to a server for some data that is returned in the JSON format.
http://www.recipepuppy.com/api/?i=onions,garlic&q=omelet&p=3

The data that is returned is in a string, to see the structure of it paste the link into
http://jsonformat.com/ and run.

Basic For Android Monday, 11 June 2012 Page 109


A good overview can be found on the Wikipedia http://en.wikipedia.org/wiki/Json

The structure is nested. Here is the first set of data returned, with the end added on to make
it a single unit. Subsequent sets have the same structure.

{"title":"Recipe Puppy","version":0.1,
"href":"http:\/\/www.recipepuppy.com\/",
"results":
[{
"title":"Vegetable-Pasta Oven Omelet",
"href":"http:\/\/find.myrecipes.com\/recipes\/recipefinder.dyn?action=disp
layRecipe&recipe_id=520763",
"ingredients":"tomato, onions, red pepper, garlic, olive oil, zucchini,
cream cheese, vermicelli, eggs, parmesan cheese, milk, italian seasoning,
salt, black pepper",
"thumbnail":"http:\/\/img.recipepuppy.com\/560556.jpg"}, }
],}

This data looks confusing on the first look, and the second, and the .

However look at the main text in terms of Maps. A Map is a Key:Value pair separated by a :
and this data is make up of maps with each map separated by a comma,

"title":"Vegetable-Pasta Oven Omelet"

Its the format of Key:Value , Key:Value , Key:Value , Key:Value , Key:Value ,

This is an array of maps

The main part the data

"results":
[{
Is again Key:Value, the Key being Result, the Value being everything inside of the [{

The next page gives a better idea of the structure using a Firefox addon below. You can
clearly see the Blue Green matched Key Value pairs

Basic For Android Monday, 11 June 2012 Page 110


Recipe Program construction
This program requires us to access the net and download the JSON from the
http://www.recipepuppy.com website using their API (Application programming interface).
As a result we need the HTTP library.

We need

1 panel

2 Buttons

3 Labels

2 edit boxes

1 imageview

Edtcode is only to see if the


code is coming down OK

LBLhyperlink and IVpic are


not set up so far, the pic will
go in the pic box and the
hyperlink will take you to the
website.

Basic For Android Monday, 11 June 2012 Page 111


The code

'Activity module
Sub Process_Globals
Dim hc As HttpClient 'download the json
Dim req As HttpRequest
Dim JSON As JSONParser
Dim Map1 As Map
End Sub

Sub Globals
Dim btnrun As Button
Dim datamap As Map
Dim btnnext As Button
Dim edtsearch, edtcode As EditText
Dim lblhyperlink,lblingredients, lbltitle As Label
Dim counter As Int :counter = 0
Dim ivpic As ImageView
Dim recipecode As String
End Sub

Sub Activity_Create(FirstTime As Boolean)


Activity.LoadLayout("main")
hc.Initialize("hc")
datamap.Initialize
'set as a default to save typing in all the time while testing
edtsearch.Text = "i=onions,garlic&q=omelet&p=3"
'initialise the JSON and tells it what it has to parse
JSON.Initialize(recipecode)
End Sub

Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub btnrun_Click
Dim url, search As String
search = edtsearch.Text
url = "http://www.recipepuppy.com/api/?"& search
'i=onions,garlic&q=omelet&p=3"
'OPTIONS
'i=ingredients comma deliminated
'q=type of food eg omelet
Basic For Android Monday, 11 June 2012 Page 112
'p= page number? -put page number in a counter so that it increments each
time you press run? 1, 2, 3 still to do
req.InitializeGet(url)
hc.Execute(req, 1)
ProgressDialogShow("downloading ...")
End Sub

Sub hc_ResponseSuccess(Response As HttpResponse, TaskId As Int)


Dim temp As String
temp = Response.GetString("UTF8") 'Get the whole page
recipecode = temp
edtcode.text = temp Just to see what the code is on the screen
ProgressDialogHide
'run the download sub below (gets the first entry up and running)
download
counter = 0
End Sub
Totally standard error message copied from an earlier exercise

Sub hc_ResponseError(Response As HttpResponse, Reason As String,


StatusCode As Int, TaskId As Int)

If Response <> Null Then


Msgbox("Error: " & Response.GetString("UTF8")& "Cannot find ", "Connection
Error")
Response.Release

ProgressDialogHide
ToastMessageShow("bugger",True)
End If
End Sub

Sub btnnext_Click
download
End Sub

Sub download
JSON.Initialize(recipecode)
'JSON.NextObject parses the string and returns a Map with the parsed
data. This method should be called when the top level value is an object
(which is usually the case).
Map1 = JSON.NextObject

Dim results As List 'list holds all the recipes

Basic For Android Monday, 11 June 2012 Page 113


results = Map1.Get("results")'top level with a key: the value is
everything else in the code. key:value pass it to m

'Counter to move between recipes


counter = counter + 1
'If the counter reaches the last recipe then go back to the first one,
otherwise crashes
If counter = results.Size Then
counter = 1
End If
'get the results at the place of the counter 1, 2, 3 etc
'some voodoo here
datamap = results.Get(counter)

lbltitle.Text = counter &" " & datamap.Get("title")


lblingredients.Text = datamap.Get("ingredients")
lblhyperlink.Text = datamap.Get("href") m
End Sub
Create your own APIS with http://apify.heroku.com/resources

How to make a hyperlink that opens the web browser


Creating a link to a local webbrowser is simple. In the code above we directly passed the
html to the text box, lblhyperlink.Text = datamap.Get("href") giving us a string of text that
sort of looks like an url.

'http:\/\/find.myrecipes.com\/recipes\/recipefinder.dyn?action=displayReci
pe&recipe_id=520763",
To use this we need to remove the \\ symbols and turn it into an active URL.

The code for that is simple, create a new variable called hyperlink to hold the data and then
do a string replace to take out the unwanted symbols.

As I was feeling somewhat lazy I attached the url to the click event of the label box itself,
Sub lblhyperlink_Click it might go better under a button.

hyperlink = datamap.Get("href")
hyperlink = hyperlink.Replace("\","")
lblhyperlink.Text = hyperlink
End Sub

Sub lblhyperlink_Click
Dim p As PhoneIntents
StartActivity(p.OpenBrowser(hyperlink))
End Sub
This is no way the end of this program, only the beginning.

Basic For Android Monday, 11 June 2012 Page 114


Basic For Android Monday, 11 June 2012 Page 115

You might also like