AIDL
2015-12-28 18:09
351 查看
AIDL介绍
AIDL表示“Android接口定义语言”:Android Interface Definition Language.
使用AIDL定义的接口,会被开发工具生成为可实现远程访问的接口。
进程间通信模式是组件间通信的“高级”应用方式,与一般组件间通信的区别在于:接口需要使用AIDL定义。
由于存在2个应用程序进行通信,因此,提供服务的应用程序通常被称之为“服务端”,而调用它的
接口的方法的应用程序则被称之为“客户端”。
AIDL接口:
使用java中创建接口的方式即可创建AIDL的接口,区别在于:
AIDL的接口的原文件扩展名为.aidl,一般的接口的源文件的扩展名为java。
AIDL的接口不允许使用public或任何访问权限修饰符去修饰该接口,它
默认即被修饰为public。
在创建了AIDL接口后,开发工具会在gen下生成匹配的J***A源文件。
使用AIDL绑定远程Service
在开发工具生成的AIDL接口的J***A源文件中,定义了名为stub的内部类,
继承了android.os.Binder,并实现了AIDL的接口,因此,开发人员在创建Service中的IBinder
的实现类时,仅需继承该Stub类即可。
由开发人员定义的AIDL接口中的抽象方法,都被定义为抛出远程异常(android.os.RemoteException),
在实现这些抽象方法时需要处理。
在AIDL接口的Stub内部类中,存在asInterface(IBinder obj)方法,用于将IBinder对象
转换为AIDL接口的实现类对象,因此,在绑定Service的组件中,可通过该方法得到AIDL接口的实现类对象。
使用AIDL与一般绑定服务的区别
使用AIDL与一般绑定服务的区别:
【服务端】使用AIDL接口
【服务端】创建AIDL接口的内部类Stub的子类对象,并将其作为Service中
onBind()的返回值;
【服务端】必须配置Service是可以隐式激活的
【客户端】将服务端的AIDL文件复制到客户端
【客户端】在ServiceConnection的onServiceConnected()中,使用AIDL接口的
Stub的asinterface()方法,将参数IBinder转换为AIDL接口的对象。
服务端开发步骤:
开发AIDL接口源文件,并确保扩展名是.aidl(如果先创建的*.java源文件后改名,则需刷新)
在Service中开发AIDL接口的实现类,并实现AIDL接口中定义的抽象方法;
实现Service类中的onBind()方法,并将AIDL的实现类的对象作为该方法的返回值
注册Service类,并配置<intent-filter>
部署服务端应用程序到设备上
客户端开发步骤
1、将服务端的AIDL相关文件复制到客户端中,注意:相关文件的包名、类名是不允许修改的
2、开发ServiceConnection接口中的实现类
3、使用隐式意图绑定服务端的Service
4、在ServiceConnection接口中的实现类的onServiceConnected()方法中,通过AIDL的内部类Stub的asInterface()方法
,将IBinder对象转换为AIDL接口的对象。
一个简单的小案例:
服务端:
MainActivity:
PlayerAIDL.aidl
布局没有任何改变,初始的即可,
需要在AndroidMainfest.xml中配置信息:
需要将相对应的aidl包跟文件都复制到应用端,
MainActivity:
以上的就是这个简单的小项目,先将服务端配置到虚拟器上,然后将客户端配置到虚拟器上,运行成功,就会在客户端打印出服务端的信息。
注意:
绑定远程Service时,组件的相关方法执行顺序:
1、【客户端】绑定远程Service,即调用bindService()方法;
2、【服务端】Service的生命周期开始,即onCreate()->onBind();
3、【客户端】ServiceConnection中onServiceConnected()方法被回调。
在客户端执行bindService()时,由于服务端的Service尚未启动,更没有返回IBinder
对象,则客户端中onServiceConnected()方法还没有被回调,因此,直接在客户端bindService()后马上
调用远程服务可能导致NullPointerException.
使用AIDL远程播放音乐
服务端:
MainActivity:
Service:
需要提前将音乐添加到虚拟机中,我在这里边添加了三首歌曲,
PlayerAIDL.aidl
布局里边不用修改,就按照默认的就可以,
重要的一步,在AndroidMainfest.xml中配置Service:
应用端:
相应的,需要将服务端的相对应的.aidl所在的包名以及文件都拷贝到应用端,这里不再做介绍,
MainActivity:
布局:
AIDL中的数据类型
在AIDL接口中,如需使用以下数据类型,无需导包语句即可直接使用:
J***A的基本数据类型,包括:byte,short,int,long,float,double,char,boolean.
String与CharSequence。
List与Map。
如需使用自定义的数据类型,或List,Map中封装自定义数据类型的数据,则要求:
1、自定义的数据类型实现Parcelable接口i;
2、编写自定义数据类型的*.aidl文件;
3、无论自定义数据类型与AIDL接口文件是否在同一个包中,在使用自定义数据类型时,都需在AIDL接口文件中
显式的使用import语句导入;
4、将自定义数据类型的*.java源文件与*.aidl源文件复制到客户端。
自定义数据类型的*.aidl文件:
需存在与*.java源文件相同的package语句;
添加parcelable类名;语句。
Parcelable接口:基于任何复合数据类型都是基本数据类型封装后的集合,因此,各种复合数据类型都可以被拆分为
基本数据类型进行传输。
parcelable接口约定了数据被序列化传输的方式。
在parcelable接口中,定义了一下抽象方法:
public int describeContents()(用于内容接口的描述)
public void writeToParcel(Parcel dest,int flags)(writeToParcel()方法用于将当前类的成员写入到Parcel
容器中,重写该方法时,调用Parcel类的write系列方法即可,例如writeInt(),writeString()等。)
通常开发人员仍自定义readFromParcel(Parcel parcel)方法,以对应必须重写的writeToParcel()方法,用于从Parcel容器中
读取数据。
读取数据时,顺序必须与写入数据完全相同!
必须创建静态常量CREATOR,实现Parcelable.Creator<T>接口:
该常量必须被修饰为public static final ,且常量名必须为
CREATOR;
重写接口中的抽象方法。
使用AIDL访问自定义类型数据
功能:服务端提供getStudentList()方法,返回List<Student>类型数据。
Student类型中至少封装3个属性,且至少其中2个属性的数据类型是相同的,
例如2个String类型和1个int类型。
客户端可获取服务端提供的数据
下面的是相对应的案例:
服务端:
MainActivity:
Student.java
Service:
Student.aidl:
StudentAIDL.aidl:
服务端的布局使用默认的即可,不用做更改,
应用端:相应的需要将Student.sidl,StudentAIDL.aidl,Student.java及他们所在的包名都复制到客户端,
MainActivity:
布局不用做任何的修改,先将服务端部署到虚拟机上,然后运行应用端,查看logcat,就会看到服务端的打印的信息。
AIDL表示“Android接口定义语言”:Android Interface Definition Language.
使用AIDL定义的接口,会被开发工具生成为可实现远程访问的接口。
进程间通信模式是组件间通信的“高级”应用方式,与一般组件间通信的区别在于:接口需要使用AIDL定义。
由于存在2个应用程序进行通信,因此,提供服务的应用程序通常被称之为“服务端”,而调用它的
接口的方法的应用程序则被称之为“客户端”。
AIDL接口:
使用java中创建接口的方式即可创建AIDL的接口,区别在于:
AIDL的接口的原文件扩展名为.aidl,一般的接口的源文件的扩展名为java。
AIDL的接口不允许使用public或任何访问权限修饰符去修饰该接口,它
默认即被修饰为public。
在创建了AIDL接口后,开发工具会在gen下生成匹配的J***A源文件。
使用AIDL绑定远程Service
在开发工具生成的AIDL接口的J***A源文件中,定义了名为stub的内部类,
继承了android.os.Binder,并实现了AIDL的接口,因此,开发人员在创建Service中的IBinder
的实现类时,仅需继承该Stub类即可。
由开发人员定义的AIDL接口中的抽象方法,都被定义为抛出远程异常(android.os.RemoteException),
在实现这些抽象方法时需要处理。
在AIDL接口的Stub内部类中,存在asInterface(IBinder obj)方法,用于将IBinder对象
转换为AIDL接口的实现类对象,因此,在绑定Service的组件中,可通过该方法得到AIDL接口的实现类对象。
使用AIDL与一般绑定服务的区别
使用AIDL与一般绑定服务的区别:
【服务端】使用AIDL接口
【服务端】创建AIDL接口的内部类Stub的子类对象,并将其作为Service中
onBind()的返回值;
【服务端】必须配置Service是可以隐式激活的
【客户端】将服务端的AIDL文件复制到客户端
【客户端】在ServiceConnection的onServiceConnected()中,使用AIDL接口的
Stub的asinterface()方法,将参数IBinder转换为AIDL接口的对象。
服务端开发步骤:
开发AIDL接口源文件,并确保扩展名是.aidl(如果先创建的*.java源文件后改名,则需刷新)
在Service中开发AIDL接口的实现类,并实现AIDL接口中定义的抽象方法;
实现Service类中的onBind()方法,并将AIDL的实现类的对象作为该方法的返回值
注册Service类,并配置<intent-filter>
部署服务端应用程序到设备上
客户端开发步骤
1、将服务端的AIDL相关文件复制到客户端中,注意:相关文件的包名、类名是不允许修改的
2、开发ServiceConnection接口中的实现类
3、使用隐式意图绑定服务端的Service
4、在ServiceConnection接口中的实现类的onServiceConnected()方法中,通过AIDL的内部类Stub的asInterface()方法
,将IBinder对象转换为AIDL接口的对象。
一个简单的小案例:
服务端:
MainActivity:
package com.edu.hpu.service; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }Service:
package com.edu.hpu.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class PlayerService extends Service{ @Override public void onCreate() { // TODO Auto-generated method stub Log.d("AIDL","服务端:PlayerService onCreate"); super.onCreate(); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.d("AIDL","服务端:PlayerService onBind"); return new InnerBinder(); } private class InnerBinder extends PlayerAIDL.Stub{ @Override public void playMusic() throws RemoteException { // TODO Auto-generated method stub Log.d("AIDL","服务端:PlayerService playMusic"); } @Override public void pauseMusic() throws RemoteException { // TODO Auto-generated method stub Log.d("AIDL","服务端:PlayerService pauseMusic"); } } }
PlayerAIDL.aidl
package com.edu.hpu.service; interface PlayerAIDL { void playMusic(); void pauseMusic(); }
布局没有任何改变,初始的即可,
需要在AndroidMainfest.xml中配置信息:
<service android:name="com.edu.hpu.service.PlayerService"> <intent-filter> <action android:name="com.edu.hpu.service.intent.action.REMOTE_PLAYER_SERVICE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>应用端:
需要将相对应的aidl包跟文件都复制到应用端,
MainActivity:
package com.example.receiveservice; import com.edu.hpu.service.PlayerAIDL; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { private ServiceConnection conn = null; PlayerAIDL player; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("AIDL","客户端:MainActivity.onCreate"); conn = new InnerServiceConnection(); Intent service = new Intent("com.edu.hpu.service.intent.action.REMOTE_PLAYER_SERVICE"); bindService(service,conn,BIND_AUTO_CREATE); } private class InnerServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Log.i("AIDL","客户端:MainActivity.onServiceConnected"); player = PlayerAIDL.Stub.asInterface(service); try { player.playMusic(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { player.pauseMusic(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } } @Override protected void onDestroy() { // TODO Auto-generated method stub unbindService(conn); super.onDestroy(); } }
以上的就是这个简单的小项目,先将服务端配置到虚拟器上,然后将客户端配置到虚拟器上,运行成功,就会在客户端打印出服务端的信息。
注意:
绑定远程Service时,组件的相关方法执行顺序:
1、【客户端】绑定远程Service,即调用bindService()方法;
2、【服务端】Service的生命周期开始,即onCreate()->onBind();
3、【客户端】ServiceConnection中onServiceConnected()方法被回调。
在客户端执行bindService()时,由于服务端的Service尚未启动,更没有返回IBinder
对象,则客户端中onServiceConnected()方法还没有被回调,因此,直接在客户端bindService()后马上
调用远程服务可能导致NullPointerException.
使用AIDL远程播放音乐
服务端:
MainActivity:
package com.example.service1; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Service:
package com.example.service1; import java.io.IOException; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.os.Environment; import android.os.IBinder; import android.os.RemoteException; public class PlayerService extends Service { private MediaPlayer player; private int Current; private String[] musics = new String[] { Environment.getExternalStorageDirectory().getAbsolutePath() + "/Music/number1.mp3", Environment.getExternalStorageDirectory().getAbsolutePath() + "/Music/number2.mp3", Environment.getExternalStorageDirectory().getAbsolutePath() + "/Music/number3.mp3" }; private int currentMusicIndex = 0; @Override public void onCreate() { // TODO Auto-generated method stub player = new MediaPlayer(); player.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // TODO Auto-generated method stub doNext(); } }); super.onCreate(); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return new InnerBinder(); } private void doPlay() { player.reset(); try { player.setDataSource(musics[currentMusicIndex]); player.prepare(); player.seekTo(Current); player.start(); Current = 0; } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void doPause() { if (player.isPlaying()) { Current = player.getCurrentPosition(); player.pause(); } } private void doPrevious() { currentMusicIndex--; if (currentMusicIndex < 0) { currentMusicIndex = musics.length - 1; } Current = 0; doPlay(); } private void doNext() { currentMusicIndex++; if (currentMusicIndex >= musics.length) { currentMusicIndex = 0; } Current = 0; doPlay(); } private class InnerBinder extends PlayerAIDL.Stub { @Override public void play() throws RemoteException { // TODO Auto-generated method stub doPlay(); } @Override public void pause() throws RemoteException { // TODO Auto-generated method stub doPause(); } @Override public void previous() throws RemoteException { // TODO Auto-generated method stub doPrevious(); } @Override public void next() throws RemoteException { // TODO Auto-generated method stub doNext(); } } @Override public void onDestroy() { // TODO Auto-generated method stub player.release(); player = null; super.onDestroy(); } }
需要提前将音乐添加到虚拟机中,我在这里边添加了三首歌曲,
PlayerAIDL.aidl
package com.example.service1; interface PlayerAIDL { void play(); void pause(); void previous(); void next(); }
布局里边不用修改,就按照默认的就可以,
重要的一步,在AndroidMainfest.xml中配置Service:
<service android:name="com.example.service1.PlayerService"> <intent-filter> <action android:name="com.example.service1.REMOTE_PLAYER_SERVICE_1"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
应用端:
相应的,需要将服务端的相对应的.aidl所在的包名以及文件都拷贝到应用端,这里不再做介绍,
MainActivity:
package com.example.service2; import com.example.service1.PlayerAIDL; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { private InnerServiceConnection conn; private PlayerAIDL player; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new InnerServiceConnection(); Intent service = new Intent( "com.example.service1.REMOTE_PLAYER_SERVICE_1"); bindService(service, conn, BIND_AUTO_CREATE); } public void doPlay(View view) { try { player.play(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void doPause(View view) { try { player.pause(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void doPrevious(View view) { try { player.previous(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void doNext(View view) { try { player.next(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private class InnerServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub player = PlayerAIDL.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } } @Override protected void onDestroy() { // TODO Auto-generated method stub unbindService(conn); super.onDestroy(); } }
布局:
<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" > <ImageButton android:id="@+id/pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/play" android:layout_marginLeft="58dp" android:onClick="doPause" android:layout_toRightOf="@+id/play" android:src="@android:drawable/ic_media_pause" /> <ImageButton android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:onClick="doPlay" android:layout_alignParentTop="true" android:layout_marginLeft="87dp" android:layout_marginTop="36dp" android:src="@android:drawable/ic_media_play" /> <ImageButton android:id="@+id/previous" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/play" android:onClick="doPrevious" android:layout_below="@+id/play" android:layout_marginTop="49dp" android:src="@android:drawable/ic_media_previous" /> <ImageButton android:id="@+id/next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/pause" android:onClick="doNext" android:layout_alignTop="@+id/previous" android:src="@android:drawable/ic_media_next" /> </RelativeLayout>AndroidMainfest.xml中的相关信息无需配置,直接将服务端的应用部署到虚拟机上边,然后将应用端的应用部署到虚拟机上边,运行应用端的应用,就会实现一个跨应用程序获取Service的一个能够进行歌曲播放、暂停、上一曲、下一曲的功能。
AIDL中的数据类型
在AIDL接口中,如需使用以下数据类型,无需导包语句即可直接使用:
J***A的基本数据类型,包括:byte,short,int,long,float,double,char,boolean.
String与CharSequence。
List与Map。
如需使用自定义的数据类型,或List,Map中封装自定义数据类型的数据,则要求:
1、自定义的数据类型实现Parcelable接口i;
2、编写自定义数据类型的*.aidl文件;
3、无论自定义数据类型与AIDL接口文件是否在同一个包中,在使用自定义数据类型时,都需在AIDL接口文件中
显式的使用import语句导入;
4、将自定义数据类型的*.java源文件与*.aidl源文件复制到客户端。
自定义数据类型的*.aidl文件:
需存在与*.java源文件相同的package语句;
添加parcelable类名;语句。
Parcelable接口:基于任何复合数据类型都是基本数据类型封装后的集合,因此,各种复合数据类型都可以被拆分为
基本数据类型进行传输。
parcelable接口约定了数据被序列化传输的方式。
在parcelable接口中,定义了一下抽象方法:
public int describeContents()(用于内容接口的描述)
public void writeToParcel(Parcel dest,int flags)(writeToParcel()方法用于将当前类的成员写入到Parcel
容器中,重写该方法时,调用Parcel类的write系列方法即可,例如writeInt(),writeString()等。)
通常开发人员仍自定义readFromParcel(Parcel parcel)方法,以对应必须重写的writeToParcel()方法,用于从Parcel容器中
读取数据。
读取数据时,顺序必须与写入数据完全相同!
public void writeToParcel(Parcel parcel,int flags){ parcel.writeInt(age); parcel.writeString(name); parcel.writeString(from); } public void readFromParcel(Parcel parcel){ this.age = parcel.readInt(); this.name = parcel.readString(); this.from = parcel.readString(); }
必须创建静态常量CREATOR,实现Parcelable.Creator<T>接口:
该常量必须被修饰为public static final ,且常量名必须为
CREATOR;
重写接口中的抽象方法。
使用AIDL访问自定义类型数据
功能:服务端提供getStudentList()方法,返回List<Student>类型数据。
Student类型中至少封装3个属性,且至少其中2个属性的数据类型是相同的,
例如2个String类型和1个int类型。
客户端可获取服务端提供的数据
下面的是相对应的案例:
服务端:
MainActivity:
package com.example.servicemen; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Student.java
package com.example.servicemen; import android.os.Parcel; import android.os.Parcelable; public class Student implements Parcelable{ private String name; private String from; private int age; public Student(String name, String from, int age) { this.name = name; this.from = from; this.age = age; } @Override public String toString() { return "Student [name=" + name + ", from=" + from + ", age=" + age + "]"; } public Student(Parcel source) { // TODO Auto-generated constructor stub readFromParcel(source); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>(){ @Override public Student createFromParcel(Parcel source) { // TODO Auto-generated method stub return new Student(source); } @Override public Student[] newArray(int size) { // TODO Auto-generated method stub return new Student[size]; } }; @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated method stub dest.writeString(name); dest.writeString(from);dest.writeInt(age); } private void readFromParcel(Parcel from){ this.name = from.readString(); this.from = from.readString(); this.age = from.readInt(); } }
Service:
package com.example.servicemen; import java.util.ArrayList; import java.util.List; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; public class StudentService extends Service{ @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return new InnerBinder(); } private class InnerBinder extends StudentAIDL.Stub{ @Override public List<Student> getStudentList() throws RemoteException { // TODO Auto-generated method stub List<Student> students = new ArrayList<Student>(); students.add(new Student("asjdasd","fdghfg",30)); students.add(new Student("ssasd","saafg",60)); students.add(new Student("sliuliud","ililfg",90)); return students; } } }
Student.aidl:
package com.example.servicemen; parcelable Student;
StudentAIDL.aidl:
package com.example.servicemen; import com.example.servicemen.Student; interface StudentAIDL { List<Student> getStudentList(); }相应的需要在AndroidMainfest.xml中配置相关的信息:
<service android:name="com.example.servicemen.StudentService"> <intent-filter> <action android:name="com.example.servicemen.intent.action.STUDENT_ACTION"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>
服务端的布局使用默认的即可,不用做更改,
应用端:相应的需要将Student.sidl,StudentAIDL.aidl,Student.java及他们所在的包名都复制到客户端,
MainActivity:
package com.example.service4; import java.util.List; import com.example.servicemen.Student; import com.example.servicemen.StudentAIDL; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { private ServiceConnection conn; private StudentAIDL service; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new InnerServiceConnection(); Intent service = new Intent("com.example.servicemen.intent.action.STUDENT_ACTION"); bindService(service, conn, BIND_AUTO_CREATE); } private class InnerServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder arg0) { // TODO Auto-generated method stub service = StudentAIDL.Stub.asInterface(arg0); try { List<Student> students = service.getStudentList(); for (Student student : students) { System.out.println("student" + student); } } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } } @Override protected void onDestroy() { // TODO Auto-generated method stub unbindService(conn); super.onDestroy(); } }
布局不用做任何的修改,先将服务端部署到虚拟机上,然后运行应用端,查看logcat,就会看到服务端的打印的信息。
相关文章推荐
- FZU 2216 The Longest Straight 二分
- offsetof与container_of宏[总结]
- jms的failover方式
- 服务器主机上RAID Controller的Read Ahead Policy
- 自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 一)
- 自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 一)
- RAID6磁盘阵列数据如何恢复
- MiniSnail子模块的规划
- SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
- Training set、 gallery set、Probe set
- WSAWaitForMultipleEvents
- stl map用法和make_pair函数和pair结构体
- Clairewd’s message
- Failed to restart network.service: Unit network.service failed to load: No such file or directory.
- v8 bailout
- UVA-Matrix Chain Multiplication(栈)
- Containing ViewControllers
- UVA-514 Rails (栈)
- CTE(Custom Terrain Editor)使用说明
- CTE(CustomTerrainEditor) 自定义地形编辑器(已上传视频, 并更新版本到CTE1.3)