Service依照其启动的方式,可分为两种:

1、Started

Started的Service。通过在Application里用startService(Intent
intent)方法来启动。这样的类型的Service一经启动。会在后面无休止地执行,即使启动它的Activity被Destroy掉。要停止此类型的Service,可在Service中调用stopSelf()或在Application中调用stopService(Intent intent),要不然就仅仅能等Android系统在系统资源紧张的时候把它杀掉。

2、Bound

Bound的Service。通过在Application里调用bindService()方法来启动。

该类型的Service与Application绑定在一起,一旦绑定的全部Application消失了,Android会Detroy掉该Service。也能够主动调用unbindService()方法来解绑Service。

有时候我们想在Activity中获知Service的状态,比如一个音乐播放器。Service负责音乐播放,Activity负责显示当前歌曲名和播放进度。

能够用Broadcast。这个也不失为一个解决方法。

但假设能够获取Service实例,那么就能够调用Service中自己定义的一些方法来获取Service状态了。

首先要明白的是,第一种类型的Service是无能为力的。

由于Activity与Service之间并没有相关联的接口。即使这个Service是在Activity里start的,一旦start,两者不再有关联。

一、本地Service调用。

假设Activity与Service在同一应用程序中。两者间的交互就属于本地Service调用。

可通过bindService实现。详细操作例如以下:

1、自己定义子类MyService。继承Service类

2、在MyService类中,自己定义内部类MyBinder,继承Binder类

在内部类中,依据须要交互的数据,创建一些方法,以便Activity可通过这些方法得到Service中的一些数据。或者干脆通过一个方法返回Service实例。

  1. public class MyBinder extends Binder
  2. {
  3. public MyService getServiceInstance()
  4. {
  5. return MyService.this;
  6. }
  7. }

3、在Service类中,new一个MyBinder私有成员。并在onBind()方法中return一个MyBinder实例。

之所以这样做,是由于Service一旦绑定,就会回调onBind()方法,并返回一个Binder对象给Activity。详细看下一个步骤。

4、在Activity中覆写ServiceConnection接口中的onServiceConnected(ComponentName name, IBinder service)方法,

当中的service參数就是MyService类中onBind()方法返回的MyBinder对象,调用MyBinder对象的自己定义方法getServiceInstance()可得到Service实例。

以下是一个DEMO:

  1. import android.os.Bundle;
  2. import android.os.IBinder;
  3. import android.app.Activity;
  4. import android.content.ComponentName;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.view.Menu;
  8. import android.view.View;
  9.  
  10. public class MainActivity extends Activity {
  11.  
  12. MusicInterface mi;
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_main);
  17. Intent intent = new Intent(this, MusicService.class);
  18. //混合调用
  19. //为了把服务所在进程变成服务进程
  20. startService(intent);
  21. //为了拿到中间人对象
  22. bindService(intent, new MusicServiceConn(), BIND_AUTO_CREATE);
  23. }
  24.  
  25. class MusicServiceConn implements ServiceConnection{
  26.  
  27. @Override
  28. public void onServiceConnected(ComponentName name, IBinder service) {
  29. // TODO Auto-generated method stub
  30. mi = (MusicInterface) service;
  31. }
  32.  
  33. @Override
  34. public void onServiceDisconnected(ComponentName name) {
  35. // TODO Auto-generated method stub
  36.  
  37. }
  38.  
  39. }
  40.  
  41. //開始播放button
  42. public void play(View v){
  43. mi.play();
  44. }
  45. //暂停播放button
  46. public void pause(View v){
  47. mi.pause();
  48. }
  49. }
  1. import android.app.Service;
  2. import android.content.Intent;
  3. import android.os.Binder;
  4. import android.os.IBinder;
  5.  
  6. public class MusicService extends Service{
  7. @Override
  8. public IBinder onBind(Intent intent) {
  9. // TODO Auto-generated method stub
  10. return new MusicController();
  11. }
  12.  
  13. //必须继承binder。才干作为中间人对象返回
  14. class MusicController extends Binder implements MusicInterface{
  15. public void play(){
  16. MusicService.this.play();
  17. }
  18. public void pause(){
  19. MusicService.this.pause();
  20. }
  21. }
  22.  
  23. public void play(){
  24. System.out.println("播放音乐");
  25. }
  26.  
  27. public void pause(){
  28. System.out.println("暂停播放");
  29. }
  30.  
  31. }
  1. public interface MusicInterface {
  2.  
  3. void play();
  4. void pause();
  5. }

二、跨进程Service调用

跨进程Service调用。即在当前应用程序中。调用还有一个应用程序中的Service。

由于Android中,每一个应用程序都执行于自己的进程中,拥有独立的Dalvik虚拟机实例,因而称为跨进程调用(Inter-Process Comunication)。

可通过AIDL服务来实现。

AIDL(Android Interface Definition Language),是Android定义的一种类似Java的语言。

主要用于定义跨进程调用时。服务端跟client用于数据交互的接口。



AIDL服务并不支持全部的Java数据类型。它仅仅支持下面的几种类型:

1、Java的简单类型(int, char, boolean等)。无需import

2、String和CharSequence。无需import

3、List和Map。无需import(应当注意的是:List和Map的元素类型必须是AIDL支持的)

4、AIDL自己主动生成的接口。须要import

5、实现android.os.Parcelable接口的类。须要import



建立简单的AIDL服务的过程例如以下:

(一)服务端步骤:

1、在服务端创建AIDL文件IMyAidl.aidl

AIDL与Java代码非常相近,演示样例代码例如以下:(注意:aidl文件后缀名为.aidl)

  1. interface IMyAidl
  2. {
  3. void print();
  4. }

创建完aidl文件后,ADT会自己主动调用aidl命令生成对应的Java文件。

可查看gen目录下是否有一个名为IMyAidl.java的文件。

假设没有,说明.aidl文件有误。



2、继承Service类,在子类中。将AIDL接口暴露出来。

这一步类似于本地Service调用,则通过onBind(Intent
intent)方法返回一个IBinder对象。

演示样例代码例如以下:

  1. public class MyService extends Service
  2. {
  3. private AidlBinder mBinder;
  4. //Stub类是上一步骤中,aidl命令生成的Java代码中的一个类
  5. //该类实现了IBinder接口和IMyAidl接口
  6. //能够通过继承该类,然后在onBind()方法中返回AidlBinder对象
  7. //如此一来。就可以通过AidlBinder对象对AIDL文件里定义的方法进行调用
  8. public class AidlBinder extends Stub
  9. {
  10. @Override
  11. public void print()
  12. {
  13. System.out.println("Hello world!")//实现AIDL文件里的接口函数
  14. }
  15. }
  16. @Override
  17. public void onCreate()
  18. {
  19. mBinder = new AidlBinder();//启动服务时即创建Binder对象
  20. }
  21.  
  22. @Override
  23. public IBinder onBind(Intent intent)
  24. {
  25. return mBinder;//返回Binder对象,让client获得Binder对象
  26. }
  27. }

3、配置AndroidManifest.xml文件

  1. <!-- 自己定义訪问Service所需的权限 -->
  2. <permission android:protectLevel="normal" android:name="thomas.permission.AIDL_SERVICE"/>
  3.  
  4. <service android:name="com.thomas.aidlserver.MyService" android:exported="true"
  5. android:permission="thomas.permission.AIDL_SERVICE">
  6. <!-- IntentFilter属性是不可缺少的 -->
  7. <!-- 如此一来,client才干通过该action远程调用服务端的Service -->
  8. <intent-filter>
  9. <action android:name="com.thomas.aidlserver.action.AIDL_SERVICE"/>
  10. </intent-filter>
  11. </service>

(二)client步骤:

1、创建AIDL文件

client也要创建AIDL文件,并且是跟服务端全然一样的AIDL文件。

复制服务端AIDL文件就可以。

应当注意的是:AIDL文件的包名一定要跟服务端的一致。

假设client没有该包。应创建一个包,并将AIDL文件放到包下。



2、跨进程调用Service

client跨进程调用Service的方法与本地调用Service的方法差点儿相同,也是通过bindService()。

应当注意的是。调用成功后。通过ServiceConnection接口中的onServiceConnected(ComponentName
name, IBinder service)方法得到服务端onBind()方法传递过来的Binder对象。

将该对象类型转化为AIDL文件里声明的接口类型,就可以调用该接口中定义的方法。

演示样例代码例如以下:

  1. private IMyAidl mAidl;
  2. mServiceCon = new ServiceConnection()
  3. {
  4. @Override
  5. public void onServiceConnected(ComponentName name, IBinder service)
  6. {
  7. //将IBinder类型转化为IMyAidl类型。
  8. mAidl = IMyAidl.Stub.asInterface(service);
  9. }
  10. @Override
  11. public void onServiceDisonnected(ComponentName name){}
  12. }
  13. //远程Service绑定,当中Intent的action參数是服务端在
  14. //AndroidManifest.xml文件里<service>标签下的<intent-filter>指定的字符串
  15. bindService(new Intent("com.thomas.aidlserver.action.AIDL_SERVICE"),
  16. mServiceCon, Service.BIND_AUTO_CREATE);
  17. mAidl.print();//调用AIDL文件里声明的方法

3、配置AndroidManifest.xml文件

  1. <!-- 请求訪问远程Service所需的权限,该权限定义于服务端的AndroidManifest.xml文件里 -->
  2. <uses-permission android:name="thomas.permission.AIDL_SERVICE"/>

Android--绑定服务调用服务的方法的更多相关文章

  1. Android(java)学习笔记229:服务(service)之绑定服务调用服务里面的方法 (采用接口隐藏代码内部实现)

    1.接口 接口可以隐藏代码内部的细节,只暴露程序员想暴露的方法 2.利用上面的思想优化之前的案例:服务(service)之绑定服务调用服务里面的方法,如下: (1)这里MainActivity.jav ...

  2. Android(java)学习笔记228:服务(service)之绑定服务调用服务里面的方法

    1.绑定服务调用服务里面的方法,图解: 步骤: (1)在Activity代码里面绑定 bindService(),以bind的方式开启服务 :                     bindServ ...

  3. Android(java)学习笔记172:服务(service)之绑定服务调用服务里面的方法 (采用接口隐藏代码内部实现)

    1. 接口 接口可以隐藏代码内部的细节,只暴露程序员想暴露的方法 2. 利用上面的思想优化之前的案例:服务(service)之绑定服务调用服务里面的方法,如下: (1)这里MainActivity.j ...

  4. Android(java)学习笔记171:服务(service)之绑定服务调用服务里面的方法

    1.绑定服务调用服务里面的方法,图解: 步骤: (1)在Activity代码里面绑定 bindService(),以bind的方式开启服务 :                     bindServ ...

  5. [android] 绑定方式开启服务&调用服务的方法

    需求:后台开启一个唱歌服务,这个服务里面有个方法切换歌曲 新建一个SingService继承系统Service 重写onCreate()和onDestory()方法 填一个自定义的方法changeSi ...

  6. 绑定方式开始服务&调用服务的方法

    1.编写activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/androi ...

  7. Android开发-API指南-服务

    Service 英文原文:http://developer.android.com/guide/components/services.html 采集(更新)日期:2014-12-23 原博客:htt ...

  8. WCF 服务调用 QueryRun

    通过AX2012的WCF服务调用AX2012的方法时,如果方法里调用了QueryRun对象时,会报错,报错信息如下:System.ServiceModel.FaultException: 无法将类型为 ...

  9. android 一个简单的服务例子

    public class MessageService extends Service { // 获取消息线程 private MessageThread messageThread = null; ...

随机推荐

  1. PHP mac xdebug配置

    PHP实现断点调试的条件 1. 需要PHP安装xdebug扩展 2. 修改PHP配置文件,开启xdebug扩展,并且对xdebug进行一些配置 3. 重启服务器如apach或nginx 4. 编译器配 ...

  2. Leetcode 477.汉明距离总和

    汉明距离总和 两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量. 计算一个数组中,任意两个数之间汉明距离的总和. 示例: 输入: 4, 14, 2 输出: 6 解释: 在二进制表示中, ...

  3. [automator篇][5]Viewer 提示connect to adb fail

    7. UIAutomatorViewer提示: Unable to connect to adb. Check if adb is installed correctly 解决,sdk升级到了25产生 ...

  4. javascript学习笔记 - 引用类型 基本包装类型

    六 基本包装类型 Boolean,Number,String 这三个引用类型亦称为基本包装类型,与基本的数据类型boolean,number,string相关联.为了方便操作这些基本类型的数据. 引用 ...

  5. POJ 2353 Ministry

    Ministry Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4220   Accepted: 1348   Specia ...

  6. google chrome & preferences & languages

    google chrome & preferences & languages language settings https://www.google.com/preferences ...

  7. 【bzoj1002】[FJOI2007]轮状病毒 矩阵树定理+高精度

    题目描述 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图所示 N轮状病 ...

  8. 刷题总结——Human Gene Functions(hdu1080)

    题目: Problem Description It is well known that a human gene can be considered as a sequence, consisti ...

  9. oracle 导出表结构信息

    直接贴sql: select cols.table_name 表名, cols.column_name 列名, cols.data_type 字段类型, cols.data_length 长度, co ...

  10. xsy 1836 - Shop

    from NOIP2016模拟题36 Description 商店里有n种背包和m种物品,物品体积为1到m,背包容积<=m 给出n个背包的容积 现在要求出这样一个物品集合,满足: 1)对于任意一 ...