标签:parcelable aidl service service android 四大组件
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
在前一篇文章(关于Android中的四大组件(Service的开启与关闭))中介绍了开发人员如何定制自己的服务,但这些
服务并不能被其它的应用程序访问,为了使其它的应用程序也可以访问本应用程序提供的服务,Android系统采用了
远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其它的基于RPC的解决方案一样,Android使用一种
接口定义语言(Interface Definition Language,IDL)来公开服务的接口,因此,可以将这种跨进程访问的服务称为
(Android Interface Definition Language)AIDL服务。
建立AIDL服务比普通的服务要复杂一些,具体步骤如下。
(1)在Eclipse Android工程的Java源文件目录中建立一个扩展名为aidl的文件,该文件的语法类似于Java代
码,但会稍不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,注意的是<action>标签中android:name的属性值就是客户端
要引用该服务的ID,也就是Intent类构造方法的参数值。
以下程序是服务端创建了一个简单的AIDL服务,这个服务有两个get方法,分别获取姓名和年龄,创建此AIDL服务的步骤
如下。
(1)建立一个aidl文件,如下图中的IPerson.aidl文件。
IPerson.aidl文件的内容如下:
<pre name="code" class="html">package com.aidl; interface IPerson{ String getName(); int getAge(); }
务不支持的数据类型例如:InputStream、OutputStream等内容。
(2)如果IPerson.adil文件中内容正确,ADT会自动生成一个IPerson.java文件。
(3)编写一个MyService类,该类继承自Service,在MyService类中定义了一个内联类PersonImpl,该类继承自
IPerson.Stub,MyService类的代码如下:
public class MyService extends Service{ public class PersonImpl extends IPerson.Stub{ @Override public String getName() throws RemoteException { return "bill"; } @Override public int getAge() throws RemoteException { return 25; } } @Override public IBinder onBind(Intent intent) { return new PersonImpl(); } }
(4)在AndroidManifest.xml文件中配置MyService类,代码如下:
<service android:name="com.example.aidlserviceproject.service.MyService"> <intent-filter > <action android:name="com.aidl.IPerson"/> </intent-filter> </service>
至此服务端的AIDL服务编写完成,接下来进行客户端代码的编写,新建工程,将服务端的自动生成的
IPerson.java文件连同包目录一起复制到客户端工程中,如下图:
以下程序实现了绑定AIDL服务,以及获取服务端数据:
public class MainActivity extends Activity implements OnClickListener{ private Button btn_aidl; private Button btn_get; private TextView tv_show; private Intent mIpItent; private IPerson mIpIPerson=null; private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { mIpIPerson=IPerson.Stub.asInterface(service); btn_get.setEnabled(true); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); initEvent(); } private void initData(){ mIpItent=new Intent("com.aidl.IPerson"); } private void initView(){ btn_aidl=(Button) this.findViewById(R.id.btn_aidl); btn_get=(Button) this.findViewById(R.id.btn_get); tv_show=(TextView) this.findViewById(R.id.tv_show); btn_get.setEnabled(false); } private void initEvent(){ btn_aidl.setOnClickListener(this); btn_get.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_aidl://绑定AIDL服务 bindService(mIpItent, conn, Context.BIND_AUTO_CREATE); break; case R.id.btn_get://获取服务端数据 try { tv_show.setText("姓名:"+mIpIPerson.getName()+"\n年龄:"+mIpIPerson.getAge()); } catch (RemoteException e) { e.printStackTrace(); } default: break; } } }
以上代码使用bindService方法来绑定AIDL服务,其中需要指定AIDL服务的ID,也就是<action>标签中的
android:name属性值。在绑定时需要一个ServiceConnection对象,当绑定成功,系统调用
ServiceConnection.onServiceConnected方法,通过此方法的service参数获取AIDL服务对象。最后先运行服务端程
序,再运行客户端程序。
效果如下:
AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据需要做更一步处理,AIDL服务支
持的数据类型如下。
(1)java的简单类型(int、char、boolean等),不需要导入。
(2)String和CharSequence,不需要导入。
(3)List和Map,List和Map对象的元素类型必须是AIDL服务支持的数据类型,不需要导入。
(4)AIDL自动生成的接口,需要导入。
(5)实现android.os.Parcelable接口的类,需要导入。
以下程序传递的数据类型是Person类,服务端代码如下:
(1)新建Person实现Parcelable接口
public class Person implements Parcelable{ private String name; private int age; public static final Parcelable.Creator<Person> CREATOR=new Creator<Person>() { @Override public Person[] newArray(int size) { return new Person[size]; } @Override public Person createFromParcel(Parcel source) { return new Person(source.readInt(),source.readString()); } }; public Person(){ } public Person(int age,String name){ this.name=name; this.age=age; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(age); dest.writeString(name); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Person实现android.os.Parcelable这个接口,该接口用于序列化对象,在Person类中必须有一个静态常量,常量
名必须是CREATOR,而且CREATOR常量的数据类型必须是Parcelable.Creator。在writeToParcel方法中需要将序列
化的值写入Parcel对象,注意,读取的顺序必须和写入的顺序保持一致。
(2)接着建立一个IPerson.aidl文件,代码如下:
package com.aidl; import com.aidl.Person; interface IPerson{ Person getPerson(); }
(3)建立一个Person.aidl文件,代码如下:
package com.aidl; parcelable Person;
(4)创建一个MyService类,代码如下:
public class MyService extends Service { public class PersonImpl extends IPerson.Stub { @Override public Person getPerson() throws RemoteException { Person person = new Person(); person.setName("bill"); person.setAge(25); return person; } } @Override public IBinder onBind(Intent intent) { return new PersonImpl(); } }
最后服务端的工程目录结构如下图:
OK,服务端的AIDL服务编写完毕,接着编写客户端程序,将服务端的Person.java与IPerson.aidl连同包一起复
制到客户端工程中,如下图:
以下代码实现了获取服务端的Person对象中的数据:
public class MainActivity extends Activity implements OnClickListener{ private Button btn_aidl; private Button btn_get; private TextView tv_show; private Intent mIpItent; private IPerson mIpIPerson=null; private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { mIpIPerson=IPerson.Stub.asInterface(service); btn_get.setEnabled(true); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); initEvent(); } private void initData(){ mIpItent=new Intent("com.bill.aidl.IPerson"); } private void initView(){ btn_aidl=(Button) this.findViewById(R.id.btn_aidl); btn_get=(Button) this.findViewById(R.id.btn_get); tv_show=(TextView) this.findViewById(R.id.tv_show); btn_get.setEnabled(false); } private void initEvent(){ btn_aidl.setOnClickListener(this); btn_get.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_aidl://绑定AIDL服务 bindService(mIpItent, conn, Context.BIND_AUTO_CREATE); break; case R.id.btn_get://获取服务端数据 try { Person person=mIpIPerson.getPerson(); tv_show.setText("姓名:"+person.getName()+"\n年龄:"+person.getAge()); } catch (RemoteException e) { e.printStackTrace(); } default: break; } } }
先运行服务端程序,在运行客户端程序,运行效果如下:
-------------------------------------------------------------------------------------------------------------------------------------------------------
转载请注明出处:http://blog.csdn.net/hai_qing_xu_kong/article/details/47748779情绪控
版权声明:本文为博主原创文章,未经博主允许不得转载。
关于Android中的四大组件(AIDL Service的使用)
标签:parcelable aidl service service android 四大组件
原文地址:http://blog.csdn.net/hai_qing_xu_kong/article/details/47748779