`
haliluya4
  • 浏览: 123457 次
  • 性别: 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与AIDL

    这篇博客“android笔记--Service与AIDL”深入探讨了这两者在Android开发中的应用。 Service的基本概念: 1. Service是一种轻量级的后台组件,它可以持续运行,即使用户已经离开了应用程序。Service并不运行在单独的...

    android service+aidl应用

    总结一下,Service和AIDL在Android开发中的作用是: 1. Service:提供后台运行的能力,用于执行长时间任务或与其他组件通信。 2. AIDL:实现进程间通信,让不同进程的组件可以调用另一进程Service的方法。 在实际...

    Android Service讲解 和 aidl 实现

    总结来说,`Android Service`是后台运行组件,用于执行长时间任务,而`AIDL`则提供了进程间通信的机制,使得Service能与客户端或者其他Service进行数据交换。在实际开发中,理解并熟练运用Service和AIDL,能够提升...

    Android startService bindService Aidl service基础全

    本文将深入探讨"Android startService, bindService, Aidl service基础全"这一主题,按照学习顺序依次讲解`testService`, `testBindService`, `testIntentService`, `testAidlClient+testAIDL`。 首先,我们来看`...

    Android Service学习之AIDL, Parcelable和远程服务

    总结,AIDL、Parcelable和远程服务是Android Service开发中不可或缺的部分。AIDL为进程间通信提供接口定义,Parcelable提高了数据传递效率,而远程服务则使得我们可以跨越进程边界调用Service的功能。理解并熟练掌握...

    AIDL Demo源码实现Activity与Service进程间通信

    本篇文章将深入探讨如何通过AIDL在Activity与Service之间进行进程间通信。 首先,理解AIDL的基本概念。AIDL是一种接口定义语言,它允许开发者声明接口,这些接口可以被其他进程调用。当一个Service在不同的进程中...

    Activity和Service通过aidl交互(跨进程)

    总结起来,通过AIDL,Android提供了跨进程通信的能力,使得应用A的Service可以被应用B调用。这在实现如插件化、模块化等高级功能时非常有用。在实际开发过程中,理解并熟练运用AIDL能够极大地提升应用的扩展性和灵活...

    通过aidl service调用activity

    总结,通过AIDL,我们可以使Service与Activity在不同进程中相互通信,实现跨进程调用。同时,Service还可以通过Intent启动Activity。在实际开发中,需要注意跨进程通信的安全性和效率,合理设计接口,以提供高效且...

    Activity中使用AIDL让Service与Activity通信

    总结起来,通过AIDL,我们可以方便地在Activity和Service之间进行跨进程通信,使得Service能够处理Activity传递的数据并提供结果。虽然这种方式相比直接在同一个进程中调用方法稍微复杂一些,但它提供了进程间通信的...

    一个及其简单的AIDL远程Service调用

    总结来说,这个简单的例子展示了如何使用AIDL在客户端和Service之间建立连接,进行数据传输。AIDL是Android IPC的重要工具,使得不同进程的应用组件能够协同工作,扩大了Android应用的功能范围。理解并熟练运用AIDL...

    AIDL_RemoteService

    总结来说,AIDL是Android中实现跨进程通信的关键工具,它简化了开发者处理复杂的IPC问题。理解并熟练掌握AIDL,能够帮助我们构建更健壮、可扩展的Android应用。通过定义清晰的服务接口,可以实现组件间的松耦合,...

    android aidl 之 system service 架构

    总结起来,AIDL在Android System Service架构中扮演着桥梁的角色,它使得系统服务能够跨越进程边界,为整个Android生态系统提供稳定且高效的通信机制。通过对AIDL的深入理解和应用,开发者可以充分利用系统服务的...

    android_service_and_aidl_server_client.zip

    总结来说,"android_service_and_aidl_server_client.zip"项目提供了一个实用的实例,展示了如何在Android中使用Service和AIDL进行进程间通信。开发者可以参考这个项目,学习如何在自己的应用中实现类似的通信机制。...

    Android的IPC与AIDL

    通过以上步骤,我们实现了Activity与Service之间的简单通信,展示了如何使用IBinder和AIDL实现进程间的通信过程。 #### 五、总结 Android的IPC机制是其架构设计中的一个重要组成部分,它不仅提高了应用的安全性和...

    安卓aidl学习源码

    **安卓AIDL学习源码详解** 在Android操作系统中,应用程序通常运行在各自的进程中,为了实现不同进程间的通信(IPC,Inter-Process Communication),Android提供了一种强大的机制——AIDL(Android Interface ...

    android aidl 复杂数据类型 传图片service

    总结起来,使用AIDL在Service中传递复杂类型如图片,需要对Android IPC机制有深入理解,包括AIDL接口定义、数据类型转换以及Service的生命周期管理。这是一个涉及到多方面技术的综合问题,需要开发者具备扎实的...

    AIDL 实现Service 双向 通讯 Demo

    总结一下,本Demo展示了如何利用AIDL实现在Android Service中的双向通信。具体步骤包括: 1. 创建AIDL接口,定义服务和客户端需要交换的方法。 2. 在服务端实现AIDL接口,并在`onBind()`中返回接口实例。 3. 客户端...

    Activity与远程Service通信,使用AIDL

    总结来说,AIDL在Activity与远程Service通信中扮演了关键角色,它使得两个不同进程间的对象能够透明地调用对方的方法。通过定义接口、实现接口、在Service中返回Binder实例以及在Activity中绑定Service,我们可以...

    使用AIDL通过进程APK之间通信

    总结,AIDL在Android中提供了强大的进程间通信能力,让开发者可以轻松地在不同的应用程序之间进行数据交换和服务调用。通过定义接口、实现服务、注册服务、连接服务和调用方法等步骤,我们就可以实现类似A.apk向B....

Global site tag (gtag.js) - Google Analytics