5、Service详解(三):远程Service

Android中的应用程序都会运行在自己的进程里,可是如何让不同进程之间通信和数据交换呢,Android提供了AIDL( Android Interface definition language),它是一种Android内部进程通信接口额描述语言,用来实现跨进程通信( interprocess communication,即IPC)。
(一)AIDL文件
Android需要使用AIDL来定义远程接口,它用来定义两个进程之间的通信接口,所以语法比较简单,AIDL接口与java接口相似,需要注意的是:
1.AIDL定义必须以.aidl 结尾。
2.AIDL中用到的数据类型,除了基本数据类型、String、List、Map、CharSequence之外,其他数据类型都需要导包,无论是否在同一个包中。

我们试着在当前包中创建一个aidl文件,命名:IPerson.aidl。
我们在aidl接口中定义两个方法
package com.lingyun.blog.aidl;

interface IPerson{
String getName();
int getAge();
}
保存后,可以在gen目录下看到生成出了一个java接口文件,该接口中包含了一个 Stub内部类,该内部类实现了 Binder和IPerson两个接口,这个Stub类将会作为远程Service的回调类,可以作为onBind()方法的返回值。





(二)服务端-为客户端暴露接口
     首先我们需要一个Service的实现类,同本地Service一样,通过onBind()方法实现Service通信,该方法返回的就是上一步所说的Stub内部类的子类的实例。
public class MyAIDLService extends Service {

private PersonBinder myPersonBinder = new PersonBinder();

//PersonBinder继承自Stub,而Stub实现了Binder接口,所以可以用于Service通信
public class PersonBinder extends Stub {

@Override
public String getName() throws RemoteException {
// TODO Auto-generated method stub
return "小明";
}

@Override
public int getAge() throws RemoteException {
// TODO Auto-generated method stub
return 22;
}
}


@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return myPersonBinder;
}
}


写完Service后,我们需要在AndroidMenifest.xml中配置
        <service
            android:name=".MyAIDLService">
            <intent-filter >
                <action android:name="com.lingyun.blog.action.MYAIDL_SERVICE"/>
            </intent-filter>
        </service>

(三)客户端-访问AIDL服务
    AIDL接口定义了两个进程之间的通信接口,所以不仅服务端需要AIDL接口,客户端也需要AIDL接口,并且客户端和服务端需要对应,所以我们通过将服务端的AIDL文件复制到客户端中

定义一个布局文件,里面放一个按钮和一个文本框用来显示在上一个应用中的Service数据。
<LinearLayout 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:orientation="vertical" >

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="onGetAIDLServiceClick"
        android:text="获取远程Service数据" />

    <TextView
        android:id="@+id/textView_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

在Activity中实现数据回调对象的获取
public class MainActivity extends Activity {

private TextView tv_message;
private IPerson myPerson;

private ServiceConnection conn = new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
myPerson = null;
}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
myPerson = IPerson.Stub.asInterface(service);
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_message = (TextView)findViewById(R.id.textView_message);
Intent intent = new Intent();
intent.setAction("com.lingyun.blog.action.MYAIDL_SERVICE");
//绑定远程Service
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}

public void onGetAIDLServiceClick(View v){
try {
tv_message.setText("姓名:"+myPerson.getName()+"年龄:"+myPerson.getAge());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unbindService(conn);
}
}

需要注意的是,在获取Service回调对象时,本地Service是直接获取onBinder()的返回值,而远程Service是返回对象的代理,所以需要类似 IPerson.Stub.asInterface(service)进行处理。 另外服务端和客户端的AIDL文件需要采用同样的包名,这样才能找到。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值