Android Componets
Services
•
Services are for long
running processes that may need to keep running even decoupled from any
activity.
•
Perform long running
operations in background and does not provide a user interface.
•
Performing operations
that need to continue even if the user leaves the activity.
•
application’s
activities, such as a long download (e.g., downloading an app from the Android
Market) or playing music (e.g., an Android music app)
Example:
•
Performing operations
that need to exist regardless of activities coming and going, such as
maintaining a chat connection in support of a chat application.
•
Providing a local API
to remote APIs, such as might be provided by a web service.
Types:
•
Started : A service is
"started" when an application component (such as an activity) starts
it by calling startService().
Once started, a service can run in the background indefinitely, even if the
component that started it is destroyed. Usually, a started service performs a
single operation and does not return a result to the caller. For example, it
might download or upload a file over the network. When the operation is done, the
service should stop itself.
•
Bound : A service is
"bound" when an application component binds to it by calling bindService().
A bound service offers a client-server interface that allows components to
interact with the service, send requests, get results, and even do so across
processes with interprocess communication (IPC). A bound service runs only as
long as another application component is bound to it. Multiple components can
bind to the service at once, but when all of them unbind, the service is
destroyed.
•
Local Service :
Corresponding service is running in the same application.
•
Remote Service :
Corresponding service is running in different application.
•
For creating a service
we need to extend the service class or a subclass of service like
IntentService.
Life Cycle:
•
onCreate(): The system
calls this method when the service is first created, to perform one-time setup
procedures (before it calls either onStartCommand()
or onBind()).
If the service is already running, this method is not called.
•
onStartCommand(): The
system calls this method when another component, such as an activity, requests
that the service be started, by calling startService().
Once this method executes, the service is started and can run in the background
indefinitely. If you implement this, it is your responsibility to stop the
service when its work is done, by calling stopSelf()
or stopService().
(If you only want to provide binding, you don't need to implement this method.)
•
onBind :The system
calls this method when another component wants to bind with the service (such
as to perform RPC), by calling bindService().
In your implementation of this method, you must provide an interface that
clients use to communicate with the service, by returning an IBinder.
You must always implement this method, but if you don't want to allow binding,
then you should return null.
•
onDestroy() : The
system calls this method when the service is no longer used and is being
destroyed. Your service should implement this to clean up any resources such as
threads, registered listeners, receivers, etc. This is the last call the
service receives.
Life time of Service:
•
Activities being
terminated abruptly in the face of low memory issues apply in a similar fashion
with services.
•
Android 4.0 Ice Cream
Sandwich introduces a new method, onTrimMemory(), that allows the system to
better handle low memory situations specifically with services, giving them a
chance to release unused or unneeded resources before having to resort to
onDestroy().
Mainfest Entry:
•
<service
android:name=“NameofService"/>.
•
If we want to require
some permission of those who wish to start or bind to the service, add an
android:permission attribute naming the permission we are mandating.
•
Like an activity, a
service can define intent filters that allow other components to invoke the
service using implicit intents. By declaring intent filters, components from
any application installed on the user's device can potentially start your
service if your service declares an intent filter that matches the intent
another application passes to startService()
Caution
•
A service runs in the
main thread of its hosting process—the service does not create its own
thread and does not run in a separate process (unless you specify
otherwise). This means that, if your service is going to do any CPU intensive
work or blocking operations (such as MP3 playback or networking), you should
create a new thread within the service to do that work. By using a separate
thread, you will reduce the risk of Application Not Responding (ANR) errors and
the application's main thread can remain dedicated to user interaction with our
activities.
Creating a started service:
•
A started service is
one that another component starts by calling startService(),
resulting in a call to the service's onStartCommand()
method.
•
An application
component such as an activity can start the service by calling startService()
and passing an Intent
that specifies the service and includes any data for the service to use. The
service receives this Intent
in the onStartCommand()
method.
Service class:
•
Service :This is the
base class for all services. When we extend this class, it's important that we create
a new thread in which to do all the service's work, because the service uses
our application's main thread, by default, which could slow the performance of
any activity our application is running.
•
IntentService :This is
a subclass of Service
that uses a worker thread to handle all start requests, one at a time. This is
the best option if we don't require that our service handle multiple requests
simultaneously. All we need to do is implement onHandleIntent(),
which receives the intent for each start request so we can do the background
work.
Extending the IntentService Class
•
Most started services
don't need to handle multiple requests simultaneously (which can actually be a
dangerous multi-threading scenario), it's probably best if we implement our
service using the IntentService
class.
•
Creates a default
worker thread that executes all intents delivered to onStartCommand()
separate from our application's main thread.
•
Creates a work queue
that passes one intent at a time to our onHandleIntent()
implementation, so we never have to worry about multi-threading.
•
Stops the service after
all start requests have been handled, so we never have to call stopSelf().
•
Provides a default
implementation of onStartCommand()
that sends the intent to the work queue and then to our onHandleIntent()
implementation.
Example of Intent service
public class HelloIntentService extends
IntentService {
/** * A constructor is required, and must call
the super IntentService(String)
* constructor with a name for the worker thread. */
publicHelloIntentService() {
super("HelloIntentService");
}
/** * The IntentService calls this
method from the default worker thread with * the intent that started the
service. When this method returns, IntentService * stops the service, as
appropriate. */
protected void onHandleIntent(Intent
intent) {
/*We should do our work here like
downloading a file*/
}
That's all we need: a constructor and an
implementation of onHandleIntent().
If we decide to also override other
callback methods, such as onCreate(),
onStartCommand(),
or onDestroy(),
be sure to call the super implementation, so that the IntentService
can properly handle the life of the worker thread.
Intent Service:
•
onStartCommand()
must return the default implementation (which is how the intent gets delivered
to onHandleIntent()).
@Override
publicintonStartCommand(Intent intent,
int flags, intstartId) {
Toast.makeText(this, "service
starting", Toast.LENGTH_SHORT).show();
returnsuper.onStartCommand(intent,flags,startId);
}
Extending the service class:
•
An IntentService
completes the task and stop itself, but while using service class the user need
to stop the service.
•
Local Service: override
onCreate(),onStart().onStartCommand(),onDestroy(),onBind() returns null.
•
startSevice(Intent
service)
•
Stopservice(Intent
service)
Binding to local service:
•
In order to create a
bound service we must implement onBind() callback method to return a Ibinder
that defines the interface for communication with the service.
•
To request the service
to run in the foreground,request the service to run in the foreground using
startforeground().
•
In case of calling
bindservice(),onstartCommand() method is not called instead onBind() is called.
•
Extending the Binder Class:If
our service is private to our own application and runs in the same process as
the client (which is common), we should create our interface by extending the Binder
class and returning an instance of it from onBind().
The client receives the Binder
and can use it to directly access public methods available in either the Binder
implementation or even the Service.
•
This works only if the
client and service are in the same application and process, which is most
common. For example, this would work well for a music application that needs to
bind an activity to its own service that's playing music in the background.
•
In our service, we have
to create an instance of Binder
that either:
•
contains public methods
that the client can call
•
returns the current Service
instance, which has public methods the client can call
•
or, returns an instance
of another class hosted by the service with public methods the client can call
Example for Binding to a service:
public class LocalService extends
Service {
// Binder given to clients
private final IBindermBinder = new
LocalBinder();
// Random number generator
private final Random mGenerator = new
Random();
/** * Class used for the client Binder.
Because we know this service always * runs in the same process as its clients,
we don't need to deal with IPC. */
public class LocalBinder extends Binder
{
LocalServicegetService() {
// Return this instance of LocalService so
clients can call public methods
returnLocalService.this; } }
@Override public IBinderonBind(Intent intent)
{ return mBinder; }
/** method for clients */
publicintgetRandomNumber() {
returnmGenerator.nextInt(100); } }
protected void onStart() { super.onStart();
// Bind to LocalService
Intent intent = new Intent(this,
LocalService.class);
bindService(intent, mConnection,
Context.BIND_AUTO_CREATE); }
privateServiceConnectionmConnection =
new ServiceConnection() {
@Override public void onServiceConnected(ComponentNameclassName,
IBinder service) {
// We've bound to LocalService, cast the
IBinder and get LocalService instance
LocalBinder binder = (LocalBinder)
service;
mService = binder.getService(); mBound =
true; }
@Override public void
onServiceDisconnected(ComponentName arg0) {
mBound = false;} }
Using mService we call the methods of
the local service class.
Binding using Messenger
•
For our interface to
work across different processes, we can create an interface for the service
using a messenger. In this way service defines a Handler that responds to
different type of Message objects. This Handler is the basis for a Messenger that can then share an IBinder with the client, allowing the client to send commands
to the service using Message objects. Additionally, the client can define a Messenger of its own so the service can send messages back.
•
The
service implements a Handler that receives a callback for each call from a client.
•
Clients
use the IBinder to instantiate the Messenger (that references the service's Handler), which the client uses to send Message objects to the service.
•
The
service receives each Message in its Handler—specifically, in the handleMessage() method.
Example:
public class MessengerService
extends Service {
/** Command to
the service to display a message */
static final int
MSG_SAY_HELLO = 1;
/** * Handler of incoming messages from
clients. */
classIncomingHandler
extends Handler {
@Override
public void
handleMessage(Message msg) {
switch
(msg.what) {
case
MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(),
"hello!", Toast.LENGTH_SHORT).show(); break;
default:
super.handleMessage(msg);
} } }
/** * Target we publish for clients to send
messages to IncomingHandler. */
final Messenger
mMessenger = new Messenger(new IncomingHandler());
/** * When
binding to the service, we return an interface to our messenger * for sending
messages to the service. */
@Override
publicIBinderonBind(Intent
intent) {
Toast.makeText(getApplicationContext(),
"binding", Toast.LENGTH_SHORT).show();
returnmMessenger.getBinder();
}
}
public class
ActivityMessenger extends Activity {
/** Messenger for communicating with the
service. */
Messenger mService = null;
/** Flag indicating whether we have called
bind on the service. */
booleanmBound;
/** * Class for interacting with the main
interface of the service. */
privateServiceConnectionmConnection
= new ServiceConnection() {
public void
onServiceConnected(ComponentNameclassName, IBinder service) {
// This is
called when the connection with the service has been // established, giving us
the object we can use to // interact with the service. We are communicating
with the // service using a Messenger, so here we get a client-side // representation
of that from the raw IBinder object.
mService = new
Messenger(service);
mBound = true;
}
public void
onServiceDisconnected(ComponentNameclassName) {
// This is called when the connection with
the service has been // unexpectedly disconnected -- that is, its process
crashed.
mService = null;
mBound = false;
} };
public void
sayHello(View v) {
if (!mBound)
return;
// Create and
send a message to the service, using a supported 'what' value
Message msg =
Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg); }
catch
(RemoteException e) { e.printStackTrace(); } }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void
onStart() { super.onStart();
// Bind to the
service
bindService(new
Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); }
@Override
protected void
onStop() {
super.onStop();
// Unbind from
the service
if (mBound) {
unbindService(mConnection);
mBound = false;
} } }
•
Note: Only activities, services, and content providers can
bind to a service—you cannot bind to a service from BroadCastReceiver.
•
Implement
ServiceConnection. Your implementation must override two callback
methods:
•
onServiceConnected() The system calls this to deliver the IBinder returned by the service's onBind() method. onServiceDisconnected() The Android system calls this when the connection to the service is
unexpectedly lost, such as when the service has crashed or has been killed.
This is not called when the client unbinds. a service from a broadcast receiver.
•
Call
bindService(), passing the ServiceConnection implementation.
•
When
the system calls your onServiceConnected()callback method, you can begin making calls to the service, using the
methods defined by the interface.
•
To
disconnect from the service, call unbindService().
•
Note: You should usually not bind and unbind during
your activity's onResume() and onPause(), because these callbacks occur at every lifecycle transition and you
should keep the processing that occurs at these transitions to a minimum. Also,
if multiple activities in your application bind to the same service and there
is a transition between two of those activities, the service may be destroyed
and recreated as the current activity unbinds (during pause) before the next
one binds (during resume).
•
START_NOT_STICKY: If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending
intents to deliver.
•
START_STICKY: If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do not redeliver the last intent. Instead, the system calls
onStartCommand() with a null intent, unless there were pending intents to start the
service, in which case, those intents are delivered. This is suitable for media
players (or similar services) that are not executing commands, but running
indefinitely and waiting for a job.
•
START_REDELIVER_INTENT:
If the system kills the
service after onStartCommand() returns, recreate the service and call onStartCommand() with the last intent that was delivered to the service. Any pending
intents are delivered in turn. This is suitable for services that are actively
performing a job that should be immediately resumed, such as downloading a
file.
BroadCastReceivers
•
A
broadcast receiver is a component that responds to system-wide broadcast
announcements. Many broadcasts originate from the system—for example, a
broadcast announcing that the screen has turned off, the battery is low, or a
picture was captured. Applications can also initiate broadcasts—for example, to
let other applications know that some data has been downloaded to the device
and is available for them to use. Although broadcast receivers don't display a
user interface, they may create a status bar notification to alert the user when a broadcast event occurs. More
commonly, though, a broadcast receiver is just a "gateway" to other
components and is intended to do a very minimal amount of work. For instance,
it might initiate a service to perform some work based on the event. A
broadcast receiver is implemented as a subclass of BroadcastReceiver and each broadcast is delivered as an Intent object.
Registering in Manifest file:
<receiver android:name=".Activity_Name">
<intent-filter>
<action android:name="com.unitedcoders.android.broadcasttest.SHOWTOAST"/>
</intent-filter>
</receiver>
•
We have to override the
onReceive(Context context,Intent intent) method.
privateBroadcastReceiver receiver = new
BroadcastReceiver() {
public void onReceive(Context context,
Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),
"Received", Toast.LENGTH_LONG).show();
}
};
Broadcasting a Intent:
Intent broadcast = new Intent();
broadcast.setAction(BROADCAST_ACTION);
sendBroadcast(broadcast);
The BROADCAST_INTENT should be same as
mentioned for the intent filter while registering in the mainfest.
Registering the receiver Dynamically:
We can register the receiver in
onResume() of our activity.
IntentFilter filter = new
IntentFilter();
filter.addAction(DemoBroadcast.BROADCAST_ACTION);
registerReceiver(receiver, filter);
For unregistering the receiver we can
unregister it in onPause().
unregisterReceiver(receiver);
AsyncTask
•
AsyncTask enables
proper and easy use of the UI thread. This class allows to perform background
operations and publish results on the UI thread without having to manipulate
threads and/or handlers.
•
AsyncTask is designed
to be a helper class around Thread
and Handler
and does not constitute a generic threading framework. AsyncTasks should
ideally be used for short operations (a few seconds at the most.) If we need to
keep threads running for long periods of time, it is highly recommended that we
use the various APIs provided by the java.util.concurrentpacakge such as Executor,
ThreadPoolExecutor
and FutureTask.
•
An asynchronous task is
defined by a computation that runs on a background thread and whose result is
published on the UI thread. An asynchronous task is defined by 3 generic types,
called Params, Progress and Result, and 4 steps, called onPreExecute,
doInBackground, onProgressUpdate and onPostExecute.
AsyncTask’s Generic Types
•
The three types used by
an asynchronous task are the following:
•
Params, the type of the
parameters sent to the task upon execution.
•
Progress, the type of
the progress units published during the background computation.
•
Result, the type of the
result of the background computation.
•
When an asynchronous
task is executed, the task goes through 4 steps:
•
onPreExecute(),
invoked on the UI thread immediately after the task is executed. This step is
normally used to setup the task, for instance by showing a progress bar in the
user interface.
•
doInBackground(Params...),
invoked on the background thread immediately after onPreExecute()
finishes executing. This step is used to perform background computation that
can take a long time. The parameters of the asynchronous task are passed to
this step. The result of the computation must be returned by this step and will
be passed back to the last step. This step can also use publishProgress(Progress...)
to publish one or more units of progress. These values are published on the UI
thread, in the onProgressUpdate(Progress...)
step.
•
onProgressUpdate(Progress...),
invoked on the UI thread after a call to publishProgress(Progress...).
The timing of the execution is undefined. This method is used to display any
form of progress in the user interface while the background computation is
still executing. For instance, it can be used to animate a progress bar or show
logs in a text field.
•
onPostExecute(Result),
invoked on the UI thread after the background computation finishes. The result
of the background computation is passed to this step as a parameter.
Threading rules
•
There are a few
threading rules that must be followed for this class to work properly:
•
The AsyncTask class
must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
•
The task instance must
be created on the UI thread.
•
Do not call onPreExecute(),
onPostExecute(Result),
doInBackground(Params...),
onProgressUpdate(Progress...)
manually.
•
The task can be
executed only once (an exception will be thrown if a second execution is
attempted.)
Example for AsyncTask:
classProgressTask extends
AsyncTask<Integer,Integer,Void>{
•
@Override
•
protected Void doInBackground(Integer...
params) {
•
// TODO Auto-generated method stub
•
int start = params[0];
•
for(int
i=start;i<=100;i+=5){
•
try {
•
boolean
cancelled=isCancelled();
•
//if async task is not cancelled, update
the progress
•
if(!cancelled){
•
publishProgress(i);
•
SystemClock.sleep(1000);
•
}
•
} catch (Exception e) {
•
Log.e("Error",
e.toString());
•
}
•
}
•
Log.d("Anki",
"doInBackground Called");
•
return null;
•
}
•
@Override
•
protected void
onCancelled() {
•
// TODO Auto-generated method stub
•
progress.setMax(0);
•
Log.d("Anki",
"onCancelled Called");
•
super.onCancelled();
•
}
•
@Override
•
protected void
onPostExecute(Void result) {
•
// TODO Auto-generated method stub
•
Log.d("Anki",
"onPostExecute Called");
•
super.onPostExecute(result);
}
•
@Override
•
protected void
onPreExecute() {
•
// TODO Auto-generated method stub
•
progress.setMax(100);
•
Log.d("Anki",
"onPreExecute Called");
•
super.onPreExecute();
•
}
•
@Override
•
protected void
onProgressUpdate(Integer... values) {
•
// TODO Auto-generated method stub
•
progress.setProgress(values[0]);
•
Log.d("Anki",
"onProgressUpdate Called");
•
super.onProgressUpdate(values);
•
}
•
}
Comments
Post a Comment
Please post comments here:-)