您的位置:首页 > 大数据 > 人工智能

Aidl与信使的区别

2016-03-03 23:09 495 查看
Messenger实现了IPC通信(进程间通信),其真实原理也是使用了AIDL进行通信,但是和直接使用AIDL不同的是Messenger利用了Handler处 理通信,所以它是线程安全的(不支持并发处理);
而我们平时用的AIDL是非线程安全的(支持并发处理)。所以大多数时候我们应用中是不需要处理夸进程并 发处理通信的,所以这时选择Messenger会比AIDL更加容易操作。

在不考虑并发的情况下,Messenger相比AIDL无论从代码量、工程结构、复杂度等上都更加胜出一筹

信使 代码的服务端:
//这个里面要注意自己的Messenger对象的创建是以Handler为构造参数的,而接受到的对方的Messenger则是以Binder为构造参数的(在客户端),在服务端接受的Messenger对象则是从消息中直接获取。
要在清单文件中注册服务:
public
class
MainActivity
extends
Activity {

@Override

protected
void
onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.
activity_main);
[align=left] }[/align]

@Override

public
boolean
onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.
main, menu);

return
true
;
[align=left] }[/align]
[align=left]}[/align]
public
class
PrintService
extends
Service {

//1. 声明和实例化Handler及Messenger类对象,在这个方法中处理客户端发送过来的信息

private
static
Handler
mHandler=
new
Handler(){

@Override

public
void
handleMessage(Message msg) {

//处理其它线间或进程发送过来的消息
Log.
i("debug",
"--PrintService ---------------------->handleMessage:"
+msg.getData().getString(
"info"));
[align=left] [/align]
Message replyMsg=Message.
obtain();
replyMsg.
what=2;
[align=left] [/align]

try
{
//msg.replyTo 是获取到客户端传递过来的Messenger对象。,然后用客户端自己的Messenger对象,在给客户端发送消息。

msg.
replyTo.send(replyMsg);
//应答客户端: 向客户端回传消息
[align=left] [/align]
}
catch
(RemoteException e) {
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] };[/align]
[align=left] //创建本地的Messenger,以handler为构造参数。[/align]

private
Messenger
messenger
=new
Messenger(mHandler);
[align=left] [/align]

@Override

public
IBinder onBind(Intent intent) {

return
messenger
.getBinder();//2.获取Messenger对象的IBinder接口对象
[align=left] }[/align]

[align=left]}[/align]

布局文件:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools=
"http://schemas.android.com/tools"

android:layout_width=
"match_parent"

android:layout_height=
"match_parent"

android:paddingBottom=
"@dimen/activity_vertical_margin"

android:paddingLeft=
"@dimen/activity_horizontal_margin"

android:paddingRight=
"@dimen/activity_horizontal_margin"

android:paddingTop=
"@dimen/activity_vertical_margin"

tools:context=
".MainActivity"
>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/hello_world"
/>

[align=left]</RelativeLayout>[/align]
------------------------
信使客户端:
布局文件:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools=
"http://schemas.android.com/tools"

android:layout_width=
"match_parent"

android:layout_height=
"match_parent"

android:paddingBottom=
"@dimen/activity_vertical_margin"

android:paddingLeft=
"@dimen/activity_horizontal_margin"

android:paddingRight=
"@dimen/activity_horizontal_margin"

android:paddingTop=
"@dimen/activity_vertical_margin"

tools:context=
".MainActivity"
>

<Button

android:id="@+id/btnId"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="send"

android:text="项服务端发送消息"
/>

[align=left]</RelativeLayout>[/align]

[align=left]主界面代码:[/align]

[align=left]/*[/align]
[align=left] * 基于Messenger实现应用间的线程间通信[/align]
[align=left] * 1.客户端:[/align]
[align=left] * 声明Messenger对象[/align]
[align=left] * 声明并实例化SerViceConnection 接口对象 ,在绑定服务组件时使用,用于监听绑定是否成功[/align]
[align=left] * 在合适的位置调用Context.bindService()方法进行绑定[/align]
[align=left] * 在 ServiceConnection接口 的onServiceConnected()方法中[/align]
[align=left] * 将方法的第二个参数作为实例化Messenger的构造方法参数使用[/align]
* 在核实的位置,调用Messenger对象的send(Message
msg) 项服务端的Handler中发送消息
[align=left] *[/align]
[align=left] * 2. [/align]
[align=left] * 2) 如果客户端需要接收服务端回传或应答的消息,需要实例化Handler和Messenger,[/align]
[align=left] * 并将Messenger作为服务端应答的信使封装在向服务端发送的Message(消息)中[/align]
[align=left] */[/align]

public
class
MainActivity
extends
Activity {

//1. 声明Messenger对象,这个对象是从服务端发送过来的Messenger对象。

private
Messenger
messenger
;
[align=left] [/align]

//2. 实例化ServiceConnection接口对象

private
ServiceConnection
conn
=new
ServiceConnection(){

@Override

public
void
onServiceConnected(ComponentName name, IBinder service) {

//
TODO
绑定成功的回调方法

//4.实例化Messenger对象,并使用当前方法的第二个参数,传入到Messenger构造方法中。这个Messenger对象是从服务端发送过来的。

messenger=new
Messenger(service);
[align=left] }[/align]

@Override

public
void
onServiceDisconnected(ComponentName name) {

//
TODO
Auto-generated method stub
[align=left] [/align]
[align=left] }[/align]
[align=left] };[/align]
[align=left] [/align]

private
Handler
replyHandler
=new
Handler(){

@Override

public
void
handleMessage(Message msg) {

//接收服务端回传的消息

if(msg.what
==2){
Toast.
makeText(getApplicationContext(),
"发送消息成功.."
, 1).show();
[align=left] }[/align]
[align=left] }[/align]

[align=left] };[/align]
[align=left] //这个是客户端自己的信使,这个信使的作用是要被传递到服务端,在给客户端发送消息[/align]

private
Messenger
replyMessenger
=new
Messenger(replyHandler);
//应答信使
[align=left] [/align]
[align=left] [/align]

@Override

protected
voi
d
onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.
activity_main);
[align=left] [/align]

//3.开始绑定服务组件
bindService(
new
Intent("com.mrl.messenger_server.PrintService"
),

conn,
BIND_AUTO_CREATE);
[align=left] }[/align]
[align=left] [/align]

public
void
send(View v){

//5. 通过Messenger信使,向绑定服务组件所在的应用发送消息(由这一应用的Handler来处理的)
[align=left] [/align]

Message msg=Message.
obtain();
//进程间传递的信息必须实现Parcelable接口 ,一般如果要传递对象什么的,应该通过Bundle来传递不会抛异常。

//msg.obj="hello,Messenger~Server"; //此处会抛出异常,原因是String类没有实现
Parcelable接口
Bundle data=
new
Bundle();
data.putString(
"info",
"hello,Messenger~Server"
);
[align=left] [/align]
msg.setData(data);
//设置发送消息的数据

[align=left] [/align]

//设置服务端应答信使,将客户端的信使作为消息发送给服务端

msg.
replyTo=
replyMessenger;
[align=left] [/align]

try
{

//这个Messenger是服务端发送过来的Messenger对象,现在往服务端发送消息。

messenger.send(msg);
//通过信使开始向外部应用发送消息
}
catch
(RemoteException e) {
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] }[/align]

[align=left]}[/align]
-----------------------------------------------------
aidl的创建于使用:
先在服务端的src下创建一个包,新建一个 .aidl文件。如下图:



aidl文件的写法:
[align=left]package com.mrl.aidl;[/align]

[align=left]interface IRemoteService{//接口名不能用public 修饰 [/align]

void print(String
msg);
[align=left] [/align]
[align=left] String getName();[/align]
[align=left]}[/align]
在服务端的配置文件中配置service组件:
<!--
注册Service组件,注:此组件可被其应用访问,因此必须要提供一个Action -->

<service
android:name="com.mrl.serviceaidl_server.RemoteService">

<intent-filter>

<action
android:name="com.mrl.serviceaidl_server.RemoteService"
/>

</intent-filter>

</service>
[align=left]将服务端的aidl文件连同包一块拷贝到客户端。[/align]

[align=left]下面是代码实例:[/align]
[align=left]客户端主界面:[/align]

[align=left]/**[/align]
[align=left] * 通过AIDL方式绑定其它应用的服务组件[/align]
*
@author
apple
[align=left] *[/align]
[align=left] */[/align]
public
class
MainActivity
extends
Activity {

//声明aild接口对象
IRemoteService
remoteService;
[align=left] [/align]

//实例化绑定组件之间的通信接口
ServiceConnection
conn=
new
ServiceConnection() {
[align=left] [/align]

@Override

public
void
onServiceDisconnected(ComponentName name) {}
[align=left] [/align]

@Override

public
void
onServiceConnected(ComponentName name, IBinder service) {

//将第二个参数转化为.
aidl接口对象

remoteService=IRemoteService.Stub.asInterface(service);
[align=left] }[/align]
[align=left] };[/align]
[align=left] [/align]

@Override

protected
void
onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.
activity_main);
[align=left] [/align]

//绑定其它应用的Service组件,在绑定成功之后,将返回的Stub对象转化为
aidl接口对象
bindService(
new
Intent("com.mrl.serviceaidl_server.RemoteService"
),

conn,
BIND_AUTO_CREATE);
[align=left] [/align]

[align=left] }[/align]

[align=left] [/align]

public
void
getRemoteName(View v)
throws
RemoteException{

if(remoteService
!=null){
setTitle(
remoteService.getName());
[align=left] }[/align]
[align=left] }[/align]

[align=left] [/align]

public
void
print(View v)
throws
RemoteException{

if(remoteService
!=null){

remoteService.print("hello,service!!!"
);
[align=left] }[/align]
[align=left] }[/align]

[align=left]}[/align]
[align=left]服务端主界面:[/align]

[align=left]/**[/align]
[align=left] * 使用AIDL原理,实现进程间(应用间)的Service组件与Activity组件的通信[/align]
[align=left] * 1) 服务端[/align]
* 1.声明.
aidl文件,在此文件中声明进程间的通信接口(类似于Binder子类的作用)
* 2.在Service组件的onBind()方法中,返回
aidl接口的Stub对象
[align=left] * 3. 注册Service组件是,必须要提供一个启动或绑定此组件的Action[/align]
[align=left] *[/align]
[align=left] * 2) 客户端[/align]
* 1. 将服务端提供的.
aidl文件复制到src
[align=left] * 2. 在Activity类中,实例化ServiceConnection接口对象,实现两个回调方法,[/align]
* 在onServiceConnected()方法中将第二个参数转化.
aidl接口对象
[align=left] * 3. 在适当的位置调用Context.bindService()方法,进行绑定[/align]
[align=left] * [/align]
[align=left] * 此方法的第一个参数:Intent意图,在实例化时,需要指定Service组件的Action[/align]
[align=left] * [/align]
[align=left] *[/align]
*
@author
apple
[align=left] *[/align]
[align=left] */[/align]
public
class
MainActivity
extends
Activity {

@Override

protected
void
onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.
activity_main);
[align=left] }[/align]

@Override

public
boolean
onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.
main, menu);

return
true
;
[align=left] }[/align]

[align=left]}[/align]

public
class
RemoteService
extends
Service {

//2.1 实例化.aidl接口的Stub对象

private
IRemoteService.Stub
stub
=new
IRemoteService.Stub() {
[align=left] [/align]

@Override

public
void
print(String msg)
throws
RemoteException {
Log.
i("debug",
"--RemoteSerice---------------------------"
+msg);
[align=left]// Looper.prepare();[/align]
[align=left]// 这个操作会有问题:[/align]
// Toast.makeText(getApplicationContext(),
msg, Toast.LENGTH_SHORT).show();
[align=left]// Looper.loop();[/align]
[align=left] }[/align]
[align=left]// cant't create handler inside thread that has has not called Looper.prepare()[/align]

//only one looper may be created per thread at android.os.looper.prepare

@Override

public
String getName()
throws
RemoteException {
[align=left]// Looper.prepare();[/align]
[align=left]// 这个问题同样有错[/align]
[align=left]// Toast.makeText(getApplicationContext(), "RemoteSerice", Toast.LENGTH_SHORT).show();[/align]
[align=left]// Looper.loop();[/align]

return
"RemoteSerice--------"
;
[align=left] }[/align]
[align=left] };[/align]
[align=left] [/align]

@Override

public
IBinder onBind(Intent intent) {

return
stub
;//2.2 返回
aidl接口的Stub对象
[align=left] }[/align]

[align=left]}[/align]
[align=left]-------------------------------------------[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: