Android--绑定服务调用服务的方法

简介:

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实例。

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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.     //开始播放按钮  
  42.     public void play(View v){  
  43.         mi.play();  
  44.     }  
  45.     //暂停播放按钮  
  46.     public void pause(View v){  
  47.         mi.pause();  
  48.     }  
  49. }  


[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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.       
  14.     //必须继承binder,才能作为中间人对象返回  
  15.     class MusicController extends Binder implements MusicInterface{  
  16.         public void play(){  
  17.             MusicService.this.play();  
  18.         }  
  19.         public void pause(){  
  20.             MusicService.this.pause();  
  21.         }  
  22.     }  
  23.       
  24.     public void play(){  
  25.         System.out.println("播放音乐");  
  26.     }  
  27.       
  28.     public void pause(){  
  29.         System.out.println("暂停播放");  
  30.     }  
  31.   
  32.       
  33. }  
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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的语言。主要用于定义跨进程调用时,服务端跟客户端用于数据交互的接口。

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)

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. interface IMyAidl  
  2. {  
  3. void print();  
  4. }  

创建完aidl文件后,ADT会自动调用aidl命令生成相应的Java文件。可查看gen文件夹下是否有一个名为IMyAidl.java的文件。如果没有,说明.aidl文件有误。

2、继承Service类,在子类中,将AIDL接口暴露出来。
这一步类似于本地Service调用,则通过onBind(Intent intent)方法返回一个IBinder对象。
示例代码如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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对象,让客户端获得Binder对象  
  26. }  
  27. }  

3、配置AndroidManifest.xml文件

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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. <!-- 如此一来,客户端才能通过该action远程调用服务端的Service -->  
  8. <intent-filter>  
  9. <action android:name="com.thomas.aidlserver.action.AIDL_SERVICE"/>  
  10. </intent-filter>  
  11. </service>  

(二)客户端步骤:
1、创建AIDL文件
客户端也要创建AIDL文件,而且是跟服务端完全一样的AIDL文件。
复制服务端AIDL文件即可。应当注意的是:AIDL文件的包名一定要跟服务端的一致。
如果客户端没有该包,应创建一个包,并将AIDL文件放到包下。

2、跨进程调用Service
客户端跨进程调用Service的方法与本地调用Service的方法差不多,也是通过bindService()。
应当注意的是,调用成功后,通过ServiceConnection接口中的onServiceConnected(ComponentName name, IBinder service)方法得到服务端onBind()方法传递过来的Binder对象。将该对象类型转化为AIDL文件中声明的接口类型,即可调用该接口中定义的方法。
示例代码如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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文件

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <!-- 请求访问远程Service所需的权限,该权限定义于服务端的AndroidManifest.xml文件中 -->  
  2. <uses-permission android:name="thomas.permission.AIDL_SERVICE"/>  


转载:http://blog.csdn.net/chaoyu168/article/details/51078622

目录
相关文章
|
4月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
93 2
基于Android P,自定义Android开机动画的方法
|
4月前
|
Android开发
基于android-11.0.0_r39,系统应用的手动签名方法和过程
本文介绍了基于Android 11.0.0_r39版本进行系统应用手动签名的方法和解决签名过程中遇到的错误,包括处理`no conscrypt_openjdk_jni-linux-x86_64`和`RegisterNatives failed`的问题。
229 2
|
2月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
81 15
Android 系统缓存扫描与清理方法分析
|
2月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
34 1
|
3月前
|
ARouter 测试技术 API
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
51 2
|
3月前
|
JavaScript 前端开发 Android开发
让Vite+Vue3项目在Android端离线打开(不需要起服务)
让Vite+Vue3项目在Android端离线打开(不需要起服务)
126 10
|
3月前
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
276 6
|
3月前
|
安全 API 开发工具
Android平台RTMP推送|轻量级RTSP服务如何实现麦克风|扬声器声音采集切换
Android平台扬声器播放声音的采集,在无纸化同屏等场景下,意义很大,早期低版本的Android设备,是没法直接采集扬声器audio的(从Android 10开始支持),所以,如果需要采集扬声器audio,需要先做系统版本判断,添加相应的权限。
|
3月前
|
编解码 开发工具 Android开发
Android平台实现屏幕录制(屏幕投影)|音频播放采集|麦克风采集并推送RTMP或轻量级RTSP服务
Android平台屏幕采集、音频播放声音采集、麦克风采集编码打包推送到RTMP和轻量级RTSP服务的相关技术实现,做成高稳定低延迟的同屏系统,还需要有配套好的RTMP、RTSP直播播放器
|
4月前
|
Android开发
Android在rootdir根目录创建自定义目录和挂载点的方法
本文介绍了在Android高通平台的根目录下创建自定义目录和挂载点的方法,通过修改Android.mk文件并使用`LOCAL_POST_INSTALL_CMD`变量在编译过程中添加目录,最终在ramdisk.img的系统根路径下成功创建了`/factory/bin`目录。
241 1