Android Service Creation using Messenger
Feature: Get Reply from Service component to UI using Broadcast Receiver.
Different Android Services in Android
For full description of Android Service go to this post
A live Example
The example application just send a request string from the user to the service and service reply the message string along with a random number to the UI client which it display on its View. The Start Service button is used to start the service. Once service started you can send the request message. To stop the service use Stop Service button.
activity_main.xml
Feature: Get Reply from Service component to UI using Broadcast Receiver.
Different Android Services in Android
For full description of Android Service go to this post
Messenger Service in Android
- For Asynchronous Communication
- Service and Client may live in different Address Space
- Single thread for all requests
- No Multi Threading
What Service Needs
- Create a Handler and Override its handleMessage()
- Create a Messenger and pass the Handler to it
- Override onBind()
- It returns the IBinder using Messenger
- Receive Message : By Handler
- Send Message : msg.replyTo.send(response)
public class MessengerService extends Service {
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
......
......
try {
msg.replyTo.send(res);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
.......
return mMessenger.getBinder();
}
}
|
What Client Needs
- Messenger Reference
- ServiceConnection
- Override onServiceConnected()
- Create a new Messenger using IBinder returned from Service
- Override onServiceDisconnected
- Call to bindService()
- Send the Message to Service : Using messenger Reference
- Receive the Message from the Service: Handler which is set by
- msg.replyTo.send(new Messenger(new MyResponseHandler))
public class MainActivity extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
private ServiceConnection mConnection = new ServiceConnection();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.....
.....
}
@Override
protected void onStart() {
super.onStart();
bindService(new Intent(getApplicationContext(), MessengerService.class),
mConnection, Context.BIND_AUTO_CREATE);
}
public void sendRequest(View v) {
Message msg = Message.obtain(null, MessengerService.REQUEST, 0, 0);
msg.replyTo= new Messenger(new ResponseHandler());
mService.send(msg);
}
class ResponseHandler extends Handler {
@Override
public void handleMessage(Message msg){
int mKind=msg.what;
switch(mKind){
case MessengerService.RESPONSE:
// Use the Response Message
default:
}
}
}
@Override
protected void onStop() {
super.onStop();
unbindService(mConnection);
}
}
|
What Service Connection Does for the Clients
- Confirm connection with the Service
- It gets the IBinder returned from the Service
- Creates Messenger using this for the client
- Client uses Messenger to get Handler
- Client sends Message using this Handler
private Messenger mService;
boolean mBound=false;
......
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
Toast.makeText(getApplicationContext(), "Server is connected now !", Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
}
|
What a Response Handler Does?
- It gets the Intent sent from Service
- Send the reply message to UI, the Client
class ResponseHandler extends Handler {
@Override
public void handleMessage(Message msg){
int mKind=msg.what;
switch(mKind){
case MessengerService.RESPONSE:
String res=msg.getData().getString("REPLY");
responseET.setText(res); // UI sets its View using the reply string.
default:
}
}
}
|
A live Example
The example application just send a request string from the user to the service and service reply the message string along with a random number to the UI client which it display on its View. The Start Service button is used to start the service. Once service started you can send the request message. To stop the service use Stop Service button.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="pp.messengerservice.MainActivity"
tools:ignore="MergeRootFrame" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Messenger Service Test"
android:textSize="25sp"
android:textColor="#ff0000" />
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textView1"
android:layout_marginTop="28dp"
android:onClick="sayHello"
android:text="Start Service" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/button1"
android:layout_marginTop="20dp"
android:text="Stop Service" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/button2"
android:layout_marginTop="75dp"
android:text="Request"
android:textSize="25sp"
android:layout_marginRight="5dp"/>
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/textView2"
android:layout_alignBottom="@+id/textView2"
android:layout_toRightOf="@+id/textView3"
android:ems="10"
android:hint="Put Message !" />
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/editText1"
android:layout_marginTop="25dp"
android:layout_toRightOf="@+id/textView3"
android:ems="10"
android:hint="Response from Server"
android:background="#f0fcf2"
android:textColor="#ff0000" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/editText2"
android:layout_alignBottom="@+id/editText2"
android:layout_alignParentLeft="true"
android:text="Response"
android:textSize="25sp"
android:layout_marginRight="5dp" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="24dp"
android:layout_toRightOf="@+id/textView2"
android:text="Get Message"
android:onClick="sendRequest" />
</RelativeLayout>
|
Manifest.xml
Register the service in manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pp.messengerservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name="pp.messengerservice.MessengerService"/>
<activity
android:name="pp.messengerservice.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
|
MessengerService.java
package pp.messengerservice;
import java.util.Random;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.Toast;
public class MessengerService extends Service {
static final int REQUEST = 1;
static final int RESPONSE= 2;
Random gen =new Random();
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case REQUEST:
String rq = msg.getData().getString("REQUEST");
Message res=Message.obtain(null,RESPONSE);
Bundle bundle = new Bundle();
int random = gen.nextInt(1000);
bundle.putString("REPLY", rq+" : "+random);
res.setData(bundle);
try {
msg.replyTo.send(res);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
|
MainActivity.java
package pp.messengerservice;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
boolean mBound;
Button startService, stopService;
EditText requestET, responseET;
public void sendRequest(View v) {
if (!mBound) {
Toast.makeText(getApplicationContext(), "Please Satrt The Service !", Toast.LENGTH_SHORT).show();
return;
}
Message msg = Message.obtain(null, MessengerService.REQUEST, 0, 0);
Bundle bundle = new Bundle();
String req = requestET.getText().toString();
bundle.putString("REQUEST", req);
msg.setData(bundle);
msg.replyTo= new Messenger(new ResponseHandler());
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
Toast.makeText(getApplicationContext(), "Server is connected now !", Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
class ResponseHandler extends Handler {
@Override
public void handleMessage(Message msg){
int mKind=msg.what;
switch(mKind){
case MessengerService.RESPONSE:
responseET.setEnabled(true);
String res=msg.getData().getString("REPLY");
responseET.setText(res);
responseET.setEnabled(false);
default:
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService = (Button)findViewById(R.id.button1);
stopService = (Button)findViewById(R.id.button2);
requestET=(EditText)findViewById(R.id.editText1);
responseET=(EditText)findViewById(R.id.editText2);
stopService.setEnabled(false);
requestET.setEnabled(false);
responseET.setEnabled(false);
}
@Override
protected void onStart() {
super.onStart();
startService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
bindService(new Intent(getApplicationContext(), MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
startService.setEnabled(false);
stopService.setEnabled(true);
requestET.setEnabled(true);
}
});
stopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (mBound) {
unbindService(mConnection);
mBound = false;
startService.setEnabled(true);
stopService.setEnabled(false);
requestET.setEnabled(false);
Toast.makeText(getApplicationContext(), "Server is Disconnected !", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
|
No comments:
Post a Comment