Presentation is loading. Please wait.

Presentation is loading. Please wait.

第8章 Service解析.

Similar presentations


Presentation on theme: "第8章 Service解析."— Presentation transcript:

1 第8章 Service解析

2 本章知识结构图

3 本章示例

4 Service简介 什么是Service?
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background. Service与Activity类似,都是Android中四大组件之一,并且二者都是从Context派生而来,最大的区别在于Service没有实际的界面,而是一直在Android系统的后台运行,相当于是一个没有图形界面的Activity程序,它不能自己直接运行,需要借助Activity或其他Context对象启动。

5 Service的创建及常用方法 与开发其它Android组件类似,开发Service组件需从系统中的Service继承。系统中Service类包含的方法主要有: abstract IBinder onBind(Intent intent):该方法是一个抽象方法,所有Service子类必须实现该方法。该方法将返回一个IBinder对象,应用程序可通过该对象与Service组件通信; void onCreate():当Service第一次被创建时,将立即回调该方法; void onDestroy():当Service被关闭之前,将回调该方法; void onStartCommand(Intent intent,int flags,int startId):每次客户端调用startService(Intent intent)方法启动该Service时都会回调该方法; boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。

6 配置Service 定义Service子类时必须实现onBind()方法,然后还需在AndroidManifest.xml文件中进行配置,配置时可通过<intent-filter…/>元素指定它可被哪些Intent启动。 <service android:name=“.MyService”> <intent-filter> <action android:name=“iet.jxufe.cn.android.MyService”/> </intent-filter> </service> Action中的值一定要与程序中创建的Intent的Action的值一致,程序就是根据Action的值来查找相应的Service从而启动它。

7 运行Service的两种方式 通过Context的startService()启动Service后,访问者与Service之间没有关联,该Service将一直在后台执行,即使调用startService()的进程结束了,Service仍然还存在,直到有进程调用stopService(),或者Service自己自杀(stopSelf())。这种情况下,Service与访问者之间无法进行通信、数据交换。往往用于执行单一操作,并且没有返回结果。 通过Context的bindService()绑定Service后,Service就和调用bindService()的组件同生共死了,也就是说当调用bindService()的组件销毁了,那么它绑定的Service也要跟着被结束。当然期间也可以调用unbindservice()让Service提前结束。

8 运行Service的两种方式 以上两种方式也可以混合使用,即一个Service既可以启动也可以绑定,只需要同时实现onStartedCommand()(用于启动)和onBind()(用于绑定)方法,那么只有调用stopService(),并且调用unbindservice()方法后,该Service才会被销毁。 注意:服务运行在它所在进程的主线程,服务并没有创建它自己的线程,也没有运行在一个独立的进程上。如果服务中需做一些消耗CPU或者阻塞的操作,应该在服务中创建一个新的线程去处理。通过使用独立的线程,将会降低程序出现ANR(Application No Response程序没有响应)的风险,程序的主线程仍然可以保持与用户的交互。

9 绑定Service过程 Context的bindService()方法的完整方法签名为:bindService(Intent service,ServiceConnection conn, int flags),该方法的三个参数含义如下: service:该参数表示与服务类相关联的Intent对象,用于指定所绑定的Service; conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与Service之间的连接。当访问者与Service间连接成功时,将回调该ServiceConnection对象的onServiceConnected (ComponentName name,IBinder service)方法; flags:指定绑定时是否自动创建Service(如果Service还未创建)。该参数可指定BIND_AUTO_CREATE(自动创建)。

10 绑定Service 当开发Service类时,必须提供一个onBind()方法,在绑定本地Service的情况下,onBind()方法所返回的IBinder对象将会传给ServiceConnection对象里onServiceConnected(ComponentName name,IBinder service)方法的service参数,这样访问者就可以通过IBinder对象与Service进行通信。 实际开发时通常会采用继承Binder(IBinder的实现类)的方式实现自己的IBinder对象。

11 案例 1、通过startService()启动服务、stopService()停止服务
2、通过bindService()绑定服务、unbindService()解除绑定 3、两种方式混合使用 4、获取服务数据

12 Service详解 问题与讨论 两种方式混合使用时,方法的执行顺序是怎么样的? 1、先启动后绑定 2、先绑定后启动

13 案例总结 1)先启动Service,然后绑定Service。测试步骤:【启动Service】→【绑定Service】→【启动Service】→【停止Service】→【绑定Service】→【解绑Service】。 总结:调用顺序如下:onCreate()→[onStartCommand()1到N次] →onBind()→ onServiceConnected()→onUnbind()[→ onServiceConnected()→onRebind()0到N次]→onDestroy()。

14 案例总结 2)先绑定Service,后启动Service。测试步骤:【绑定Service】→【启动Service】→【绑定Service】→【解绑Service】→【启动Service】→【停止Service】。 总结:调用顺序如下:onCreate()→onBind()→onServiceConnected() →[onStartCommand() 1到N次]→onUnBind[→onServiceConnected() →onRebind()0到N次→onUnBind]→onDestroy()。

15 案例总结 注意: (1)未启动Service而直接停止Service不起作用,但未绑定Service而先解绑Service则程序出错,强制退出; (2)若该Service处于绑定状态下,该Service不会被停止即单击停止按钮不起作用,当单击解绑Service按钮时,它会先解除绑定随后直接销毁; (3)若在解除之前,没有单击停止Service,则只解绑而不会销毁。

16 Service的生命周期 每当Service被创建时会回调onCreate()方法,每次Service被启动时都会回调onStartCommand()方法,多次启动一个已有的Service组件将不会再回调onCreate()方法,但会回调onStartCommand()方法。 绑定服务的执行过程: 执行单击事件方法根据Intent找到相应的Service类,并初始化该类调用Service的onCreate()方法调用该类的onBind()方法调用onServiceConnected()方法。 多次单击绑定服务按钮,并不会重复执行绑定方法。一旦解绑,调用onUnbind()方法,然后自动销毁。

17 跨进程调用Service AIDL:Android Interface Definition Language
AIDL是一种接口定义语言,用于约束两个进程间通信规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。 进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应的对象。 由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员来说是透明的。

18 跨进程调用Service 客户端访问Service时,Android并不是直接返回Service对象给客 户端,Service只是将一个回调对象(IBinder对象)通过onBind()方法 回调给客户端。 与绑定本地Service不同的是,远程Service的onBind()方法只是将 IBinder对象的代理传给客户端的ServiceConnection的 onServiceConnected()的第二个参数。 当客户端获取了远程的Service的IBinder对象的代理之后,接下来可 通过该IBinder对象去回调远程Service的属性或方法。

19 建立AIDL文件 AIDL定义接口的源代码必须以.aidl结尾,接口名和aidl文件名相同;
AIDL接口中用到数据类型,除了基本类型、String、List、Map、CharSequence之外,其他类型全部都需要导包,即使它们在同一个包中也需要导包。 定义好AIDL接口之后(如Song.aidl),Android Studio集成开发工具会自动生成aidl文件夹,同时会在在build文件夹下生成相应的包,并生成一个Song.java接口,在该接口里包含一个Stub内部类,该内部类实现了IBinder、Song两个接口,这个Stub类将会作为远程Service的回调类。由于它实现了IBinder接口,因此可作为Service的onBind()方法的返回值。如果没有生成,可选择菜单栏中的buildClean Project 清理项目

20 客户端访问AIDLService 开发客户端的第一步就是将Service端的AIDL接口文件复制到客户端应用中。注意:复制时可切换到project视图下,然后把整个aidl文件夹复制过来 客户端绑定远程Service与绑定本地Service的区别不大,只需要三步: 创建一个ServiceConnection对象,需要实现ServiceConnection接口的两个方法; 将传给onServiceConnected()方法的IBinder对象的代理类转换成IBinder对象,从而利用IBinder对象调用Service中的相应方法; 将创建好的ServiceConnection对象作为参数,传给Context的bindService()方法绑定远程Service。

21 案例 设计并实现下图所示功能效果。单击按钮可获取远程Service中的数据,并显示在文本框中。

22 案例 假设A应用需要与B应用进行通信,调用B应用中的getName()、getAuthor()方法,B应用以Service方式向A应用提供服务。(我们可以把A应用看成是客户端,B应用看成是服务端,分别命名为AIDLClient 、AIDLServer)。整个过程需要以下几步: 1、在Server端编写AIDL文件 package cn.jxufe.iet.aidlserver;; interface Song{ String getName(); String getAuthor(); }

23 案例 编写Aidl文件时,需要注意: 1.接口名和aidl文件名相同;
2.接口和方法前不用加访问权限修饰符public,private等,也不能用final,static; 3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。 4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。 5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。 6.Java原始类型默认的标记为in,不能为其它标记。

24 案例 当完成aidl文件创建后,Android Studio集成开发工具会自动生成aidl文件夹,同时会在在build文件夹下生成相应的包,并生成一个Song.java接口。接口文件中生成一个Stub抽象类,里面包括aidl定义的方法,还包括一些其它辅助性的方法。 对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换。

25 案例 2、在ADILServer应用中实现aidl文件生成的接口(本例是Song),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口中的方法。 public class SongBinder extends Stub{ public String getName() throws RemoteException { return name; } public String getAuthor() throws RemoteException { return author; 3、把AIDLService应用中aidl文件复制到客户端应用中,。接下来即可在AIDLClient应用中实现与AIDLService应用通信。

26 调用系统服务 在Android系统中提供了很多内置服务类,通过它们提供的系列方法,可以获取系统相关信息。
发送短信需要调用系统的短信服务,主要用到SmsManager管理类,该类可以实现短信的管理功能,通过sendXxxMessage()方法进行短信的发送操作,例如sendTextMessage()方法用于发送文本信息 PendingIntent是对Intent的包装,一般通过调用Pendingintent的getActivity()、getService() 等静态方法来获取PendingIntent对象。与Intent对象不同的是:PendingIntent通常会传给其他应用组件,从而由其他应用程序来执行PendingIntent所包装的“Intent”。

27 案例 设计实现下图所示功能效果。界面中包含两个文本输入框和一个按钮,文本输入框分别输入收件人的号码以及要发送的信息。单击“发送”按钮即可发送短信。 提示:由于短信涉及到用户隐私,需要用户授权,对应的权限为:android.permission.SEND_SMS。

28 测试题 1.运行服务的两种方式是___________________和________________。
2.简述运行服务的两种方式的区别。 3.简述绑定服务执行的过程。 4.下列不属于Service生命周期的回调方法是 ( )。 A) onCreate() B) onBind() C) onStart() D) onStop() 5.在创建Service子类时,必须重写父类的以下哪个方法( )。 A) onCreate() B) onBind() C)onStartCommand() D)onDestroy() 6.ServiceConnection中onServiceConnected() 触发条件描述正确的是( )。 A) bindService()方法执行成功后。 B) bindService()方法执行成功同时onBind()方法返回非空IBinder对象。 C) Service的onCreate()方法和onBind()方法执行成功后。 D) Service的onCreate()和onStartCommand()方法启动成功后。

29


Download ppt "第8章 Service解析."

Similar presentations


Ads by Google