• Home
  • About

a simple android service

Posted by flexnrosescom on October 20, 2011; This entry is filed under Android.

This is a small service example in Android. A Service is a running thread which is detached from the physical view of the application. It is of a great help to keep track of feeds or webservices while the application is not present and even if it was. My objective is to show a service works, and how one is able to start it and stop it at any time, and how it can be assigned by a device event such as AIRPLANE mode to turn it on and off as well. Aside from running the service, I am hooking up a thread which runs a simple loop. At times the loop dies before the service stops and it was a good thing to show what to do in case you want to start the thread to execute again.

So here is a simple description, and I will also address basic knowledge for others who are new to Android.

We work with a configuration file, which has set permissions on the device.

Here is the full code, just unzip it and you can import it to your workspace.

We work with a configuration file, which has set permissions on the device.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!--?xml version="1.0" encoding="utf-8"?-->

&nbsp;

&nbsp;

&nbsp;

&nbsp;

<!-- all it means is there were other activities, this is the initial view -->

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

<!-- we notify the device, this is our class which will be used as a service -->

&nbsp;

<!--  We set our Broadcaster class to handle intents coming from the device such as being booted or having              the device gone over airplane mode on or off  -->

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

<!-- We want the user to know we want the application to access the internet, and also get notification when the phone has booted. -->

&nbsp;

&nbsp;

Services deal with intents. Intents are ways for us to get notifications by listeners. Think if you can in ActionScript of an EventDispatcher and object’s reading when an event is dispatched. Well, the device can send these notifications through intents which we set our application to listen to. Here we set our Broadcaster to get intents notifying when the device has been booted or the user has switched from airplane mode on and off.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.flexnroses.android.services;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.util.Log;

public class Broadcaster extends BroadcastReceiver

{

public Broadcaster()

{

}

//getting the intents from device booting or airplane mode (on/off)

//such cases we deal with MyService to start it or turn it off.

@Override

public void onReceive(Context context, Intent intent )

{

Log.d( "Broadcaster", "got onReceived " + intent.getAction() );

//if airplane mode..

if( intent.getAction().equals( Intent.ACTION_AIRPLANE_MODE_CHANGED ) )

{

if( intent.getBooleanExtra("state", false ) == true )

{

context.stopService( new Intent( context, MyService.class ) );

}

else

{

context.startService( new Intent( context, MyService.class ) );

}

}

else

if( intent.getAction().equals( Intent.ACTION_BOOT_COMPLETED ) )

{

context.startService( new Intent( context, MyService.class ) );

}

}

}

Broadcaster now will start and stop our service. Later on, our main activity “MyActivity” will do the same with its buttons as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package com.flexnroses.android.services;

import android.app.Service;

import android.content.Intent;

import android.os.AsyncTask.Status;

import android.os.IBinder;

import android.util.Log;

/**

*

* @author juan.mendez @ flexnroses.com

*

* Our service class is going to set aside another thread (bgThread) which would

* run a loop, and will be also knocking back this class and notifying

* of current updates. We just wanted to run it as another thread instead

* of having it running in the same thread as the one where this service is running.

*

* I wanted to also show here how the service is able to send broadcasts of

* the udpates coming from bgThread.

*/


public class MyService extends Service

{

public static final String TAG = "MyService";

private BgThread tweet;

private boolean _running; //this property is access by the thread when it runs, just double checking

//the service is no longer running, so it won't either.

@Override

public void onCreate()

{

// TODO Auto-generated method stub

super.onCreate();

Log.d(TAG, "onCreate" );

this._running = true;

tweet = new BgThread( this );

}

@Override

public void onDestroy()

{

// TODO Auto-generated method stub

super.onDestroy();

Log.d(TAG, "onDestroy" );

//3 making sure Thread is void

this._running = false;

tweet.cancel(true );

}

@Override

public void onLowMemory()

{

Log.d(TAG, "onLowMemory" );

// TODO Auto-generated method stub

super.onLowMemory();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId)

{

Log.d(TAG, "onStartCommand " + intent.toString() + " " + Integer.toString(startId) + " " + tweet.getStatus() + " canceled?:" + tweet.isCancelled() );

//get the state of our intent

Status status = tweet.getStatus();

//is asynctask running? then don't attempt to execute twice..

if( status.equals(Status.PENDING) )

{

tweet.execute( 0, 10 );

}

else

if( status.equals(Status.FINISHED) )

{

//AsyncTask is BgThread's super class.. therefore this should only be done once.

//if you want to reuse it, follow this http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html

if( tweet.isCancelled() == false )

tweet.cancel(true);

tweet = new BgThread( this );

tweet.execute( 0, 10 );

}

//find more at http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int)

return Service.START_STICKY;

}

//find more at http://developer.android.com/reference/android/app/Service.html#onBind(android.content.Intent)

@Override

public IBinder onBind(Intent arg0)

{

return null;

}

//as our bgThread is knocking back, we are here

//notifying any broadcast receivers of what's happening.

//this idea reminded me of EventDispatcher, and even handler from ActionScript.

public void setProgress( Integer progress )

{

Intent intent = new Intent( MyService.TAG );

intent.putExtra( "percent", progress );

this.sendBroadcast(intent);

}

//is the service running or not. if not running, its bgThread shouldn't either

public boolean is_running()

{

return _running;

}

}

Service sets aside another thread ( using AsyncTask ) in such way it will iterate an array and calculate progress which is placed back in the service. The service broadcasts the progress wrapped in an intent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package com.flexnroses.android.services;

import java.util.ArrayList;

import android.os.AsyncTask;

import android.util.Log;

public class BgThread extends AsyncTask &lt;Integer, Integer, ArrayList &gt;

{

private MyService service;

public BgThread( MyService service )

{

this.service = service;

}

/**

* running function,, we are looping over and pausing for 600 miliseconds.

* don't go so much into the details of this operation..

*/


@Override

protected ArrayList doInBackground(Integer... list)

{

int min = list[0];

int max = list[1];

ArrayList col = new ArrayList();

for( int i = min; i &lt; max; i++ )

{

try

{

if( this.isCancelled() == false || this.service.is_running() == true )

{

Thread.sleep( 600 );

}

else

{

break;

}

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

col.add( i );

this.publishProgress( i, min, max );

}

this.cancel( true );

return col;

}

@Override

protected void onCancelled()

{

Log.e("BgThread", "CANCELED" );

// TODO Auto-generated method stub

super.onCancelled();

}

@Override

protected void onPostExecute(ArrayList result)

{

// TODO Auto-generated method stub

super.onPostExecute(result);

}

@Override

protected void onPreExecute()

{

// TODO Auto-generated method stub

super.onPreExecute();

}

@Override

protected void onProgressUpdate(Integer... values)

{

int current = values[0];

int min = values[1];

int max = values[2];

int percent = (int) ( (current-min) * 100 / ( max - min ) );

// TODO Auto-generated method stub

super.onProgressUpdate(percent);

//in my case i know who the service is and i am passing the percent..

this.service.setProgress( percent );

Log.d("BgThread", Integer.toString( percent ) );

}

}

Here is our activity, which is similar in Flex to spark.components.View, we have two buttons, one starts and one stops the service. This activity is tuned to the service’s broadcast intents, and is getting that progress and placing it in its textview.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package com.flexnroses.android.services;

import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

/**

*

* @author juan.mendez @ flexnroses.com

*

* Our activity is set to also broadcast notifications coming from the service.

* We also have the ability to use btnStart and btnStop to start or stop the service.

*/


public class MyActivity extends Activity implements OnClickListener

{

private Button btnStart; //button used for starting the service

private Button btnStop; //button used to stop the service

private TextView txtView; //textfield used to show the notifications from service

private ServiceReceiver receiver; //helps us to get access to service notifications.

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

//get reference of these gui's in the layout

btnStart = (Button) this.findViewById(R.id.btnStartService);

btnStop = (Button) this.findViewById(R.id.btnStopService );

txtView = (TextView) this.findViewById( R.id.textView );

btnStart.setOnClickListener(this);

btnStop.setOnClickListener(this);

this.receiver = new ServiceReceiver();

}

@Override

protected void onPause()

{

// TODO Auto-generated method stub

super.onPause();

//we don't want to get updates while we pause for reasons such as

//leaving the screen.

this.unregisterReceiver( this.receiver );

}

@Override

protected void onResume()

{

super.onResume();

//we are back in the screen.. let's keep up tuned to the service

IntentFilter filter = new IntentFilter( MyService.TAG );

this.registerReceiver(this.receiver, filter);

}

@Override

public void onClick(View view )

{

Button button = (Button) view;

//we request to start/stop the service

if( button == this.btnStart )

{

this.startService( new Intent(this, MyService.class ) );

}

else

if( button == this.btnStop )

{

this.stopService( new Intent(this, MyService.class ) );

}

}

/**

* this class is assigned to get the service getting back the feedback.

* we use super.this to get access of MyActivity.

* @author juan.mendez @ flexnroses.com

*

*/


private class ServiceReceiver extends BroadcastReceiver

{

@Override

public void onReceive(Context context, Intent intent)

{

MyActivity.this.txtView.setText( "bgThread's progress: " + intent.getExtras().getInt("percent", 0) + "%" );

}

}

}

I hope this tutorial was helpful and clear. Thank you.

( i have created a simple video, the phone is starting, and you can see the Broadcater doing its work and then service begins and so its thread.. ) :)

2 Comments

  1. Hanson January 9th, 2013 at 4:33 pm

    Wow, exactly what i was looking for – had nearly lost hope, had tried everything i could think of…

    Thanks

  2. flexnrosescom January 16th, 2013 at 5:10 pm

    i am glad you found it useful :)

Leave a Reply

Categories

  • Actionscript (19)
  • Android (3)
  • CSS (2)
  • Design Patterns (4)
  • Flex (18)
  • Geek (2)
  • Javascript (12)
  • PHP (3)
  • Wordpress (1)

RSS

  • RSS Blog
  • RSS Comments