`
coolxing
  • 浏览: 873888 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
9a45b66b-c585-3a35-8680-2e466b75e3f8
Java Concurre...
浏览量:97186
社区版块
存档分类
最新评论

android笔记--Service与AIDL

阅读更多

[coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.]

 

Service是android中的服务组件, 经常用来执行一些运行在后台的耗时操作. 使用一个Service需要继承Service类, 并根据需要重写生命周期方法. Service的生命周期如下:

|-- public abstract IBinder onBind (Intent intent): 该方法是一个抽象方法, 因此Service子类必须实现这个方法. 它返回一个IBinder对象, 应用程序可以通过这个对象与Service组件通信(关于这一点, 其后会有详细的讲解), 以bindService()方式启动Service时回调该方法.

|-- public void onCreate (): 当Service第一次被创建后回调的方法.

|-- public void onDestroy (): Service关闭之前回调的方法.

|-- public int onStartCommand (Intent intent, int flags, int startId): 以startService(Intent intent)的方式启动Service时, 系统都会回调该方法.

|-- public boolean onUnbind (Intent intent): 当所有绑定该Service的组件都断开连接时回调该方法.

 

从图中可以看出, Service可以有两种启动方式:

1. 以startService(Intent intent)的方式启动. 此时启动的Service与调用者之间没有关联, 即使调用者已经退出, Service仍然可以继续运行, 而且调用者和Service之间无法进行数据交换和通信. 如果需要停止Service的运行, 只能调用Context类的stopService(intent)方法, 或者由Service本身调用其stopSelf()等方法.

2. 以bindService(Intent service, ServiceConnection conn, int flags)的方式启动.

此时调用者与Service绑定在一起, 如果调用者退出, 则Service也随之退出, 而且调用者和Service之间可以进行数据交换或通信.

根据调用者和Service是否在一个应用程序内, 可以将调用者和Service之间的通信分为进程内通信和进程间通信.

 

 

a. 进程内通信. bindService(Intent service, ServiceConnection conn, int flags)方法的第二个参数为ServiceConnection对象, 最后一个参数通常可以是Service.BIND_AUTO_CREATE. ServiceConnection是一个接口, 该接口包含2个方法:

|-- onServiceConnected(ComponentName name, IBinder service): 该方法在调用者和Service成功绑定之后由系统回调.

方法中的第一个参数ComponentName是所绑定的Service的组件名称, 而IBinder对象就是Service中onBinder()方法的返回值. 要实现调用者和Service之间的通信, 只需要调用IBinder对象中定义的方法即可.

|-- onServiceDisconnected(ComponentName name): 该方法在调用者解除和Service的绑定之后由系统回调.

以下是利用Service实现进程内通信的一个例子.

首先自定义Service类:

 

public class MyService extends Service {

	public class MyBinder extends Binder {
		/**
		 * 获取Service的运行时间
		 * @return
		 */
		public long getServiceRunTime() {
			return System.currentTimeMillis() - startTime;
		}
	}
	
	private long startTime;
	
	/**
	 * MyBinder是Binder的子类, 而Binder实现了IBinder接口.
	 */
	@Override
	public IBinder onBind(Intent intent) {
		return new MyBinder();
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		startTime = System.currentTimeMillis();
	}
}
 

然后在activity中绑定上述的Service:

 

public class MainActivity extends Activity {
	private MyBinder binder = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// 创建一个指向MyService的intent
		Intent intent = new Intent("cn.xing.action.my_service");
		this.bindService(intent, new MyServiceConnection(),
				Service.BIND_AUTO_CREATE);

		Button button = (Button) this.findViewById(R.id.button);
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (binder != null) {
					Toast.makeText(getApplicationContext(), "MyService已经运行了" + binder.getServiceRunTime()
									+ "毫秒", Toast.LENGTH_LONG).show();
				} 
			}
		});
	}

	/**
	 * 实现ServiceConnection接口
	 * 
	 * @author xing
	 * 
	 */
	private final class MyServiceConnection implements ServiceConnection {
		/**
		 * 和MyService绑定时系统回调这个方法
		 */
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// MyService中的onBinder()方法的返回值实际上是一个MyBinder对象, 因此可以使用强制转换.
			binder = (MyBinder) service;
		}

		/**
		 * 解除和MyService的绑定时系统回调这个方法
		 */
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// 解除和MyService的绑定后, 将binder设置为null.
			binder = null;
		}

	}
}
 

b.进程间通信. 调用者和Service如果不在一个进程内, 就需要使用android中的远程Service调用机制.

android使用AIDL定义进程间的通信接口. AIDL的语法与java接口类似, 需要注意以下几点:

1. AIDL文件必须以.aidl作为后缀名.

2. AIDL接口中用到的数据类型, 除了基本类型, String, List, Map, CharSequence之外, 其他类型都需要导包, 即使两种在同一个包内. List和Map中的元素类型必须是AIDL支持的类型.

3. 接口名需要和文件名相同.

4. 方法的参数或返回值是自定义类型时, 该自定义的类型必须实现了Parcelable接口.

5. 所有非java基本类型参数都需要加上in, out, inout标记, 以表明参数是输入参数, 输出参数, 还是输入输出参数.

6. 接口和方法前不能使用访问修饰符和static, final等修饰.

 

下面通过一个例子来演示android远程Service调用机制的各个步骤:

1. 创建remoteService项目.

2. 在cn.xing.remoteservice包下定义aidl文件--IRemoteService.aidl:

 

package cn.xing.remoteservice;
interface IRemoteService{
	int getServiceRunTime();
}

Eclipse的ADT插件会在gen目录的cn.xing.remoteservice包下自动根据aidl文件生成IRemoteService接口. 

接口中有一个static的抽象内部类Stub, Stub类继承了Binder类并实现了IRemoteService接口. Stub类有如下的静态方法:

public static cn.xing.remoteservice.IRemoteService asInterface(android.os.IBinder obj)

该方法接受一个IBinder对象, 返回值是IRemoteService的instance, 通过这个instance我们就可以调用IRemoteService中定义的方法了.

3. 在remoteService项目的cn.xing.remoteservice包下创建远程服务类RemoteService:

 

public class RemoteService extends Service {
	private long startTime;
	
	/**
	 * IRemoteService.Stub类实现了IBinder和IRemoteService接口
	 * 因此Stub的子类对象可以作为onBinder()方法的返回值.
	 * @author xing
	 *
	 */
	public class MyBinder extends IRemoteService.Stub {
		@Override
		public long getServiceRunTime() throws RemoteException {
			return System.currentTimeMillis() - startTime;
		}
	};
	
	@Override
	public IBinder onBind(Intent intent) {
		return new MyBinder();
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		startTime = System.currentTimeMillis();
	}
}

4. 创建一个新的android项目invokeRemoteService, 并复制remoteService项目中的aidl文件(连同包结构一起复制)到invokeRemoteService项目中.

5. 在invokeRemoteService项目中绑定远程服务, 并调用远程方法.

 

public class MainActivity extends Activity {
	private IRemoteService iRemoteService = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// 创建一个指向RemoteService的intent
		Intent intent = new Intent("cn.xing.action.remote_service");
		this.bindService(intent, new MyServiceConnection(),
				Service.BIND_AUTO_CREATE);

		Button button = (Button) this.findViewById(R.id.button);
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (iRemoteService != null) {
					try {
						Toast.makeText(getApplicationContext(), "MyService已经运行了" + iRemoteService.getServiceRunTime()
										+ "毫秒", Toast.LENGTH_LONG).show();
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				} 
			}
		});
	}

	/**
	 * 实现ServiceConnection接口
	 * 
	 * @author xing
	 * 
	 */
	private final class MyServiceConnection implements ServiceConnection {
		/**
		 * 和RemoteService绑定时系统回调这个方法
		 */
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// 此处不能使用强制转换, 应该调用Stub类的静态方法获得IRemoteService接口的实例对象
			iRemoteService = IRemoteService.Stub.asInterface(service);
		}

		/**
		 * 解除和RemoteService的绑定时系统回调这个方法
		 */
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// 解除和RemoteService的绑定后, 将iRemoteService设置为null.
			iRemoteService = null;
		}
	}
}

 

附件中包含进程内通信和进程间通信例子的源码, 需要的朋友可自行下载查看.

 

7
1
分享到:
评论
10 楼 xiongjinpeng 2015-06-01  
不错,加深了理解,明白了进程内和进程间通信的区别
9 楼 issingleman 2014-11-18  
     
8 楼 Anennzxq 2014-10-04  
看了之后对Service有更深的了解,继续加油
7 楼 chu564544788 2014-04-16  
楼主写的真好!
6 楼 yun2223 2012-06-08  
楼主辛苦了  不够意思的朋友要回复了呵呵
5 楼 liuwuping1206 2012-03-04  
初学者表示说非常不错  呵呵。。。
4 楼 z303729470 2012-02-08  
嗯,写的不错,学习了
3 楼 Jefry 2011-11-27  
写的很好 我希望成为第二个留言的
2 楼 coolxing 2011-10-29  
mtain 写道
不错的知识!

开博以来, 你是第一个留言的. 谢谢.
有的时候觉得iteye上的朋友真是不够意思, 好像都很吝啬自己的评论.
1 楼 mtain 2011-10-29  
不错的知识!

相关推荐

    Android艺术探索-AIDL笔记code

    在Android系统中,AIDL(Android Interface Definition Language)是一种用于实现进程间通信(IPC, Inter-Process Communication)的工具,它是Android平台上的一个重要知识点。AIDL使得不同进程间的组件能够相互...

    Android群英传笔记-----by ---------刘某人程序员

    其次,笔记深入讲解了Android应用程序的生命周期管理,包括Activity、Service、BroadcastReceiver和ContentProvider的创建与使用。这部分内容对于理解和控制应用的行为至关重要,能确保你的程序在不同场景下运行稳定...

    【读博笔记】读《 Android高手进阶教程(二十五)之---Android 中的AIDL!!! 》笔记对应代码

    本笔记将深入探讨AIDL的基本概念、使用方法以及其在Android应用开发中的重要性。 首先,理解AIDL的初衷非常重要。在多进程环境下,Android系统中的两个或更多进程之间无法直接共享对象,因此需要一种机制来交换数据...

    xamarin学习笔记A19(安卓AIDL)

    AIDL是Android系统提供的一个工具,用于定义服务与不同进程之间交互的接口。它类似于Java中的RMI(Remote Method Invocation)或Web服务中的WSDL(Web Service Description Language)。AIDL使得应用程序可以在不同...

    android service 学习笔记(上)

    在《android service 学习笔记(下)》中,会介绍如何通过AIDL(Android Interface Definition Language)实现对Service的远程调用,这允许不同进程间的组件通信,增强了Service的功能和使用范围。 总结来说,...

    android service 学习笔记(下)

    在“android service 学习笔记(下)”中,主要讨论了如何利用AIDL(Android Interface Definition Language)进行跨进程通信(IPC, Inter-Process Communication)。 AIDL是一种接口描述语言,它的作用是在Android...

    Android service 服务 笔记

    这篇笔记主要围绕“Android service服务”展开,深入探讨服务的使用和实现方式,以及如何与其他组件进行交互。 首先,我们要了解服务的基本概念。Android中的Service并不是一个UI组件,它的主要功能是在后台执行长...

    Android群英传笔记

    接着,笔记可能会深入到Android应用的四大组件——活动(Activity)、服务(Service)、广播接收器(BroadcastReceiver)和内容提供者(ContentProvider)。活动是用户与应用交互的窗口,服务则在后台运行,不与用户...

    黑马Android基础笔记

    5. **Activity与Intent**:Activity是Android应用的主要交互单元,Intent则是连接不同Activity和Service的桥梁。学习如何创建和管理Activity,以及使用Intent传递数据和启动服务,是Android开发中的关键知识点。 6....

    AIDL跨进程调用学习笔记

    首先,我们需要理解AIDL的定义:它是Android提供的一种接口定义语言,允许我们定义服务(Service)如何公开其接口给其他应用程序组件,即使这些组件运行在不同的进程中。这种跨进程的通信方式对于构建大型、模块化的...

    Service基础学习笔记

    3. AIDL(Android Interface Definition Language):用于实现更复杂的进程间通信(IPC),使得不同进程间的Service可以相互调用方法。 五、Service的启动模式 1. START_STICKY:服务被杀死后,系统会重新创建并...

    Android-notes.zip_android

    12. **Android组件间通信**:包括使用Binder、AIDL,以及通过ContentProvider共享数据。笔记可能深入讨论这些高级话题。 13. **Android Jetpack组件**:这是Google推荐的一系列库,包括Lifecycle、Room、ViewModel...

    android 艺术开发探索 读书笔记(1-3章)

    ### Android艺术开发探索读书笔记(1-3章) #### 概述 《Android艺术开发探索》一书深入探讨了Android应用开发的核心技术和实践方法。本书第1至3章重点介绍了Activity生命周期、启动模式以及Android IPC机制等内容...

    Pro Android学习:Android service小例子

    这是Pro Android学习系列中Android Service部分的例子源代码。相关学习笔记见:http://blog.csdn.net/flowingflying/article/details/6212512

    Android组件自学笔记

    在Android开发领域,Android组件是构建应用程序的基础模块。...通过阅读"Note1(Activity&Context&Application&Service&AIDL)"这个笔记,初学者将能够逐步掌握这些基础概念,并为进一步深入Android开发打下坚实的基础。

    android开发资料大全

    Android 之 AIDL 和远程 Service 调用 Android 相对布局技巧 android开发环境之Logcat(日志)教程实例汇总 android网络通信之socket教程实例汇总 AsyncTask进度条加载网站数据到ListView 命令行开发、编译、打包...

    Aidl 练习

    2. **组件通信**:比如Activity和Service之间的通信,当Activity需要与另一个进程中运行的Service交互时,可以借助Aidl。 3. **多应用协作**:多个应用程序之间需要共享数据或协同工作,可以通过定义Aidl接口来实现...

    Android Binder入门学习笔记

    在Android中,Binder的使用通常与AIDL(Android Interface Definition Language)相结合。AIDL是一种接口定义语言,用于描述进程间通信的接口。当我们在项目中创建一个aidl文件,比如`IMath.aidl`: ```aidl ...

    Android核心知识.pdf

    - **Android组件间通信**:如AIDL(Android Interface Definition Language)用于跨进程通信。 - **Gradle构建系统**:理解和使用构建脚本,定制构建过程。 - **Android Studio**:集成开发环境的使用,包括调试、...

Global site tag (gtag.js) - Google Analytics