`
haliluya4
  • 浏览: 122339 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

Service与AIDL学习小结

阅读更多

一个Service,从本质上来说,可以有两种形式。
1、 通过startService()启动。这种情况下,该Service与启动它的组件是完全独立的,即使组件被销毁,Service仍会继续,不会自动结束,而且通常情况下不返回任何结果。因此,应在Service执行完毕后调用stopSelf(int)(最好用带参数的,防止一个Service被多个组件请求的情况下,把还在执行的请求结束了)或其他组件调用stopService关闭Service。
2、 通过bindService()启动。其生命周期与绑定该Service的组件有关,可以多个组件绑定一个Service,但当所有组件都解绑后,该Service将被销毁。但是当有组件绑定一个Service时,该Service无法以stopService或stopSelf的方式终止。

默认情况下,任何组件都可以访问Service,但是我们可以在AndroidManifest.xml中将其声明为私有的,从而拒绝其他应用中的组件访问本应用的Service。通过设置intent-filter,可以使得Service能够被隐式调用。
同时,一个Service默认情况下运行在它的宿主进程的主线程(除非在AndroidManifest.xml中另行设置),因此,若要在一个Service中执行一些复杂的操作,最好在Service的执行代码中新建一个线程,在里面运行。这样能够降低系统出现Application Not Responding (ANR)错误的风险。
若只想在Activity运行时在后台执行某些操作,可以在Activity的onCreate中新建一个线程,在onStart中启动,在onStop中停止。而不是采用Service的方式。

创建过程:继承Service类,实现生命周期方法。与Activity不同,Service不需要调用父类方法。
1、 onStartCommand:当该Service被其他组件以startService的方式调用后,执行该方法。不同的返回值可以设置当系统内存不足时,对该Service的处理方式。START_NOT_STICKY:销毁后不自动创建。START_STICKY:销毁后重新创建Service,并执行onStartCommand,但传入的intent是空的。START_REDELIVER_INTENT:在START_STICKY基础上,传入了最后传入的那个intent。
2、 onBind:当该Service被其他组件以bindService的方式调用后,执行该方法。绑定后,该Service的生命周期就与绑定它的组件相关联。这种情况下,不用在代码里停止Service。要支持Service绑定,需要返回一个IBinder接口的实例(使用内部类继承Binder类定义并创建,Binder类实现了IBinder接口),在里面定义一些自己需要的方法,以便Service的绑定者与该Service之间的交互。

class MyBinder extends Binder{
	// 比如说,定义一个停止Service的方法
	public void stopService(){
		MyService.this.stopSelf();
	}
	// 甚至可以定义一个返回该Service对象的方法
	public MyService getService(){
		return MyService.this;
	}
}
@Override
public IBinder onBind(Intent arg0) {
	Log.d(TAG, "onBind");
	return new MyBinder();
}

 
然后就可以在Service的绑定者(比如说Activity)的代码里对其进行操作

MyService myService;
MyService.MyBinder localBinder;
// 定义ServiceConnection对象并在Service连接时获取相关对象
private ServiceConnection mConnection = new ServiceConnection() {
	@Override
	public void onServiceConnected(ComponentName className,IBinder binder)
{
		localBinder = (MyService.MyBinder) binder;
		myService = localBinder.getService();
	}
	@Override
	public void onServiceDisconnected(ComponentName arg0) {
	}
};
// 然后进行绑定
Intent intent2=new Intent();
intent2.setClass(context, MyService.class);
context.bindService(intent2, mConnection, Context.BIND_AUTO_CREATE);

 
3、 onCreate:只在Service第一次被创建时调用,其调用在onStartCommand与onBind之前。
4、 onDestroy:销毁时调用。

对于onStartCommand和onBind,可以只实现其中一种。
不能从BroadcastReceiver中调用bindService。但如果是用registerReceiver的方式注册过的BroadcastReceiver,由于其生命周期与Activity绑定,则可以。
IntentService是Service的子类,其中采用了一个工作者线程来处理所有的Intent请求(串行);当请求执行完毕后自动调用stopSelf方法;提供返回null的onBind的实现;提供onStartCommand的默认实现,并把请求转发至onHandleIntent方法(需自行实现)。若不需要所有请求同时处理,建议通过继承该类来实现Service。

前台Service:可以在通知栏中看到的Service。
当一个Service处于前台模式下时,系统不会在内存不足时销毁它。同时,前台Service需要在通知栏上显示一个图标及相应信息。并支持从通知栏启动相应的Activity。可以在Service的onStartCommand方法中根据传入的intent中的内容的不同,修改状态。

// service内执行
// 此处的title是一个通知生成时,在通知栏显示的提示消息
Notification notification = new Notification(R.drawable.icon, "title",System.currentTimeMillis());
// 为了能在通知栏拉下来后,点击通知能够打开Activity,使用了PendingIntent
Intent notificationIntent = new Intent(this, BroadcastActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// 此处的title2是把通知栏拉下来后,显示的标题。content即文本内容。
notification.setLatestEventInfo(this, "title2","content", pendingIntent);
// 设置为前台显示
startForeground(id, notification);

 
不想在前台显示时,在Service中执行stopForeground(true);即可。

只有Activity,Service,ContentProvider能够绑定Service,BroadcastReceiver不可以。
如果想要在每次绑定时都执行一遍onBind,要在onUnbind中返回true。否则,当下一次有组件绑定该服务时,将运行onRebind,而不是onBind。如下图:


 

进程间通信
当要在Service中支持IPC(进程间通信)时,可以使用Messenger(不需要多线程)或AIDL(需要支持多线程访问服务)。
Messenger:
1、 在Service中实现一个Handler,在它的handleMessage方法中处理包含不同Message的请求。
2、 在Service中创建Messenger对象(公共,参数是自定义Handler对象),在onBind时,使用Messenger的getBinder方法返回绑定的IBinder对象。
3、 调用时,在ServiceConnection类的onServiceConnected方法中,利用IBinder对象创建Messenger对象。然后在想要调用服务的地方使用它的send方法发送Message对象给Service。
AIDL
注:对AIDL的访问相当于函数调用,无法保证其运行在哪个线程。
对AIDL的调用是同步调用,调用完毕函数才返回。如果是比较耗时的工作,注意不要在主线程中调用,防止界面卡死(ANR)。
实现过程:
1、 定义AIDL文件,定义完后,Eclipse会自动在gen的相应目录生成一个.java文件。

interface MyAidl {
    int getPid();
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);
    void stopService();
}

 
2、 在自己实现的Service中,创建一个Stub类(Binder的子类,在.java中自动生成的)对象,给出相应方法的实现。

public class AidlBinder extends MyAidl.Stub{
	@Override
public void basicTypes(int anInt, long aLong, boolean 
aBoolean,float aFloat, double aDouble, String aString)
throws RemoteException
{
		Log.d(TAG, "basicTypes");
	}
	@Override
	public int getPid() throws RemoteException {
		Log.d(TAG, "getPid");
		return 0;
	}
	@Override
	public void stopService() throws RemoteException {
		MyService.this.stopSelf();
	}
}

 
3、 将Stub对象通过onBind传给调用者

@Override
	public IBinder onBind(Intent arg0) {
		return myAidlBinder;
	}

 
4、 在调用者的代码中,利用asInterface方法获取接口对象(若处于不同应用,调用者应能获取aidl文件,以便自动生成接口类)。

MyAidl aidl;
private ServiceConnection mConnection = new ServiceConnection() {
	@Override
	public void onServiceConnected(ComponentName 
	className,IBinder binder) {
		aidl=MyAidl.Stub.asInterface(binder);
	}
	@Override
	public void onServiceDisconnected(ComponentName arg0) {
	}
};

 

若要在AIDL中使用基本类型、String、CharSequence以外的数据类型,需要使用Parcelable,并指明方向。过程如下:
1、 定义一个类继承Parcelable,实现writeToParcel,以便将该类写入Parcel中(类似一个输出流)
2、 添加一个实现了Parcelable.Creator接口的名为CREATOR的静态变量

public class MyParcelable implements Parcelable {
	int num;
	double n2;
	String string;
	public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
		public MyParcelable createFromParcel(Parcel in) {
			return new MyParcelable(in);
		}
		public MyParcelable[] newArray(int size) {
			return new MyParcelable[size];
		}
	};
	public MyParcelable() {
	}
	private MyParcelable(Parcel in) {
		num = in.readInt();
		n2 = in.readDouble();
		string = in.readString();
	}
	@Override
	public int describeContents() {
		return 0;
	}
	@Override
	public void writeToParcel(Parcel out, int flag) {
		out.writeInt(num);
		out.writeDouble(n2);
		out.writeString(string);
	}
}

 
3、 创建一个MyParcelable.aidl文件,声明该类

package com.learn.aidl;
parcelable MyParcelable;

 
4、 在使用该类作为参数的aidl文件中import

import com.learn.aidl.MyParcelable;
interface MyAidl {
	MyParcelable getParcelable();
void setParcelable(in MyParcelable myParcelable);
}

 

 

  • 大小: 67.6 KB
分享到:
评论
1 楼 hao3100590 2012-01-03  
非常好!有参考价值

相关推荐

    Android Service大总结Demo

    Android Service大总结Demo 包括跨进程之间的通信。详情请参考博客

    ophone多媒体编程

    ophone应用开发权威指南的第七,八章,关于移动多媒体编程和程序后台运行,同时压缩包里还有这两章的源代码。 第7章 移动多媒体编程 274 7.1 多媒体文件格式与编码 274 7.1.1 多媒体文件格式 274 ...8.4 小结 353

    详解Android Service 使用时的注意事项

    最近有个项目刚好使用了Service,特别是AIDL远程服务,经过这次项目对Service有了更好的理解,在这里作个总结。 startService / bindService 混合使用 每一次调用 startService 都会回调onStartCommand,之后调用了...

    服务通信方案总结

    一共有两个项目,一个项目充当服务端,使用aidl进程通信控制另一个项目,播放音乐,其中还包括Activity和Service之间的通信方案,Parcel绑定和接口回调……

    《深入理解Android》卷Ⅰ

    第1章 阅读前的准备工作 1.1 系统架构 1.1.1 Android系统架构 1.1.2 本书的架构 1.2 搭建开发环境 1.2.1 下载源码 1.2.2 编译源码 1.3 工具介绍 1.3.1 Source Insight介绍 1.3.3 Busybox的使用 ...10.5 本章小结

    深入理解Android卷1全

    深入理解Android 卷1 不是扫描版的,是全版电子书的,非PDF,可编辑,各种阅览器以打开!包括书签和同步目录! 第1章 阅读前的准备工作 / 1 1.1 系统架构 / 2 1.1.1 Android系统架构 / 2 ...10.5 本章小结 / 488

    疯狂Android讲义源码

     1.7 本章小结 33  第2章 Android应用的界面编程 35  2.1 界面编程与视图(View)组件 36  2.1.1 视图组件与容器组件 36  2.1.2 使用XML布局文件控制UI  界面 40  2.1.3 在代码中控制UI界面 41  2.1.4 使用...

    疯狂Android讲义.part2

    第1章 Android应用与开发环境 1 1.1 Android的发展和历史 2 1.1.1 Android的发展和简介 2 1.1.2 Android平台架构及特性 3 1.2 搭建Android开发环境 5 1.2.1 下载和安装Android SDK 5 ...19.10 本章小结 689

    疯狂Android讲义.part1

    第1章 Android应用与开发环境 1 1.1 Android的发展和历史 2 1.1.1 Android的发展和简介 2 1.1.2 Android平台架构及特性 3 1.2 搭建Android开发环境 5 1.2.1 下载和安装Android SDK 5 ...19.10 本章小结 689

    Android典型技术模块开发详解

    目录 第一篇 Android开发初步 第1章 Android初识 1.1 Android简介 1.1.1 认识Android 1.1.2 Android系统框架 1.1.3 应用程序框架 1.2 Eclipse开发环境 1.2.1 安装ADT插件 1.2.2 安装SDK ...16.7 本章小结

    OPhone应用开发权威指南(黄晓庆)

    1.4 小结 11 第2章 OPhone开发环境和流程 12 2.1 安装Eclipse和ODT 12 2.1.1 安装Java SDK 12 2.1.2 安装Eclipse 13 2.1.3 安装OPhone SDK 13 2.1.4 安装和配置ODT插件 14 2.2 第一个OPhone应用程序 16 2.2.1 新建...

    Android中的Service相关全面总结

    1、Service的种类 按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在...

    Android开发案例驱动教程 配套代码

    本章小结 42 第4章 UI基础知识 43 4.1 Android UI组件概述 43 4.1.1 View 43 4.1.2 ViewGroup 44 4.1.3 布局管理器 44 4.2 UI设计工具 44 4.2.1 DroidDraw工具 44 4.2.2 ADT插件UI设计工具 46 4.3 事件处理...

    Android中使用 Messenger 实现进程间通信小案例与分析说明

    文章目录Messenger 是什么Messenger 底层实现Messenger 使用说明案例实现说明新建一个项目创建 ServiceService 代码说明客户端代码说明小结验证结果Messenger 工作原理总结 Messenger 是什么 Messenger 可以翻译为...

    深入理解Android:卷I--详细书签版

    8.3.5 初识Surface小结 309 8.4 深入分析Surface 310 8.4.1 与Surface相关的基础知识介绍 310 8.4.2 SurfaceComposerClient分析 315 8.4.3 SurfaceControl分析 320 8.4.4 writeToParcel和Surface对象的创建 ...

    Android 代码分析

    3 Android JAVA AIDL Analysis 15 4 Android JAVA Binder IPC System 20 5 Android Media Scanner Process 27 5.1 JAVA layer initialize 27 5.2 JAVA layer prescan 28 5.3 C++ layer processDirectory 28 5.4 JAVA...

    精通ANDROID 3(中文版)1/2

    1.8 小结  第2章 设置开发环境  2.1 设置环境  2.1.1 下载JDK 6  2.1.2 下载Eclipse 3.6  2.1.3 下载Android SDK  2.1.4 命令行窗口  2.1.5 安装ADT  2.2 了解基本组件  2.2.1 View  2.2.2 ...

    精通Android 3 (中文版)2/2

    1.8 小结  第2章 设置开发环境  2.1 设置环境  2.1.1 下载JDK 6  2.1.2 下载Eclipse 3.6  2.1.3 下载Android SDK  2.1.4 命令行窗口  2.1.5 安装ADT  2.2 了解基本组件  2.2.1 View  2.2.2 ...

Global site tag (gtag.js) - Google Analytics