码迷,mamicode.com
首页 > 移动开发 > 详细

关于Android中的四大组件(AIDL Service的使用)

时间:2015-08-18 19:21:18      阅读:398      评论:0      收藏:0      [点我收藏+]

标签:parcelable   aidl service   service   android   四大组件   

跨进程调用Service(AIDL Service)


Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。


在前一篇文章(关于Android中的四大组件(Service的开启与关闭))中介绍了开发人员如何定制自己的服务,但这些


服务并不能被其它的应用程序访问,为了使其它的应用程序也可以访问本应用程序提供的服务,Android系统采用了


远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其它的基于RPC的解决方案一样,Android使用一种


接口定义语言(Interface Definition Language,IDL)来公开服务的接口,因此,可以将这种跨进程访问的服务称为


(Android Interface Definition Language)AIDL服务。



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服务


以下程序是服务端创建了一个简单的AIDL服务,这个服务有两个get方法,分别获取姓名和年龄,创建此AIDL服务的步骤


如下。


(1)建立一个aidl文件,如下图中的IPerson.aidl文件。

技术分享


IPerson.aidl文件的内容如下:

<pre name="code" class="html">package com.aidl;
interface IPerson{
	String getName();
	int getAge();
}



IPerson.aidl文件的内容与Java代码非常相似,但要注意,不能加修饰符,比如:public、private,同时AIDL服


务不支持的数据类型例如: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();
	}

}

注意:以上的onBind()方法必须返回PersonImpl对象,否则客户端无法获得服务对象。


(4)在AndroidManifest.xml文件中配置MyService类,代码如下:


<service android:name="com.example.aidlserviceproject.service.MyService">
            <intent-filter >
                <action android:name="com.aidl.IPerson"/>
            </intent-filter>
</service>

注意:其中的“com.aidl.IPerson”是客户端用于访问AIDL服务的ID。


至此服务端的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服务传递一些复杂的数据需要做更一步处理,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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!