第5章 Android服务(Service)

Slides:



Advertisements
Similar presentations
网络应用程序设计 2014 JavaBean. JavaBean 及其属性 JavaBean 就是一种 Java 的组件技术 JavaBean 是 Java 类 JavaBean 通过约定的方法名实现属性功能 简单属性 void setXxx(Type value) Type getXxx() boolean.
Advertisements

7.1 内置对象概述及分类 JSP 视频教学课程. JSP2.2 目录 1. 内置对象简介 1. 内置对象简介 2. 内置对象分类 2. 内置对象分类 3. 内置对象按功能区分 3. 内置对象按功能区分 4. 内置对象作用范围 4. 内置对象作用范围.
面向侧面的程序设计 方林博士 本文下载地址:
第六 章数据库访问页 6.1 数据访问页视图 6.2 创建数据访问页 6.3 编辑数据访问页 6.4 查看数据访问页 退出.
第13章 繪圖與多媒體 13-1 顯示圖檔-行動相簿 13-2 音樂播放-音樂播放器 13-3 影片播放-視訊播放器
實驗五:多媒體播放器選單介面.
Part 2 開發Android應用程式的流程
位置與地圖應用 此投影片為講解Android如何取得定位經緯度和使用Google Map地圖.
第14章 c++中的代码重用.
在PHP和MYSQL中实现完美的中文显示
第10讲 Java面向对象编程基础(4) 教学目标 主要内容.
Android + Web Service 建國科技大學 資管系 饒瑞佶 2017/3 V1.
厦门大学数据库实验室 报告人:谢荣东 导师:林子雨 2014年8月30日
第7章 后台服务.
實驗四:單位轉換程式.
第7章 Android文件与本地数据库(SQLite)
Chapter 13 Android 實戰演練.
Android + JUnit 單元測試 建國科技大學資管系 饒瑞佶 2012/8/19V4.
Kvm异步缺页中断 浙江大学计算机体系结构实验室 徐浩.
實驗十三:顯示目前經緯度位置.
Ch06 再談選單元件 物件導向系統實務.
使用Android控制Arduino 史先强
第一个Android程序 本讲大纲: 1、创建Android应用程序 2、Android项目结构说明 3、运行Android应用程序
第8章 Android内容提供者(ContentProvider)应用
Chapter 7 Android應用元件 Android應用元件可以幫助我們獲得系統資源訊息(ActivityManager)、提供系統服務(Service)、搜尋系統服務(SearchManager)、監聽Intent訊息(Broadcast Receiver)以及資料共享(ContentProvider和ContentResolver)。
Chapter 6 進階UI設計.
第4章 Android生命周期.
第八章 菜单设计 §8.1 Visual FoxPro 系统菜单 §8.2 为自己的程序添加菜单 §8.3 创建快捷菜单.
CH7 佈局、按鈕與文字編輯元件.
Android + Service 建國科技大學 資管系 饒瑞佶.
實驗十四:顯示與控制地圖.
走进编程 程序的顺序结构(二).
辅导课程六.
第2讲 移动应用开发基础知识(二) 宋婕
网络常用常用命令 课件制作人:谢希仁.
第8章 Service解析.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第6章 建立Android使用介面 6-1 介面元件的基礎 6-2 Android的事件處理 6-3 按鈕元件 6-4 文字元件
第五讲 四则运算计算器(一) 精品教程《C#程序设计与应用(第2版)清华大学出版社 谭恒松 主编
9.1 程式偵錯 9.2 捕捉例外 9.3 自行拋出例外 9.4 自定例外類別 9.5 多執行緒
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
實驗十一:待辦事項程式 (儲存在手機上).
主编:钟元生 赵圣鲁.
SOA – Experiment 2: Query Classification Web Service
Android Application Component
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
$9 泛型基础.
C#面向对象程序设计 $6 深入理解类.
第四章 团队音乐会序幕: 团队协作平台的快速创建
Drupal Dev 我想知道:什么时候、什么变化.
實驗九:延續實驗八, 製作一個完整音樂播放器
VB与Access数据库的连接.
第二章 Java语法基础.
iSIGHT 基本培训 使用 Excel的栅栏问题
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
辅导课程十五.
第二章 Java基本语法 讲师:复凡.
本节内容 Windows线程切换_时钟中断切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
阻塞式模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
Android Speech To Text(STT)
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第2章 Java语言基础.
第9章 BroadcastReceiver的使用
Android进程间通讯.
第8章 创建与使用图块 将一个或多个单一的实体对象整合为一个对象,这个对象就是图块。图块中的各实体可以具有各自的图层、线性、颜色等特征。在应用时,图块作为一个独立的、完整的对象进行操作,可以根据需要按一定比例和角度将图块插入到需要的位置。 2019/6/30.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
Part 8 Broadcast Receiver、Service和App Widget
多个Activity的使用 本讲大纲: 1、使用Bundle在Activity之间交换数据 2、调用另一个Activity并返回结果
Presentation transcript:

第5章 Android服务(Service) QQ号:1281147324 QQ群:489059718(Android编程-清华版) 287966120(公共版) 网络资源:http://www.xs360.cn/book

主要内容

5.1 Service概述 5.1.1 Service介绍 Service是android 系统中的一种组件,它跟Activity的级别差不多,它们都是从Context派生出来的,但是它不能自己运行,只能在后台运行,并且可以和其它组件进行交互。它需要通过某一个Activity或者其他Context对象来调用。 文本

5.1.2 启动Service的两种方式 在Android系统中,常采用以下两种方式启动Service. (1)通过Context的startService()启动service后,访问者与service之间没有关联,该service将一直在后台执行,即使调用startservice的进程结束了,service仍然还存在,直到有进程调用stopService(),或者service自己停止(stopSelf)。这种情况下,service与访问者之间无法进行通信,数据交换,往往用于执行单一操作,并且没有返回结果。例如通过网络上传,下载文件,操作一旦完成,服务应该自动销毁。 (2)通过Context的bindService()绑定Service,绑定后Service就和调用bindService的组件同生共死了。也就是说当调用bindService()的组件销毁了,那么它绑定的Service也要跟着被结束,当然期间也可以调用unbindservice()让Service提前结束。 注意: 一个服务可以与多个组件绑定,只有当所有的组件都与之解绑后,该服务才会被销毁。

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

5.1.3 Service中常用方法 与开发其它Android组件类似,开发Service组件需要先开发一个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时都会回调onStartCommand()方法; boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。

5.1.3 Service中常用方法 开发Service组件需要先开发一个Service子类,然后在AndroidManifest.xml文件中配置该Service,配置时可通过<intent-filter…/>元素指定它可被哪些Intent启动。 在AndroidManifest.xml文件中配置Service: <service android:name=“.MyService”> <intent-filter> <action android:name=“iet.jxufe.cn.android.MyService”/> </intent-filter> </service> Action中的值一定要与程序中创建的Intent的Action的值一致,程序就是根据Action的值来查找相应的Service从而启动它。

5.1.2 Service中常用方法简介 通过Context的startService()启动Service后,访问者与Service之间没有关联,该Service将一直在后台执行,即使调用startService()的进程结束了,Service仍然还存在,直到有进程调用stopService(),或者Service自己自杀(stopSelf())。这种情况下,Service与访问者之间无法进行通信、数据交换。 通过Context的bindService()绑定Service后,Service就和 调用bindService()的组件同生共死了,也就是说当调用 bindService()的组件销毁了,那么它绑定的Service也要跟着被结束。

案例:FirstService 定义的Service子类必须实现onBind()方法,然后还需在AndroidManifest.xml文件中对该Service子类进行配置,配置时可通过<intent-filter...>元素指定它可被哪些Intent启动。下面具体来创建一个Service子类并对它进行配置,代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MyService.java public class MyService extends Service { private static final String TAG = "MyService"; public IBinder onBind(Intent arg0) { Log.i(TAG, "MyService onBind invoked!"); return myBinder; } public void onCreate() { Log.i(TAG, "MyService onCreate invoked!"); super.onCreate(); } public void onDestroy() { Log.i(TAG, "MyService onDestroy invoked!"); super.onDestroy(); quit=true; } public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "MyService onStartCommand invoked!"); return super.onStartCommand(intent, flags, startId); } →自定义服务类 →重写OnBind方法 →重写OnCreate方法 →重写OnDestory方法 →重写OnStartCommand方法

案例:FirstService 在上述代码中,创建了自定义的MyService类,该类继承了Android.app.Service类,并重写了onBind(),onCreate(),onStartCommand(),onDestory等方法,在每个方法中,通过LOG语句测试和查看该方法是否被调用。 定义完Service之后,还需在项目的AndroidManifest.xml文件中配置该Service,增加配置片段如下。 <service android:name=".MyService"> <intent-filter > <action android:name="iet.jxufe.cn.android.MyService"/> </intent-filter> </service>

案例:FirstService 虽然目前MyService已经创建并注册了,但系统仍然不会启动MyService,要想启动这个服务。必须显示地调用startService()方法。如果想停止服务,需要显示地调用stopService()方法,下面代码中,使用Activity作为Service的启动者,分别定义了启动Service和关闭Service两个按钮,并为它们添加了事件处理。 程序清单:/FirstService/src/iet/jxufe/cn/android/MainActivity.java public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start=(Button)findViewById(R.id.start); stop=(Button)findViewById(R.id.stop); final Intent intent=new Intent(); intent.setAction("iet.jxufe.cn.android.MyService"); start.setOnClickListener(new OnClickListener() { public void onClick(View v) { startService(intent); } }); stop.setOnClickListener(new OnClickListener() { stopService(intent); } }); } }

案例:FirstService 运行本节的例子后,第一次单击【启动Service】按钮后,在DDMS视图下的LogCat视图有如下图所示的输出。 然后单击【关闭Service】按钮,LogCat视图有如下图所示的输出。 下面按如下的单击顺序,重新测试一下本例。 【启动Service】→【启动Service】→【启动Service】→【停止Service】 测试完程序,查看LogCat控制台输出信息如下图所示。系统只在第一次单击【启动Service】按钮时调用onCreate()和onStartCommand()方法,再单击该按钮 时,系统只会调用onStartCommand()方法,而不会重复调用onCreate()方法。

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

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

5.1.4 绑定Service案例 在上一个案例中,添加两个按钮,一个用于绑定服务,一个用于解绑,然后分别为其添加事件处理。在绑定服务时,需要传递一个ServiceConnection对象,所以先创建该对象,代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MainActivity.java private ServiceConnection conn=new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { Log.i(TAG,"MainActivity onServiceDisconnected invoked!"); } public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG,"MainActivity onServiceConnected invoked!"); myBinder=(MyBinder)service; };

5.1.4 (绑定Service案例) 然后在MyService中添加两个与绑定Service相关的方法,onUnBind()和onRebind(),与其他方法类似,只是在方法体重打印出该方法被调用了信息,代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MyService.java public boolean onUnbind(Intent intent) { Log.i(TAG, "MyService onUnbind invoked!"); return super.onUnbind(intent); } public void onRebind(Intent intent) { Log.i(TAG, "MyService onRebind invoked!"); super.onRebind(intent);

5.1.4 (绑定Service案例) 最后在MainActivity中为绑定Service和解绑Service按钮添加事件处理,代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MainActivity.java public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bind=(Button)findViewById(R.id.bind); unbind=(Button)findViewById(R.id.unbind); final Intent intent=new Intent(); intent.setAction("iet.jxufe.cn.android.MyService"); bind.setOnClickListener(new OnClickListener() { public void onClick(View v) { bindService(intent, conn,Service.BIND_AUTO_CREATE); } }); unbind.setOnClickListener(new OnClickListener() { unbindService(conn);

5.1.4 (绑定Service案例) 程序执行后,单击绑定Service按钮,LogCat控制台打印信息如下图所示,首先调用onCreate()方法,然后调用onBind()方法。 程序执行后,单击解绑Service按钮,LogCat控制台打印信息如下图所示,首先调用onUnbind()方法,然后调用onDestory()方法。 程序运行后,单击绑定Service按钮,然后退出程序,LogCat控制台打印信息如下图。可以看出,程序退出后,Service会自动退出。

5.1.4 (绑定Service案例) 当单击绑定Service按钮后,再重复多次单击绑定Service按钮,查看控制台打印信息,发现程序并不会多次调用onBind()方法。 采用绑定服务的另一个优势是组件可以与Service之间进行通信,传递数据。这主要是通过IBinder对象进行的,因此需在Service中创建一个IBinder对象,然后让其作为onBind()方法的返回值返回,对数据的操作是放在IBinder对象中的。修改我们的MyService类,添加一个内部类MyBinder,同时在onCreate()方法中启动一个线程,模拟后台服务,该线程主要是做数据递增操作,在MyBinder类中,提供一个方法,可以获取当前递增的值(count的值),具体代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MyService.java

5.1.4 (绑定Service案例) public class MyService extends Service { private static final String TAG = "MyService"; private int count=0; private boolean quit=false; private MyBinder myBinder=new MyBinder(); public class MyBinder extends Binder { public MyBinder() { Log.i(TAG, "MyBinder Constructure invoked!"); } public int getCount() { return count; } } public IBinder onBind(Intent arg0) { Log.i(TAG, "MyService onBind invoked!"); return myBinder; } public void onCreate() { Log.i(TAG, "MyService onCreate invoked!"); super.onCreate(); →线程中循环是否停止的标志 →创建自定义的MyBinder对象 →MyBinder的构造方法,观察什么时候创建 →MyBinder中提供的获取数据的方法 →重写onBind()方法, 返回创建的对象

5.1.4 (绑定Service案例) new Thread(){ public void run(){ while(!quit){ try{ Thread.sleep(500); count++; System.out.println(); }catch (Exception e) { e.printStackTrace(); } }.start(); public void onDestroy() { Log.i(TAG, "MyService onDestroy invoked!"); super.onDestroy(); quit=true; →判断是否继续执行循环 →休眠0.5秒 →数据递增 →改变循环是否退出的标志,否则子线程一直在循环

5.1.4 (绑定Service案例) 接着在MainActivity中添加一个获取数据的按钮,获取数据的前提是要绑定Service,所以先绑定Service,在ServiceConnection()对象的onServiceConnected()方法中,获取绑定Service时,返回的IBinder对象,然后将该对象强制类型转换成MyBinder对象,最后利用MyBinder对象获取服务中的数据信息。 首先改写创建ServiceConnection对象的方法,关键代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MainActivity.java private ServiceConnection conn=new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { Log.i(TAG,"MainActivity onServiceDisconnected invoked!"); } public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG,"MainActivity onServiceConnected invoked!"); myBinder=(MyBinder)service; }; →将传递的参数强制类型装换成MyBinder对象

5.1.4 (绑定Service案例) 然后,为获取数据按钮添加事件处理方法,关键代码如下。 程序清单:/FirstService/src/iet/jxufe/cn/android/MainActivity.java getData.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(MainActivity.this, "Count="+myBinder.getCount(), Toast.LENGTH_LONG).show(); } }); →以消息的形式,显示获取的数据 此时,单击绑定服务后,LogCat控制台打印信息如下图,首先创建MyBinder对象,因为该对象是作为MyService的成员变量进行创建的,完成MyService的初始化工作,然后再调用onCreate()方法,再调用onBind()方法,该方法返回一个IBinder对象,因为IBinder对象不为空,表示有服务连接,所以会调用ServiceConnection借口的onServiceConnected()方法,并将调用IBinder对象它的第二个参数。

案例总结 1、通过Context的startService()方法启动和停止Service 2、通过Context的bindService()方法绑定和解除绑定 3、两种方式混合使用

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

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

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

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

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

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

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

5.2.2 建立AIDL文件 AIDL文件创建和java借口定义相类似,但在编写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,不能为其它标记。

5.2.2 建立AIDL文件 定义好AIDL接口之后(如Song.aidl),ADT工具会自动在gen目录下生成相应的包,并生成一个song.java接口,在该接口里包含一个Stub内部类,该内部类实现了IBender,Song两个接口,这个Stub类将会作为远Service的回调类。由于它实现了IBinder接口,因此可作为Service的onBind()方法的返回值。 程序清单:/AIDLServer/src/iet/jxufe/cn/android/Song.aidl package iet.jxufe.cn.android; interface Song{ String getName(); String getAuthor(); }

5.2.2 建立AIDL文件 AIDL使用时需注意: AIDL定义接口的源代码必须以.aidl结尾; AIDL接口中用到数据类型,除了基本类型、String、List、Map、CharSequence之外,其他类型全部都需要导包,即使它们在同一个包中也需要导包。 定义好AIDL接口之后(如Song.aidl),ADT工具会自动在gen目录下生成相应的包,并生成一个Song.java接口,在该接口里包含一个Stub内部类,该内部类实现了IBinder、Song两个接口,这个Stub类将会作为远程Service的回调类。它内部能实现一些功能。 开发客户端的第一步就是将Service端的AIDL接口文件复制到客户端应用中,复制到客户端后ADT工具会为AIDL接口生成相应的Java接口类。

5.2.3 建立AIDL服务端 远程Service的编写和本地Service很相似,只是远程Service中onBind()方法返回的IBinder对象不同,该Service代码如下。 程序清单:/AIDLServer/src/iet/jxufe/cn/android/AIDLServer.java public class AIDLServer extends Service { private String[] names=new String[]{"老男孩","春天里","在路上"}; private String[] authors=new String[]{"筷子兄弟","汪峰","刘欢"}; private String name,author; private SongBinder songBinder; private Timer timer=new Timer(); public class SongBinder extends Stub { public String getName() throws RemoteException { return name; } public String getAuthor() throws RemoteException { return author;

5.2.3 建立AIDL服务端 远程Service的编写和本地Service很相似,只是远程Service中onBind()方法返回的IBinder对象不同,该Service代码如下。 程序清单:/AIDLServer/src/iet/jxufe/cn/android/AIDLServer.java public IBinder onBind(Intent intent) { return songBinder; } public void onCreate() { songBinder=new SongBinder(); timer.schedule(new TimerTask() { public void run() { int rand=(int)(Math.random()*3); name=names[rand]; author=authors[rand]; System.out.println(rand); } }, 0,1000); public void onDestroy() { super.onDestroy(); timer.cancel(); } }

5.2.3 建立AIDL服务端 通过上面的程序可以看出,在远程Service中定义了一个SongBinder类,且该类继承Stub类,而Stub类继承了Binder类,并实现了Song接口,Binder类实现了IBinder接口。因此,与本地Service相比,开发远程Service要多定义一个AIDL接口。另外,程序中onBind()方法返回SongBinder类的对象实例,以便客户端获得服务对象,SongBinder对象的创建放在onCreate()方法中,因为onBind()方法在onCreate()方法之后被调用,因此onBind()方法的返回值不会为空。 接下来在AndroidManifest.xml文件中配置该Service类,配置Service类的代码如下: 程序清单:/AIDLServer/AndroidManifest.xml <service android:name=".AIDLServer"> <intent-filter> <action android:name="iet.jxufe.cn.android.AIDLServer"/> </intent-filter> </service>

5.2.4 建立AIDL客户端 客户端绑定远程Service与绑定本地Service的区别不大, 同样只需要三步: 1、创建ServiceConnection对象; 2、以ServiceConnection对象作为参数,调用Context的bindService()方法绑定远程Service。 3、将返回的IBinder对象的代理类转换成IBinder对象,从而调用Service中的相应方法。

5.2.4 建立AIDL客户端案例 通过一个按钮来获取远程Service的状态,并显示在两个文本框中。

5.2.4 建立AIDL客户端案例 public class MainActivity extends Activity { 程序清单:/AIDLClient/src/iet/jxufe/cn/android/client/MainActivity.java public class MainActivity extends Activity { private Button getData; private EditText name,author; private Song songBinder; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getData=(Button)findViewById(R.id.getData); name=(EditText)findViewById(R.id.name); author=(EditText)findViewById(R.id.author); final Intent intent=new Intent(); intent.setAction("iet.jxufe.cn.android.AIDLServer"); bindService(intent, conn, Service.BIND_AUTO_CREATE); getData.setOnClickListener(new OnClickListener() { public void onClick(View v) { try{ name.setText(songBinder.getName()); author.setText(songBinder.getAuthor()); } →用于获取其他进程数据的按钮 →显示获取的数据的文本编辑框 →用户交互的IBinder对象 →根据ID找到相应控件 →根据ID找到相应控件 →根据ID找到相应控件 →创建一个Intent对象 →设置Intent的特征 →绑定Service →添加单击事件处理 →显示获取的数据

5.2.4 建立AIDL客户端案例 catch(Exception ex){ ex.printStackTrace(); } }); private ServiceConnection conn=new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { songBinder=null; public void onServiceConnected(ComponentName name, IBinder service) { songBinder=Song.Stub.asInterface(service); }; protected void onDestroy() { super.onDestroy(); unbindService(conn); →创建ServiceConnection对象 →将代理类转换成IBinder对象 →销毁时解绑Service →解绑Service

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

5.3 调用系统服务案例 以下程序提供两个文本框,分别输入收信人的号码和发送的短信内容,通过点击“发送短信”按钮即可将短信发送出去。 程序清单:/SendMessage/res/layout/activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="20dp" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp" android:text="@string/num"/> <EditText android:id="@+id/num" android:inputType="number"/>

5.3 调用系统服务案例 以下程序提供两个文本框,分别输入收信人的号码和发送的短信内容,通过点击“发送短信”按钮即可将短信发送出去。 程序清单:/SendMessage/res/layout/activity_main.xml <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="18sp" android:text="@string/content"/> <EditText android:id="@+id/Mess" android:minLines="3"/> <Button android:layout_width="wrap_content" android:id="@+id/btn" android:text="@string/btn"/> </LinearLayout>

5.3 调用系统服务案例 以下程序提供两个文本框,分别输入收信人的号码和发送的短信内容,通过点击“发送短信”按钮即可将短信发送出去。 程序清单:/SendMessage/res/layout/activity_main.xml public class MainActivity extends Activity { EditText num, mess; Button btn; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); num = (EditText) findViewById(R.id.num); mess = (EditText) findViewById(R.id.Mess); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { String mobile=num.getText().toString(); String content=mess.getText().toString(); SmsManager smsManager = SmsManager.getDefault();

5.3 调用系统服务案例 以下程序提供两个文本框,分别输入收信人的号码和发送的短信内容,通过点击“发送短信”按钮即可将短信发送出去。 程序清单:/SendMessage/res/layout/activity_main.xml PendingIntent sentIntent = PendingIntent.getActivity( MainActivity.this, 0, new Intent(), 0); List<String> msgs = smsManager.divideMessage(content); for (String msg : msgs) { smsManager.sendTextMessage(mobile, null, msg sentIntent,null); } Toast.makeText(MainActivity.this, "短信发送完成!", Toast.LENGTH_SHORT).show(); });