Android基本之Service

来源:互联网 发布:采用js实现评论和回复 编辑:程序博客网 时间:2024/05/16 05:22

一、Service的概念

Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台运行的组件。

Service需要注册到AndroidManifest.xml。

在不特别说明的情况下,即默认情况下,Service跟启动它的Activity处于同一个进程中;

在特定情况下,需要单独给Service开一个进程,则在AndroidManifest.xml中给Service添加一个android:process=":remote"这样一个标签,Android会在启动该Service的时候单独给它开一个进程。官方文档是这么说的:

The name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The <application> element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.

 

context

二、Service的生命周期

Service对象不能自己启动,需要通过某个Activity、Service或者其他Context对象来启动。

启动的方法有两种,Context.startService和Context.bindService()。

两种方式的生命周期是不同的,具体如下所示。

 

Context.startService方式的生命周期:
启动时,startService –> onCreate() –> onStart()
停止时,stopService –> onDestroy()

 

Context.bindService方式的生命周期:
绑定时,bindService -> onCreate() –> onBind()
解绑定时,unbindService –>onUnbind() –> onDestory()

 

如果你在Service 的onCreate或者onStart 做一些很耗时间的事情,最好在 Service 里启动一个线程来完成,因为Service是跑在主线程中,会影响到你的UI 操作或者阻塞主线程中的其他事情。

 

 

 需要Service实例源码可去这个地址下载:http://android.yaohuiji.com/archives/569

 

 


 

Activity如何远程调用Service的方法?需要可以通过AIDL实现。

AIDL的作用
由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。
通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

 

另外怎么实现Service主动给Activity发送事件/数据?通过RemoteCallbackList实现,具体看Api demos里的RemoteService.java,这个类定义了一个RemoteService类,及接口IRemoteService.Stub,ISecondary.Stub的具体实现, 另外还定义了两个内部Activity类,RemoteService.Controller,RemoteService.Binding, 用于测试远程service方法调用。在类Binding里实现了接口IRemoteServiceCallback.Stub的具体实现.

 

 

Note: 如果android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

 

Follow these steps to implement an IPC service using AIDL.

  1. Create your .aidl file - This file defines an interface (YourInterface.aidl) that defines the methods and fields available to a client.
  2. Add the .aidl file to your makefile - (the ADT Plugin for Eclipse manages this for you). Android includes the compiler, called AIDL, in the tools/ directory.
  3. Implement your interface methods - The AIDL compiler creates an interface in the Java programming language from your AIDL interface. This interface has an inner abstract class named Stub that inherits the interface (and implements a few additional methods necessary for the IPC call). You must create a class that extends YourInterface.Stub and implements the methods you declared in your .aidl file.
  4. Expose your interface to clients - If you're writing a service, you should extend Service and override Service.onBind(Intent) to return an instance of your class that implements your interface.  

A few rules about implementing your interface:

  • No exceptions that you throw will be sent back to the caller.
  • By default, IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete, you should not call it in the Activity/View thread, because it might hang the application (Android might display an "Application is Not Responding" dialog). Try to call them in a separate thread.
  • Only methods are supported; you cannot declare static fields in an AIDL interface.

Here are the steps a calling class should make to call your remote interface:

  1. Declare a variable of the interface type that your .aidl file defined.
  2. Implement ServiceConnection.
  3. Call Context.bindService(), passing in your ServiceConnection implementation.
  4. In your implementation of ServiceConnection.onServiceConnected(), you will receive an IBinder instance (called service). Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.
  5. Call the methods that you defined on your interface. You should always trap DeadObjectException exceptions, which are thrown when the connection has broken; this will be the only exception thrown by remote methods.
  6. To disconnect, call Context.unbindService() with the instance of your interface.

A few comments on calling an IPC service:

  • Objects are reference counted across processes.
  • You can send anonymous objects as method arguments.

 

  

 

If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.