Chapter 3: Digging deeper into Android

In this chapter, we explain the important things you need to know about the 'Activity lifecycle', designing the screen layouts for your app, testing them, and how you can use extra code from other people to enhance your app easily. For most of the examples from page 79 onwards, you'll need a licensed copy of Basic4Android, rather than the trial one, as that doesn't allow extra libraries.

  • 56 Circle of life
    Learn about the Android Activity Cycle, and what it means for your app
  • 60 Laying it out
    Discover all you need to know about creating great looking screens for your app
  • 64 STEP BY STEP: Using the B4A Designer
    Use the Designer to give your app a polished appearance
  • 68 STEP BY STEP: Testing your interface
    Use Basic4Android's UI Cloud to see what your app looks like on different devices
  • 70 Statement of Intent
    How intents can make your app open web pages, call phone numbers and more
  • 74 STEP BY STEP: Using Intents in your app
    Add simple intents to your app in minutes
  • 76 Make your code modular
    Learn how to split your code up to save time and effort
  • 79 Open book
    Find out how libraries make it easy to add extra features to your apps
  • 82 Essential B4A Libraries
    We pick some of the most useful libraries and show you how to use them
  • 86 STEP BY STEP: Using libraries in your app
    Install a library and use it to add new functions easily
  • 88 Hints and tips
    Our expert tips to help make the most of Basic4Android and solve common programming problems
  • 92 Service station
    Find out how to use services, and communicate with different parts of your app

Page 58: Saving user input

This short example helps to save a value that's been entered by the user, if they rotate the device. First, this is the code to add in Activity_Create:

If firstTime = True then
     savedText = ""
end if

temperature.Text = savedText

And then in Activity_Pause, we add:

If UserClosed = False then
     savedText = temperature.Text
end if

Don't forget to add the Dim statement in Process_Globals, either

Page 59: Understanding the activity cycle

These bits of code (and the Dim statements you need to add too) can help understand what's preserved and what's lost during different actions on your device. In Activity_Create:

If FirstTime = True Then
     ToastMessageShow("First time",False)
     gInfo = "This is a global"
Else
     ToastMessageShow("Activity create",False)
End If

For Activity_Resume:

ToastMessageShow("Resuming, gInfo = " & gInfo & " pInfo = " & pInfo, False)

And in Activity_Pause:

If UserClosed Then
     ToastMessageShow("Pausing. User closed = true",False)
Else
     ToastMessageShow("Pausing. User closed = false",False)
End If

Page 71: Simple intents

This code works in all versions of B4A and allows you to open a web site in the phone's browser:

Dim a As Intent
i.Initialize(i.ACTION_VIEW, "http://nwcode.info")
StartActivity(i)

This slightly more elegant version does the same thing, but needs the Phone library, so will only work in a licensed version:

Dim p as phoneIntents
StartActivity(p.OpenBrowser("http://nwcode.info")


To open a Google map, after settings the variables for latitude, longitude and placename, use code like this:

Dim maplink As String
maplink = "http://maps.google.com/maps/?loc:" & latitude & "," & longitude & "(" & placename & ")"


Dim mapIntent as Intent
mapIntent.Initialize(mapIntent.ACTION_VIEW,maplink)
StartActivity(mapIntent)

Page 72: Email intent

This code allows you to create a new email with some of the information already filled in. Again, it requires the phone library and so won't work in the trial version of B4A:

Dim e as Email
Dim recipients As List
recipients.Initialize

 

recipients.Add("help@nwcode.info")
e.To = recipients
e.Subject = "Request for help with Android app"
e.Body = "Please fill in the rest of this message with a clear description of your problem"

StartActivity(e.GetIntent)

Page 72: Starting intent

This code will let your app work with the intent that started it, and respond to cetain links:

Dim sn As Intent
sn = Activity.GetStartingIntent
If sn.HasExtra("Notification_tag") then
     Dim tag As String
     Tag = sn.GetExtra("Notification_tag")
     Log("Started from notification with tag " & tag)
Else If sn.GetData <> Null AND sn.GetData.StartsWith("http://nwcode.info") then
     ' do something based on the page requested
End If

To make the app start from a link to anything that begins http://nwcode.info/example/, you'd need to edit your app's manifest in B4A, and include code like this (the Manifest Editor is on the Project menu):

AddActivityText(Main,
<intent-filter>

  <action android:name="android.intent.action.VIEW" />

  <category android:name="android.intent.category.DEFAULT" />

  <category android:name="android.intent.category.BROWSABLE" />

  <data android:scheme="http" />

  <data android:host="nwcode.info" />

  <data android:pathPrefix="/example/" />

</intent-filter>)

Page 73: Create a notfication

Here's how to make a notification appear on your device:

Dim n as Notification
n.Initialize
n.AutoCancel = true
n.icon = "notifyicon"
n.setinfo2("This is the title","This is the message","tag text","")
n.Vibrate = false
n.Sound = true
n.Notify(999)

While most icons you use are in the Files folder of your project, the notification icon needs to be in the Objects/res/drawable folder, and should be a png graphic.

Page 75: Open a YouTube video

This code should start the YouTube app and play a music video by Spanish singer Luz Casal:

Dim p As Intent
p.Initialize(p.ACTION_VIEW,"http://www.youtube.com/watch?v=LS04M9Mz26E")
p.SetComponent("com.google.android.youtube.WatchActivity")
p.PutExtra("","http://www.youtube.com/watch?v=LS04M9Mz26E")
StartActivity(p)

Page 75: Dial a number

This code opens the phone dialler with the number specified:

Dim p As Intent
p.Initialize(p.ACTION_VIEW,"tel:02079460000")
StartActivity(p)

Page 76: A simple sub

This is a simple subroutine that you could use to help with your debugging; remember you also need the Process_Globals variable 'debugging':

Sub myLog ( message As String )
  Log(message)
  If debugging = True then ToastMessageShow(message,false)
End sub

Page 76/77: Temperature conversion sub

This simple subroutine has two parameters and returns a value, so though simple it shows how to do some extremely useful tasks:

Sub convertTemp( temp As Float, celsius As Boolean ) As Float

  Dim Factor, result as Float
  If celsius  = True then
     Factor = 9/5 ' things get bigger
  Else
     Factor = 5/9
  End if

  result = ((temp+40) * Factor )- 40
  Return result
End sub

Page 77: Code modules

On page 77, the magazine says that when you use a code module, a copy of it is added to your project, so if you change the master copy, you need to add it to each app again. This was correct when the magazine was written, but Basic4Android v3.80 was released in late May 2014, and adds the ability to have shared code modules, which can be kept in a specific folder - like libraries - so that there will only be one copy of the module. You can read more about using these in this article on the B4A website.

Page 80/81: Roaming or airplane?

This code snippet uses the phone library to work out whether or not the user might be using roaming data, or if their device is in airplane mode:

Dim p as Phone

If p.IsAirplaneModeOn = True then ToastMessageShow("You are in airplane mode. Latest info will not be available",false)
If p.IsNetworkRoaming = True then ToastMessageShow("You are roaming. Fetching latest info could incur extra charges",false)

Page 81: Making a phone call

This way of making a call uses the Phone library, rather than a tel: style URL as we saw above:

Dim help as PhoneCalls
StartActivity(help.Call("01234567890"))

Page 81: Find out when Airplane mode is turned on and off

Using PhoneEvents, you can set up a sub that will be called when the user turns Airplane mode off or on, and react accordingly:

Dim pe As PhoneEvents
pe.Initialize("pe")

Later in the code, create your sub:

Sub pe_AirplaneModeChanged (State As Boolean, Intent As Intent)
     If State = True Then ToastMessageShow("Turn off Airplane mode to allow downloads",False)
End Sub

Page 82: Getting a date with Dialogs

This code example uses the Dialogs library to ask the user for the start of their holiday:

Dim now as Long
now = DateTime.now ' get the current time

 

Dim holiday As DateDialog
holiday.Year = DateTime.GetYear(now)
holiday.Month = DateTime.GetMonth(now)
holiday.DayOfMonth = DateTime.GetDayOfMonth(now)

 

Dim result As Int
result = holiday.Show("Select the start date","Holiday planner","OK","Cancel","",null)


If result = DialogResponse.POSITIVE Then
     ' the OK button was clicked
     ' check holiday.Year, holiday.Month and holiday.DayOfMonth

End if

Page 82/83: Are we using WiFi?

Here's how to check that the wifi is turned on, and the phone isn't using mobile data. After checking this, you might, for example, try to download a web page, to check that the there's a full internet connection:

Dim p As Phone
If p.GetSettings("wifi_on") AND p.GetDataState = "DISCONNECTED" then
     ' the phone has wifi turned on, and is not using mobile data
End if

Page 83: Downloading with HttpUtils2

To work with this library, you need to set up your request, as an HttpJob, and then add a JobDone sub to your code, which handles the results. So, first, say something like this, to get the BBC home page:

Dim bbc As httpJob
bbc.Initialize("bbc",Me)
bbc.Download("http://www.bbc.co.uk")

Then set up your JobDone sub:

Sub JobDone ( job as HttpJob)
  If job.Success = True then
     Select job.JobName
          Case "bbc"
               ' do something with the BBC home page
          Case "logo"
               ' use a downloaded image
               myImage.Bitmap = job.GetBitmap
     End Select
  Else
     ToastMessageShow("Error downloading",False)
  End If

End sub

If your layout has an image on it called myImage, then the code above wll replace it with a logo that you can fetch like this:

Dim getLogo as HttpJob
getLogo.Initialize("logo",Me)
getLogo.Download("http://nwcode.info/logo.jpg")

Page 85: A pop up menu wth AHQuickAction

Here's how to create a pop-up menu using the AHQuickAction library:

Dim myMenu As AHPopupMenu
myMenu.Initialize("myMenu")
For i = 1 to 3
     Dim ai As AHActionItem
     Dim menutext As string


     Select i
          Case 1
              menutext = "About this app"
          Case 2
               menutext = "Help"
          Case 3
               menutext = "Exit"
     End select
     ai.Initialize(i,menutext,null)
     ai.Selected(i,True)
     myMenu.AddActionItem(ai)
Next

If you have a button called myButton on your layout, you could make the menu pop up by that with this code:

myMenu.show(myButton)

And a sub like this will handle the clicks on the menu:

Sub myPopup_Click( position As Int, actionItemID As Int)
  ' check the result here

End sub

Page 85: Getting the language with Reflection

This simple example uses the Reflection library to get the device's language

Dim Language As String
Dim r As Reflector
r.Target = r.RunStaticMethod("java.util.Locale", "getDefault", Null, Null)
Language = r.RunMethod("getLanguage")

Page 86: step by step

Note that, as of B4A version 3.80 the screen shown in step 1 of this example has a fourth box, which allows you to specify a location for shared code modules. This feature was not available in the version of B4A that was used when we wrote the magazine.

Page 89: Trapping the back key

To intercept the back key, you need to add this code to your app:

Sub Activity_KeyPress(KeyCode As Int) As Boolean
     ' trap the back key
     If KeyCode = KeyCodes.KEYCODE_BACK Then

          CallSubDelayed(Me,"backhandler")
        Return True
       
     Else
        Return False
     End If
End Sub


Make sure you have a global variable called closeCounter, and then add this sub, called backhandler:

Sub backhandler
  closeCounter = closeCounter + 1
  If closeCounter = 2 Then
    closeCounter = 0
    Activity.Finish
  Else
     ToastMessageShow("Press back again to exit", False)
  End If
End Sub

Page 89: Adding a webview

This code places a webview over your app, full screen,  and displays a page in it:

Dim myBrowser As WebView
myBroswer.Initalize("myBrowser")
Activity.Addview(myBrowser,0,0,100%x,100%y)
myBrowser.LoadUrl("http://nwcode.info/")

And this sub handles clicks on the webview, as long as the link clicked contains the path 'nwcode.info/help'

Sub myBrowser_OverrideURL ( URL As String ) As Boolean
     If URL.Contains("nwcode.info/help") Then
       Return False ' Allow the link to be followed
     Else
          If URL = "http://nwcode.info/closehelp" then Activity.RemoveViewAt(Activity.NumberOfViews-1)
          Return True ' Don't follow the link
     End if

End Sub

Page 90: Using a webview to display a photo with pinch to zoom

Here's a quick way to use the webview to show a photo that can be zoomed:

Dim photoView As WebView
photoView.Initialize("photoView")
photoView.Color = Colors.Black

Dim posterURL As String = "file://" & File.DirDefaultExternal & "/mypicture.jpg"

 
Activity.AddView(photoView,0,0,100%x,100%y)
photoView.LoadHtml("<html><body><a href='" & posterURL & "'><img src='" & posterURL & "' width='100%' /></a></body></html>")
ToastMessageShow("Tap photo to return",False)

Page 90/91: Capturing and emailing logs

Here's how you can make your app gather information from the logs and send them via email. First create some process globals:

Dim myLogs As LogCat
Dim emailLog, logTag As String
Dim logArgs(1) At String

Then, run this code when the user asks to send you the logs:

myLogs.LogCatStart(logArgs,"logger")
emailLog = ""
logTag = "Capturing at " & DateTime.Now
Log(logTag)

And finally, this sub will capture the logs (which will include entries from before the preceding code was run, hopefully showing the error you need to investigate) and email them to you:

Sub logger_LogCatData (Buffer() As Byte, Length As Int)
     ' convert the buffer to string data
   
     Dim logdata As String
     logdata = BytesToString(Buffer,0,Length,"UTF-8")
     emailLog = emailLog & logdata
        

     If logdata.Contains(logTag) Then
          myLog.LogCatStop
          Dim e As Email
        
          e.To = Array As String ("help@nwcode.info")
          e.Subject = "Log from app user"
          e.Body = emailLog
        
          StartActivity(e.GetIntent)
     End If
End Sub