Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Xamarin

MonoAndroid: Using Started Service

4.87/5 (12 votes)
21 Nov 2013CPOL5 min read 49.2K   573  
Demonstration of started service.

Introduction

Here, Once again I am back with another article in my series of MonoAndroid, for previous articles in series, please refer bottom part of article. In this article I am going to demonstrate creating Started Service in Mobile App. It similar to windows services however with a twist it is created and run by front application as for window service they have to be installed and managed by their own console.

According to Android Developer Guide "A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use." 

There are two types of services one is Started Services and other is bound services. The "Started Service" will keep running till it’s ask to shutdown and in case of “Bound Service” its lifetime attached to application which created it. Here the Life Cycle diagram for the Started Service:-

Image 1

In this article I will create Long Running Calculation app. In this we will simulate mathematical table in ListView using ArrayAdapter.

Step By Step we move forward

  1. Create Android application by selecting New ->Solutions and provide its name “myStartedServiceApp

    Image 2


    Figure 1: Creating Android Project!
     
  2.  
  3. Now do following changes in the the Main.axml file under Layout, after adding  UI code, it looks something like this :-
    XML
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView
            android:text="@string/entername"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:layout_width="110dp"
            android:layout_height="24.7dp"
            android:id="@+id/textView1"
            android:layout_marginRight="50dp" />
        <Button
            android:id="@+id/btnCalculate"
            android:layout_width="fill_parent"
            android:layout_height="31.3dp"
            android:text="@string/hello"
            android:textSize="10dp"
            android:layout_toRightOf="@+id/textView1"
            android:layout_marginBottom="0.0dp" />
        <EditText
            android:inputType="numberSigned"
            android:layout_width="110dp"
            android:layout_height="wrap_content"
            android:id="@+id/txtNumber"
            android:layout_below="@+id/textView1"
            android:layout_marginRight="50dp"
            android:layout_marginBottom="8.7dp" />
        <Button
            android:id="@+id/btnStopService"
            android:layout_width="fill_parent"
            android:layout_height="31.3dp"
            android:text="@string/StopService"
            android:textSize="10dp"
            android:layout_below="@+id/btnCalculate"
            android:layout_toRightOf="@+id/txtNumber"
            android:layout_marginBottom="0.0dp" />
        <ListView
            android:minWidth="25px"
            android:minHeight="25px"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:id="@+id/LVTable"
            android:layout_below="@+id/txtNumber" />
    </RelativeLayout>

    In this layout I have added two buttons, one for starting the service and other for stopping the service and the EditText for getting number for generating mathematical table. Once completed, the UI look like this 


    Image 3

    Figure: UI Screen
     
  4. Now it’s time to add BroadcastReceiver derived class MyServiceBR in the project. This class will act a medium for sending information from the service to front end activity. Once added the code  look like this :-

    C#
    [BroadcastReceiver]
    public class MyServiceBR : BroadcastReceiver
    {
    	public event Action<Context,Intent> OnBroadcastReceive = null;
    	public override void OnReceive (Context context, Intent intent)
    	{
    		if (OnBroadcastReceive != null)
    			OnBroadcastReceive.Invoke (context, intent);
    	}
    }            
  5. I have added class which contains the string constant, which I am going utilize throughout the project. Code is as follow:-

    C#
    public class MyServiceConstant
    {
    	public const string MSG_FROM_SERVICE ="MSG_FROM_SERVICE";
    	public const string VAR_CALCNUMBER ="CalculateNumber";
    	public const  string VAR_RETN_TABLE ="ReturnedTable";
    }

  6. Now it’s time to add our Service derived class, let give it name MyStartedServiceCls, you have to implement OnBind function, from here you can suggest the OS, whether this is Started Service or the Bound Service. If you return NULL from the OnBind method, you are indicating that current service is started one otherwise if you pass IBinder derived class object you are intended to create Bound service. So we will pass NULL here.
    C#
    #region implemented abstract members of Service
            public override IBinder OnBind (Intent intent)
            {
                return null;
            }
    #endregion 
    Commonly any service developer override following methods:-
    • OnStart : all service initialize code goes here
    • OnStartCommand: this method will called every time someone call StartService method, since provide calling intent as one of the parameter you can pass message to it at the time of calling
    • OnDestroy : any cleanup task you want to perform.
    C#
    public override void OnStart (Intent intent, int startId){
    }
    
    public override void OnDestroy (){
                base.OnDestroy ();
    } 

  7. Now in our OnStartCommand method , add following code :-
    C#
    public override StartCommandResult OnStartCommand (Intent intent, 
    StartCommandFlags flags, int startId)
    {
    
          int variable = int.Parse(
    intent.GetStringExtra (MyServiceConstant.VAR_CALCNUMBER));
    
    Thread tVar = new Thread(() =>
    {
      for (int value = 1; value <= 10; value++) {
          Intent newIntent = 
            new Intent(MyServiceConstant.MSG_FROM_SERVICE);
      
          newIntent.PutExtra(MyServiceConstant.VAR_RETN_TABLE,
             string.Format(" {0} X {1} = {2}",
                         variable,value,variable*value));
    
          SendBroadcast(newIntent);
          Thread.Sleep(1000);
      }
    });
    
         tVar.Start ();
         return base.OnStartCommand (intent, flags, startId);
    } 

    In this method we are returning the mathematical table (what we used to learn in school, one to ten multiplication of any number). We retrieve number from intent for which we have to generate the table. Then we broadcast our formatted string using SendBroadcast method and to simulate the long running task we will broadcast message every one second.


  8. Now add following code in MainActivity.cs,
    C#
    public class MainActivity : Activity
    {
            EditText _txtNumber = null;
            Button _btnCalculate =null,_btnStopService=null;
            ListView _lvTable=null;
            MyServiceBR _myServiceBR = new MyServiceBR();
            List<String> _myStringList = new List<String> ();
            Intent _serviceIntent; 
    
    // Other Methods
    } 
    Class methods and there explanations:-

    • OnCreate: - in this method we will initialize all the UI control on the main screen, create event handler for OnBroadcastReceive and Register broadcast receiver for MyServiceConstant.MSG_FROM_SERVICE using RegisterReceiver method.
      C#
      protected override void OnCreate (Bundle bundle) {
                  base.OnCreate (bundle);
                  // Set our view from the "main" layout resource
          SetContentView (Resource.Layout.Main);
          GetUIControls ();
      
          _myServiceBR.OnBroadcastReceive += HandleOnBroadcastReceive;
          
      RegisterReceiver(_myServiceBR,
      new IntentFilter(MyServiceConstant.MSG_FROM_SERVICE));
      
      }
    • GetUIControls : this method will associate all the UI control with variable.
      C#
      void GetUIControls ()
      {
        _btnCalculate = FindViewById<Button>  (Resource.Id.btnCalculate);
        _txtNumber = FindViewById<EditText>  (Resource.Id.txtNumber);
        _lvTable = FindViewById<ListView>  (Resource.Id.LVTable);
        _btnStopService= FindViewById<Button>  (Resource.Id.btnStopService);
        
        _btnCalculate.Click += btnCalculate_Click;
        _btnStopService.Click += btnStopService_Click;
      } 
    • btnCalculate_Click :- this method will clear all the string list, then we will create intent of type MyStartedServiceCls, provide it with EditBox text and start the service using StartService method, subsequent call to this method will call OnStartCommand method of service, instead of starting service again and again.
      C#
      void btnCalculate_Click (object sender, EventArgs e)
      {
        _myStringList.Clear ();
        _serviceIntent = new Intent (this, typeof(MyStartedServiceCls));
      
        _serviceIntent.PutExtra (MyServiceConstant.VAR_CALCNUMBER, 
      _txtNumber.Text);
      
           StartService (_serviceIntent);
      } 
    • btnStopService_Click: this method will stop running service, if you wish to stop it.
      C#
      void btnStopService_Click (object sender, EventArgs e)
      {
           StopService (_serviceIntent);
      } 
    • HandleOnBroadcastReceive : this method will handle broadcast sent by service and update the ListView with information sent by service.
      C#
      void HandleOnBroadcastReceive (Context arg1, Intent arg2)
      {
              _myStringList.Add (arg2.GetStringExtra (
      MyServiceConstant.VAR_RETN_TABLE));
      
         _lvTable.Adapter = new ArrayAdapter<string>  (this, 
              Android.Resource.Layout.SimpleListItem1,
             _myStringList);
      
      } 
      For updating the ListView we are using ArrayAdapter by passing Android common layout of type SimpleListItem1 and myStringList as list of item to be updated.

  9. Now Build and Run the application,
    Initial Screen Updating Updated
     Image 4   Image 5   Image 6 


  10. If you don’t stop the service, you can check that out in app console like shown in following images. (it’s under Setting->App->Running Process)
    Image1 Image2
    Image 7 Image 8


StartCommandResult

This section text is taken from here, word by word.

When the system is under memory pressure, Android may stop any running services.

When a service is stopped by the system, Android will use the value returned from OnStartCommand to determine how or if the service should be restarted. This value is of type StartCommandResult, which can be any of the following:

Return Type Description
Sticky  A sticky service will be restarted, and a null intent will be delivered to OnStartCommand at restart. Used when the service is continuously performing a long-running operation, such as updating a stock feed.
RedeliverIntent The service is restarted, and the last intent that was delivered to OnStartCommand before the service was stopped by the system is redelivered. Used to continue a long-running command, such as the completion of a large file upload.
NotSticky The service is not automatically restarted.
StickyCompatibility Restart will behave like Sticky on API level 5 or greater, but will downgrade to pre-level 5 behavior on earlier versions.
     

Points of Interest

I have used MonoAndroid for C# and Xamarin Studio to build this tutorial.  Watch out, if I continue learning it, you can expect more articles coming soon. 

Though Xamarin Studio is proprietary software, however they provide free starter version to built, test and publish android application. I am using same for my learning. 

Articles in this series!

Tips/Tricks in this Series

History   

  • 04-Sept-2013: First Version 
  • 06-Sept-2013: Updated Articles and Tips/Tricks Section 
  • 11-Oct-2013 : Updated article section 
  • 05-Nov-2013: Updated article section 
  • 22-Nov-2013: Updated other article section

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)