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:-
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
- Create Android application by selecting New ->Solutions and
provide its name “
myStartedServiceApp
”
Figure 1: Creating Android Project!
- Now do following changes in the the Main.axml file under Layout, after adding UI code,
it looks
something like this :-
="1.0"="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
Figure: UI Screen
-
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 :-
[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);
}
}
-
I have added class which contains the string constant, which I am going utilize throughout the project. Code is as follow:-
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";
}
- 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.
#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.
public override void OnStart (Intent intent, int startId){
}
public override void OnDestroy (){
base.OnDestroy ();
}
- Now in our OnStartCommand method , add following code :-
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.
- Now add following code in MainActivity.cs,
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;
}
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.
protected override void OnCreate (Bundle bundle) {
base.OnCreate (bundle);
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.
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.
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.
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.
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.
- Now Build and Run the application,
Initial Screen | Updating | Updated |
| | |
- 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 |
| |
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