Pour transmettre des messages entre processus Android il est pratique d’utiliser l’inter-process-communication (IPC) « Messenger ».
Ceci est possible dans le cadre d’un service lié à une activité (service Bound). Dans ce cas, au lieu de fonctionner en tâche de fond indéfiniment, le service ne sera activé que tant que l’activité le sera et des messages pourront être échangés entre l’activité et le service.
Ce procédé fonctionne comme un client/serveur. Le(s) client(s) est/sont des activités qui se connectent au serveur : le service.
Exemple : dans un service placer une gestion de message IPC permettant de recevoir une chaîne de caractères et de la retourner convertie en majuscule.
Dans le service placer le traitement du message :
public class ConvertService extends Service {
//-- Définition des valeurs des messages
static final int TO_UPPER_CASE = 1;
static final int TO_UPPER_CASE_RESPONSE = 2;
//-- Handler du Message
private Messenger msg = new Messenger(new ConvertHandler());
public IBinder onBind(Intent paramIntent) {
return msg.getBinder();
}
//-- Traiement du message
class ConvertHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int msgType = msg.what;
switch (msgType) {
case TO_UPPER_CASE: {
try {
//-- lecture des données dans "data"
String data = msg.getData().getString("data");
//-- renvoi des données dans "resp"
Message resp = Message.obtain(null, TO_UPPER_CASE_RESPONSE);
Bundle bResp = new Bundle();
bResp.putString("respData", data.toUpperCase());
resp.setData(bResp);
msg.replyTo.send(resp);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
default:
super.handleMessage(msg);
}
}
}
Dans le manifest de l’application déclarer que le service fonctionne dans un autre processus :
<service android:name=".ConvertService" android:process=":convertprc"/>
L’activité appelant le service, envoyant et recevant des messages :
public class MainActivity extends AppCompatActivity {
//--
private ServiceConnection sConn; //-- Pour récupérer la valeur retour
private Messenger messenger;
//-- variables layout
private TextView TxtOrigin, TxtResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
////////////////
TxtOrigin = (TextView) findViewById(R.id.txt_origin);
TxtResult = (TextView) findViewById(R.id.txt_conv);
Button BtnConv = (Button) findViewById(R.id.btn_conv);
BtnConv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String val = TxtOrigin.getText().toString();
//-- Envoi du message
Message msg = Message
.obtain(null, ConvertService.TO_UPPER_CASE);
msg.replyTo = new Messenger(new ResponseHandler());
// We pass the value
Bundle b = new Bundle();
b.putString("data", val);
msg.setData(b);
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
////////////
// Service Connection to handle system callbacks
sConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
messenger = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// We are conntected to the service
messenger = new Messenger(service);
}
};
// We bind to the service
bindService(new Intent(this, ConvertService.class), sConn,
Context.BIND_AUTO_CREATE);
}
// This class handles the Service response
class ResponseHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int respCode = msg.what;
switch (respCode) {
case ConvertService.TO_UPPER_CASE_RESPONSE: {
String result = msg.getData().getString("respData");
TxtResult.setText(result);
}
}
}
}
Le code complet est ici
Références :
http://www.survivingwithandroid.com/2014/01/android-bound-service-ipc-with-messenger-2.html
https://androidtutorialmagic.wordpress.com/bound-service-tutorial-by-using-messenger/
http://www.truiton.com/2015/01/android-bind-service-using-messenger/
http://codetheory.in/android-interprocess-communication-ipc-messenger-remote-bound-services/