Android Tutorial Service Modules

Discussion in 'Tutorials & Examples' started by Erel, Jan 27, 2011.

  1. Erel

    Erel Administrator Staff Member Licensed User




    Basic4android v1.2 adds support for Service modules.
    Service modules play an important role in the application and process life cycle.
    Start with this tutorial if you haven't read it before: Android Process and activities life cycle
    Code written in an activity module is paused once the activity is not visible.
    So by only using activities it is not possible to run any code while your application is not visible.
    Services life cycle is (almost) not affected by the current visible activity. This allows you to run tasks in the background.
    Services usually use the status bar notifications to interact with the user. Services do not have any other visible elements. Services also cannot show any dialog (except of toast messages).
    Note that when an error occurs in a service code you will not see the "Do you want to continue?" dialog. Android's regular "Process has crashed" message will appear instead.

    Before delving into the details I would like to say that using services is simpler than it may first sound. In fact for many tasks it is easier to work with a service instead of an activity as a service is not paused and resumed all the time and services are not recreated when the user rotates the screen. There is nothing special with code written in service.
    Code in a service module runs in the same process and the same thread as all other code.

    It is important to understand how Android chooses which process to kill when it is low on memory (a new process will later be created as needed).
    A process can be in one of the three following states:
    - Foreground - The user currently sees one of the process activities.
    - Background - None of the activities of the process are visible, however there is a started service.
    - Paused - There are no visible activities and no started services.

    Paused processes are the first to be killed when needed. If there is still not enough memory, background processes will be killed.
    Foreground processes will usually not be killed.

    As you will soon see a service can also bring a process to the foreground.

    Adding a service module is done by choosing Project - Add New Module - Service Module.
    The template for new services is:
    Code:
    Sub Process_Globals

    End Sub

    Sub Service_Create

    End Sub

    Sub Service_Start (StartingIntent As Intent)

    End Sub

    Sub Service_Destroy

    End Sub
    Sub Process_Globals is the place to declare the service global variables. There is no other Globals sub like in Activity as Service doesn't support Activity objects.
    Sub process globals should only be used to declare variables. It should not run any other code as it might fail. This is true for other modules as well.
    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).
    Service use cases

    As I see it there are four main use cases for services.
    - Separating UI code with "business" or logic code. Writing the non-UI code in a service is easier than implementing it inside an Activity module as the service is not paused and resumed and it is usually will not be recreated (like an Activity).
    You can call StartService during Activity_Create and from now on work with the service module.
    A good design is to make the activity fetch the required data from the service in Sub Activity_Resume. The activity can fetch data stored in a process global variable or it can call a service Sub with CallSub method.

    - Running a long operation. For example downloading a large file from the internet. In this case you can call Service.StartForeground (from the service module). This will move your activity to the foreground state and will make sure that the OS doesn't kill it. Make sure to eventually call Service.StopForeground.

    - 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).

    - Run a service after boot. By setting the #StartAtBoot attribute to True, our service will run after boot is completed.
    Notifications

    Status bar notifications can be displayed by activities and services.
    Usually services use notifications to interact with the user. The notification displays an icon in the status bar. When the user pulls the status bar they see the notification message.

    Example of a notification (using the default icon):

    [​IMG]


    [​IMG]

    The user can press on the message, which will open an activity as configured by the Notification object.

    The notification icon is an image file which you should manually put in the following folder: <project folder>\Object\res\drawable.
    Accessing other modules

    Process global objects are public and can be accessed from other modules.
    Using CallSub method you can also call a sub in a different module.
    It is however limited to non-paused modules. This means that one activity can never access a sub of a different activity as there could only be one running activity.
    However an activity can access a running service and a service can access a running activity.
    Note that if the target component is paused then an empty string returns.
    No exception is thrown.
    You can use IsPause to check if the target module is paused.

    For example if a service has downloaded some new information it can call:
    Code:
    CallSub(Main, "RefreshData")
    If the Main activity is running it will fetch the data from the service process global variables and will update the display.
    It is also possible to pass the new information to the activity sub. However it is better to keep the information as a process global variable. This allows the activity to call RefreshData whenever it want and fetch the information (as the activity might be paused when the new information arrived).

    Note that it is not possible to use CallSub to access subs of a Code module.

    Examples:
    Downloading a file using a service module
    Periodically checking Twitter feeds
     
    Last edited: Mar 11, 2018
  2. Cor

    Cor Active Member Licensed User

    could you export a simple service app

    thanks
     
    mohammad4461 likes this.
  3. schimanski

    schimanski Well-Known Member Licensed User

    Thanks, Erel!!!! :icon_clap:

    It is one of the most needed things and very easy to use...:sign0060:


    @Cor!

    Here a very simple program to check a service. It is only a timer, which runs in the backround and updates the label1.text, if the activity-modul becomes active.....You need only an activity-modul with one label and a timer, which updates the label. And a service-modul, which counts in the backround...

    Activity-Modul:
    Code:
    Sub Process_Globals 
       
    Dim Timer1 As Timer
       Timer1.Initialize(
    "Timer1",1000)
    end sub

    Sub Button1_Click
      Timer1.Enabled=
    True
      
    StartService(TestService)
    End Sub

    Sub Timer1_Tick
      Label1.Text=TestService.Counter 
    End Sub
    Service-Modul(TestService):
    Code:
    Sub Process_Globals
      
    Dim TimerService As Timer
      
    Dim Counter As Int 
      Counter=
    0   
    End Sub

    Sub Service_Create
      TimerService.Initialize(
    "TimerService",1000)
      TimerService.Enabled=
    True
    End Sub

    Sub Service_Start
      Counter=Counter+
    1
    End Sub
    ...
    ...
    Sub TimerService_Tick
      
    StartServiceAt(""DateTime.Now, True)
    End Sub
    It runs fine on my device and should also count, if the device is sleeping...
     
  4. schimanski

    schimanski Well-Known Member Licensed User

    But, I have one question:

    With the following code, I send geo-data to the googelmaps-intent:

    Code:
    Dim Intent1 as Intent

      
    URI"geo:" & Latitude & "," & Longitude & "?q=" & Latitude & "," & Longitude
      Intent1.Initialize(Intent1.ACTION_VIEW,
    URI)
      Intent1.SetComponent(
    "googlemaps")
      
    StartActivity(Intent1)
    How is it possible to send updated data from my service to the Intent? I can't find the right syntax for intent1.PutExtra....

    thanks for help....
     
    Jim Brown likes this.
  5. Cor

    Cor Active Member Licensed User

    thanks,

    will try this evening
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    A small correction about your example.
    The ServiceTimer timer is not needed and is likely to fail eventually.
    You should instead schedule the next task with StartServiceAt.
    Android will eventually kill your process. 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.
    Also note that for most application 1 second is a very very short period as it will drain the device battery. Running a task once an hour or every 30 minutes is usually more appropriate.

    Updated code:
    Code:
    Sub Process_Globals
      
    Dim Counter As Int 
      Counter=
    0    
    End Sub

    Sub Service_Create

    End Sub

    Sub Service_Start
      Counter=Counter+
    1 ' This counting will not work for long. If it is important it should be saved in a file instead of a variable.
     StartServiceAt(""DateTime.Now + 30 * DateTime.TicksPerSecond, True'schedule the next task to run in 30 seconds.
     ... do the required work
    End Sub
    It is not recommend to start an activity from a service. As the activity will pop up while the user is busy with something else.
    Instead you should show a notification. When the user presses on the notification, the activity will start.

    I will post a full example on Sunday.
     
    hani bassam, valentino s and s.soares like this.
  7. schimanski

    schimanski Well-Known Member Licensed User

    Thanks, Erel for your efforts!

    I'm waiting on your example.

    My idea is, that i don't want to start an other activity from the service. I only want to update the data in the active-app. I hoped, that there is a way to send only the new geo-data (lat,lon) from my app to googlemaps, when the user had activated the map-software.....

    rgds
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    You should check for updates in Sub Activity_Resume. The service for example can put the update in a process global variable or a file.
     
  9. mikewhite

    mikewhite Member Licensed User

    Hi,

    when will 1.2 be available to all?
    Thanks
    Mike
     
  10. mikewhite

    mikewhite Member Licensed User

    Sorry, just saw the thread about the beta release.
    Mike:sign0161:
     
  11. susu

    susu Well-Known Member Licensed User

    How to make a service that can check update data every hour (check on 7AM, 8AM, 9AM... and so on) ?
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    I will post a complete example. There are already some internal updates required so it is delayed for now.
     
  13. susu

    susu Well-Known Member Licensed User

    I'm still waiting your complete example :D
     
  14. Erel

    Erel Administrator Staff Member Licensed User

  15. kkolle

    kkolle Member Licensed User

    App doesn´t close

    Is it possible, that an app doesn´t close correctly when a service is running?
    My Service uses "StartServiceAt" "in the Service_Start"-function.

    I tried "Acitivy.Finish" and "ExitApplication". In both cases I called "StopService" before.

    I intalled the "Twitter feed reader" example from Erel. The app stays alive after selecting "Kill process" from the menu.

    I`m using a HTC Desire.

    Many thanks.
     
  16. Erel

    Erel Administrator Staff Member Licensed User

    In this case the app is expected to wake up when the scheduled time arrives. This is exactly the advantage of StartServiceAt. Even when your process gets killed (usually by the OS), it is recreated when time arrives.

    If you want to cancel a scheduled task you should use CancelScheduledService keyword. It is called in the Twitter example when the user unchecks the automatic updates option.
     
  17. Jim Brown

    Jim Brown Active Member Licensed User

    This all sounds really good Erel
    Is there a theoretical limit as to how far ahead into the future a 'StartServiceAt' could be set? For example would a year-long delay work?

    Can you advise what circumstances (within the O/S) would halt a service?
    I am wondering for instance if rebooting the phone would kill a scheduled service?
     
  18. Erel

    Erel Administrator Staff Member Licensed User

    Yes. You can however check the Run At Boot option, under Project - Service options (when the service module is selected), and then reschedule your service when the device starts.

    Task Managers also kill scheduled services.
     
  19. Cableguy

    Cableguy Expert Licensed User

    Can Services be used to create on-screen Widgets? if so, an example would be great...From what I can see, the only things that is lacking to B4A is the widget capability...
     
  20. Erel

    Erel Administrator Staff Member Licensed User

    You cannot create widgets for the Home screen for now. It will be supported in the future.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice