1.前面讲了关于ipc机制中的aidl的简单使用。最近看<<android艺术开发与探究>>里面涉及到Messenger的使用,为了加深印象,所以来此写一写。
2.Messenger英文单词的意思是"信使",它可以在不同的进程中传递Message对象。Messenger是轻量级的ipc方案,底层是aidl实现的。通过android api可以发现对于 Messenger类,它有俩个比较重要的构造法方法。
在这里我先把这俩个构造方法写出来,不先解释用法,后面再说。
3.现写一个Service服务,然后再声明一个handler对象,最后在声明一个Messenger对象。最后在onBind方法中返回Messenger.getBinder(). 具体代码如下:
package com.example.lenovo.myapplication;
/**
* Created by lenovo on 20/6/2016.
*/
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.util.Log;
/**
* Created by lenovo on 20/6/2016.
*/
public class MyTestService extends Service {
public static Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what)
{
case 1:
String value= (String) msg.getData().get("name");
Log.d("4577155",value);
Messenger messenger=msg.replyTo;
Bundle b=new Bundle();
b.putString("name","this is response");
Message message=Message.obtain(null,2);
message.setData(b);
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
super.handleMessage(msg);
}
};
public Messenger messenger=new Messenger(handler);
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}
写好Service之后,在Mainfest文件里面配置Service,注意了:必须要加一个process属性。这个属性可以使该service在不同的进程中。
对Messenger messenger=new Messenger(handler);这段代码的解释:将handler与Messenger对象绑定在一起。在Messenger的对象可以调用一个send( Message mge)方法,跨进程发送一个Message对象,发送过来之后该消息由handler来处理。
4.服务端的service写好了。现在就是客户端的程序。客户端主要是启动该Service,通过”bindService 绑定式“ 来启动。关键要注意 的是重写ServiceConnection类的ServiceConnected()方法。具体代码如下:
package com.example.lenovo.myapplication;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Messenger messenger;
public static Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what)
{
case 2:
String ss= (String) msg.getData().get("name");
Log.d("4577155",ss);
break;
}
super.handleMessage(msg);
}
};
public Messenger mg=new Messenger(handler);
public ServiceConnection con=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
Message m = Message.obtain(null, 1);
Bundle bundle = new Bundle();
bundle.putString("name", "wxy");
m.replyTo=mg;
m.setData(bundle);
try {
messenger.send(m);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Button but1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but1= (Button) findViewById(R.id.but1);
but1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setClass(MainActivity.this,MyTestService.class);
bindService(intent,con, Context.BIND_AUTO_CREATE);
}
});
}package com.example.lenovo.myapplication;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Messenger messenger;
public static Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what)
{
case 2:
String ss= (String) msg.getData().get("name");
Log.d("4577155",ss);
break;
}
super.handleMessage(msg);
}
};
public Messenger mg=new Messenger(handler);
public ServiceConnection con=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
<span style="background-color: rgb(255, 204, 255);"> messenger = new Messenger(service);
Message m = Message.obtain(null, 1);
Bundle bundle = new Bundle();
bundle.putString("name", "wxy");</span>
m.replyTo=mg;
<span style="background-color: rgb(255, 204, 255);"> m.setData(bundle);</span>
try {
<span style="background-color: rgb(255, 204, 255);"> messenger.send(m);</span>
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Button but1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but1= (Button) findViewById(R.id.but1);
but1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setClass(MainActivity.this,MyTestService.class);
bindService(intent,con, Context.BIND_AUTO_CREATE);
}
});
}
}
}
上面代码中标记颜色的部分非常重要:正如前面贴的Messenger的构造方法,标记颜色的部分,第一部就是得到了Messenger对象。
然后在声明一个Message对象,设置好Data之后,然后调用Messenger.send(message)方法。将这个message发送到Service的进程中,被Service里面的handler处理。"m.replyto=......"这代码先不要管。
最后运行结果:
至于第二个打印下面再说:
下面先总结下:客户端和服务service在不同的进程中,客户端向服务端发送message。
1."绑定" Messenger,即 先声明一个Handler对象,然后通过Messenger(handler)这个构造方法获取到一个Messenger对象,然后再在onbind方法中 return Messenger.getBinder();
2.客户端在ServiceConnection方法中,通过IBinder对象,获取到一个Messenger对象。这里我把Serice里面的Messenger和MainActivity里面的Messenger对象理解为同一个对象。原因就是:在Service的onbind方法中通过调用Messenger.getBinder(),返回一个Binder对象。在Activity的方法中又通过这个Binder,生成了一个Messenger对象,因此这个俩个类中的Messenger其实就是同一个对象。
3.每个Messenger对象必须和一个hander绑定。例如在A进程中声明了Messenger和handler。那么在B线程中必须调用Messenger.send(message);方法之后那么在handler里面才能接收到消息。注意A,B线程中的Messenger是同一个对象。
5.客户端发送消息到服务端我们知道了如何去做。那么服务端向客户端发送消息该如何去做呢?
那么这个时候,就不得不提message.replyto的方法了。服务端向客户端发送message,就是说接收方在MainActivity中,按照前面的总结我们要 声明一个Messenger 对象(在这里我们把Messenger称之为B对象)和一个handler对象,Messenger对象的构造方法,必须要调用Messenger(handler)这个方法,这样就将Messenger和handler绑定在一起了,接着只要在MyTestService类中,获取到MainActivity中的B对象,然后调用B的send(Message m)方法就可以实现服务端发送信息到客户端。
MyTestService的代码如下:
package com.example.lenovo.myapplication;
/**
* Created by lenovo on 20/6/2016.
*/
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.util.Log;
/**
* Created by lenovo on 20/6/2016.
*/
public class MyTestService extends Service {
public static Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what)
{
case 1:
String value= (String) msg.getData().get("name");
Log.d("4577155",value);
<span style="background-color: rgb(204, 204, 255);"> Messenger messenger=msg.replyTo;
Bundle b=new Bundle();
b.putString("name","this is response");
Message message=Message.obtain(null,2);
message.setData(b);
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}</span>
break;
}
super.handleMessage(msg);
}
};
public Messenger messenger=new Messenger(handler);
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}
着颜色那部分代码主要作用是:获取到从客户端传递过来的Messenger对象,也就是调用replyto方法。接着声明一个message,然后调用Messenger.send(message msg)方法将Message发送到MainActivity里面。
客户端也就是MainActivity方法中 ,新添加的代码主要是声明一个Handler和Messenger对象,只好把Messenger赋值给message.replyto.具体代码如下:
package com.example.lenovo.myapplication;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Messenger messenger;
<span style="background-color: rgb(255, 204, 255);"> public static Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what)
{
case 2:
String ss= (String) msg.getData().get("name");
Log.d("4577155",ss);
break;
}
super.handleMessage(msg);
}
};
public Messenger mg=new Messenger(handler);</span>
public ServiceConnection con=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
Message m = Message.obtain(null, 1);
Bundle bundle = new Bundle();
bundle.putString("name", "wxy");
<span style="background-color: rgb(255, 204, 255);"> m.replyTo=mg;</span>
m.setData(bundle);
try {
messenger.send(m);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Button but1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but1= (Button) findViewById(R.id.but1);
but1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setClass(MainActivity.this,MyTestService.class);
bindService(intent,con, Context.BIND_AUTO_CREATE);
}
});
}
}
标记颜色的为新添加的。最后运行结果
最后总结一下Messenger核心思想:
我理解的是将handler和Messenger绑定,其实也就是调用Messenger的new Messenger(handler )的构造方式,这个方法的其实就是把handler和Messenger绑定起来了。
然后将这个Messenger传递到其他的进程中,通过调研send(Message m)方法来发送一个消息。这样handler就可以处理那个message了。
今天就记录在这里。最近作者在看<<android开发艺术探究>>,将会记录下自己认为重要或者不熟悉的知识点。