深入浅出 Android核心组件Service(4)

移动开发 Android
本文51CTO专栏作者傻蛋将向我们介绍深入浅出 Android核心组件Service第四部分的系列文章。

在Android平台中,一个进程通常不能访问其他进程中的内存区域的。但是,我们可以使用IDL语言来把对象伪装成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。

如果想在应用程序中调用其他进程中的Service,则需要用到AIDL,AIDL(android接口描述语言)是一种IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。

使用AIDL的方法如下:

1.首先要编写一个 IMusicService.aidl的服务接口,ADT会根据这个接口文件帮我们自动生成一个 Stub类,这个类继承了Binder类,同时继承了IMusicService这个接口,还可以看到其中包含了一个Proxy代理类,以实现远程代理,访问不同的进程。(aidl和Stub类如下所示)。

  1. /**  
  2.  * IMusicService.aidl  
  3.  * com.androidtest.service.mediaplayer  
  4.  *  
  5.  * Function: TODO   
  6.  *  
  7.  *   ver     date           author  
  8.  * ──────────────────────────────────  
  9.  *           2011-5-19      Leon  
  10.  *  
  11.  * Copyright (c) 2011, TNT All Rights Reserved.  
  12. */   
  13.    
  14. package com.zuiniuwang.service;   
  15. /**  
  16.  * ClassName:IMusicService  
  17.  * Function: TODO ADD FUNCTION  
  18.  * Reason:   TODO ADD REASON  
  19.  *  
  20.  * @author   Leon  
  21.  * @version    
  22.  * @since    Ver 1.1  
  23.  * @Date     2011-5-19  
  24.  */   
  25.    
  26.    
  27. interface IMusicService{   
  28.     void play();   
  29.     void pause();   
  30.     void stop();   
  31. }   

2. 生成的Stub类如下,我们暂不做详细讲解,后面的课程中我们会尝试自己来写一个类似的类,完成不同进程的访问。

  1. /*  
  2.  * This file is auto-generated.  DO NOT MODIFY.  
  3.  * Original file: E:\\myworkspace\\musicservice4\\src\\com\\zuiniuwang\\service\\IMusicService.aidl  
  4.  */   
  5. package com.zuiniuwang.service;   
  6. /**  
  7.  * ClassName:IMusicService  
  8.  * Function: TODO ADD FUNCTION  
  9.  * Reason:   TODO ADD REASON  
  10.  *  
  11.  * @author   Leon  
  12.  * @version    
  13.  * @since    Ver 1.1  
  14.  * @Date     2011-5-19  
  15.  */   
  16. public interface IMusicService extends android.os.IInterface   
  17. {   
  18. /** Local-side IPC implementation stub class. */   
  19. public static abstract class Stub extends android.os.Binder implements com.zuiniuwang.service.IMusicService   
  20. {   
  21. private static final java.lang.String DESCRIPTOR = "com.zuiniuwang.service.IMusicService";   
  22. /** Construct the stub at attach it to the interface. */   
  23. public Stub()   
  24. {   
  25. this.attachInterface(this, DESCRIPTOR);   
  26. }   
  27. /**  
  28.  * Cast an IBinder object into an com.zuiniuwang.service.IMusicService interface,  
  29.  * generating a proxy if needed.  
  30.  */   
  31. public static com.zuiniuwang.service.IMusicService asInterface(android.os.IBinder obj)   
  32. {   
  33. if ((obj==null)) {   
  34. return null;   
  35. }   
  36. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);   
  37. if (((iin!=null)&&(iin instanceof com.zuiniuwang.service.IMusicService))) {   
  38. return ((com.zuiniuwang.service.IMusicService)iin);   
  39. }   
  40. return new com.zuiniuwang.service.IMusicService.Stub.Proxy(obj);   
  41. }   
  42. public android.os.IBinder asBinder()   
  43. {   
  44. return this;   
  45. }   
  46. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException   
  47. {   
  48. switch (code)   
  49. {   
  50. case INTERFACE_TRANSACTION:   
  51. {   
  52. reply.writeString(DESCRIPTOR);   
  53. return true;   
  54. }   
  55. case TRANSACTION_play:   
  56. {   
  57. data.enforceInterface(DESCRIPTOR);   
  58. this.play();   
  59. reply.writeNoException();   
  60. return true;   
  61. }   
  62. case TRANSACTION_pause:   
  63. {   
  64. data.enforceInterface(DESCRIPTOR);   
  65. this.pause();   
  66. reply.writeNoException();   
  67. return true;   
  68. }   
  69. case TRANSACTION_stop:   
  70. {   
  71. data.enforceInterface(DESCRIPTOR);   
  72. this.stop();   
  73. reply.writeNoException();   
  74. return true;   
  75. }   
  76. }   
  77. return super.onTransact(code, data, reply, flags);   
  78. }   
  79. private static class Proxy implements com.zuiniuwang.service.IMusicService   
  80. {   
  81. private android.os.IBinder mRemote;   
  82. Proxy(android.os.IBinder remote)   
  83. {   
  84. mRemote = remote;   
  85. }   
  86. public android.os.IBinder asBinder()   
  87. {   
  88. return mRemote;   
  89. }   
  90. public java.lang.String getInterfaceDescriptor()   
  91. {   
  92. return DESCRIPTOR;   
  93. }   
  94. public void play() throws android.os.RemoteException   
  95. {   
  96. android.os.Parcel _data = android.os.Parcel.obtain();   
  97. android.os.Parcel _reply = android.os.Parcel.obtain();   
  98. try {   
  99. _data.writeInterfaceToken(DESCRIPTOR);   
  100. mRemote.transact(Stub.TRANSACTION_play, _data, _reply, 0);   
  101. _reply.readException();   
  102. }   
  103. finally {   
  104. _reply.recycle();   
  105. _data.recycle();   
  106. }   
  107. }   
  108. public void pause() throws android.os.RemoteException   
  109. {   
  110. android.os.Parcel _data = android.os.Parcel.obtain();   
  111. android.os.Parcel _reply = android.os.Parcel.obtain();   
  112. try {   
  113. _data.writeInterfaceToken(DESCRIPTOR);   
  114. mRemote.transact(Stub.TRANSACTION_pause, _data, _reply, 0);   
  115. _reply.readException();   
  116. }   
  117. finally {   
  118. _reply.recycle();   
  119. _data.recycle();   
  120. }   
  121. }   
  122. public void stop() throws android.os.RemoteException   
  123. {   
  124. android.os.Parcel _data = android.os.Parcel.obtain();   
  125. android.os.Parcel _reply = android.os.Parcel.obtain();   
  126. try {   
  127. _data.writeInterfaceToken(DESCRIPTOR);   
  128. mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);   
  129. _reply.readException();   
  130. }   
  131. finally {   
  132. _reply.recycle();   
  133. _data.recycle();   
  134. }   
  135. }   
  136. }   
  137. static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);   
  138. static final int TRANSACTION_pause = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);   
  139. static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);   
  140. }   
  141. public void play() throws android.os.RemoteException;   
  142. public void pause() throws android.os.RemoteException;   
  143. public void stop() throws android.os.RemoteException;   
  144. }   

3. 在Activity中得到Binder的方式,是通过Stub类的IMusicService.Stub.asInterface(binder)方法(这一点和以前不同)。相应的代码如下:

  1. /**  
  2.  * RemoteMusicPlayerActivity.java  
  3.  * com.androidtest.activity.musicplayer  
  4.  *  
  5.  * Function: TODO   
  6.  *  
  7.  *   ver     date           author  
  8.  * ──────────────────────────────────  
  9.  *           2011-5-20      Leon  
  10.  *  
  11.  * Copyright (c) 2011, TNT All Rights Reserved.  
  12.  */   
  13.    
  14. package com.zuiniuwang.playeractivity;   
  15.    
  16.    
  17.    
  18. import android.app.Activity;   
  19. import android.content.ComponentName;   
  20. import android.content.Context;   
  21. import android.content.Intent;   
  22. import android.content.ServiceConnection;   
  23. import android.os.Bundle;   
  24. import android.os.IBinder;   
  25. import android.util.Log;   
  26. import android.view.View;   
  27. import android.view.View.OnClickListener;   
  28. import android.widget.Button;   
  29.    
  30. import com.zuiniuwang.R;   
  31. import com.zuiniuwang.service.IMusicService;   
  32.    
  33. /**  
  34.  * ClassName:RemoteMusicPlayerActivity Function: TODO ADD FUNCTION Reason: TODO  
  35.  * ADD REASON  
  36.  *   
  37.  * @author Leon  
  38.  * @version  
  39.  * @since Ver 1.1  
  40.  * @Date 2011-5-20  
  41.  */   
  42. public class RemoteMusicPlayerActivity extends Activity implements   
  43.         OnClickListener {    
  44.    
  45.     private static final String TAG = RemoteMusicPlayerActivity.class   
  46.             .getSimpleName();   
  47.    
  48.     private Button playButton, pauseButton, stopButton, closeActivityButton,   
  49.             exitActivityButton;   
  50.    
  51.     private IMusicService musicServiceInterface;   
  52.    
  53.     @Override   
  54.     protected void onCreate(Bundle savedInstanceState) {   
  55.    
  56.         // TODO Auto-generated method stub   
  57.         super.onCreate(savedInstanceState);   
  58.         this.setContentView(R.layout.music_player_layout);   
  59.         findViews();   
  60.         bindViews();   
  61.         connection();   
  62.     }   
  63.    
  64.     private void findViews() {   
  65.         playButton = (Button) this.findViewById(R.id.play);   
  66.         pauseButton = (Button) this.findViewById(R.id.pause);   
  67.         stopButton = (Button) this.findViewById(R.id.stop);   
  68.         closeActivityButton = (Button) this.findViewById(R.id.close);   
  69.         exitActivityButton = (Button) this.findViewById(R.id.exit);   
  70.     }   
  71.    
  72.     private void bindViews() {   
  73.         playButton.setOnClickListener(this);   
  74.         pauseButton.setOnClickListener(this);   
  75.         stopButton.setOnClickListener(this);   
  76.         closeActivityButton.setOnClickListener(this);   
  77.         exitActivityButton.setOnClickListener(this);   
  78.     }   
  79.    
  80.     private void connection() {   
  81.         Intent intent = new Intent(   
  82.                 "com.androidtest.service.mediaplayer.RemoteMusicService");   
  83.         this.startService(intent);   
  84.         this.bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);   
  85.    
  86.     }   
  87.    
  88.     private ServiceConnection myServiceConnection = new ServiceConnection() {   
  89.    
  90.         @Override   
  91.         public void onServiceConnected(ComponentName name, IBinder binder) {   
  92.             musicServiceInterface = IMusicService.Stub.asInterface(binder);   
  93.             Log.d(TAG, " onServiceConnected");   
  94.         }   
  95.    
  96.         @Override   
  97.         public void onServiceDisconnected(ComponentName name) {   
  98.             musicServiceInterface = null;   
  99.             Log.d(TAG, " onServiceDisconnected");   
  100.         }   
  101.    
  102.     };   
  103.    
  104.     @Override   
  105.     public void onClick(View view) {   
  106.    
  107.         // TODO Auto-generated method stub   
  108.         try {   
  109.             switch (view.getId()) {   
  110.             case R.id.play:   
  111.                 Log.d(TAG, "play.......");   
  112.                 musicServiceInterface.play();   
  113.                 break;   
  114.             case R.id.pause:   
  115.                 Log.d(TAG, "pause.......");   
  116.                 musicServiceInterface.pause();   
  117.                 break;   
  118.             case R.id.stop:   
  119.                 Log.d(TAG, "stop.......");   
  120.                 musicServiceInterface.stop();   
  121.                 break;   
  122.             case R.id.close:   
  123.                 //Activity退出之前要解除绑定,不然会报错   
  124.                 this.unbindService(myServiceConnection);   
  125.                 Log.d(TAG, "close.......");   
  126.                 this.finish();   
  127.                 break;   
  128.             case R.id.exit:   
  129.                 Log.d(TAG, "exit.......");   
  130.                 this.unbindService(myServiceConnection);   
  131.                 this.stopService(new Intent("com.androidtest.service.mediaplayer.RemoteMusicService"));   
  132.                 this.finish();   
  133.    
  134.             }   
  135.    
  136.         } catch (Exception e) {   
  137.             e.printStackTrace();   
  138.         }   
  139.    
  140.     }   
  141.    
  142. }   

4. 最后在此Service注册的时候我们需要指定它是在一个不同的进程中运行的,本例子指定的是remote进程。注意 process参数。

  1.      <!-- 注册Service -->   
  2. <service android:enabled="true"   
  3.     android:name=".service.RemoteMusicService"  android:process=":remote">   
  4.     <intent-filter>   
  5.         <action android:name="com.androidtest.service.mediaplayer.RemoteMusicService" />   
  6.     </intent-filter>   
  7. </service>   

本节的源代码可在此下载:http://down.51cto.com/data/326382

责任编辑:佚名 来源: 最牛网
相关推荐

2012-02-07 14:37:01

Android核心组件Service

2012-02-07 15:09:03

Android核心组件Service

2012-02-07 15:29:17

Android核心组件Service

2012-02-07 14:45:52

Android核心组件Service

2012-02-21 13:55:45

JavaScript

2021-03-16 08:54:35

AQSAbstractQueJava

2011-07-04 10:39:57

Web

2011-05-05 14:44:43

SurfaceFlinSurfaceActivity

2013-11-14 15:53:53

AndroidAudioAudioFlinge

2022-05-06 07:19:11

DOMDiff算法

2021-07-20 15:20:02

FlatBuffers阿里云Java

2019-01-07 15:29:07

HadoopYarn架构调度器

2012-05-21 10:06:26

FrameworkCocoa

2017-07-02 18:04:53

块加密算法AES算法

2022-09-26 09:01:15

语言数据JavaScript

2022-01-13 09:38:25

Android架构设计

2022-12-02 09:13:28

SeataAT模式

2018-11-09 16:24:25

物联网云计算云系统

2022-01-11 07:52:22

CSS 技巧代码重构

2021-04-27 08:54:43

ConcurrentH数据结构JDK8
点赞
收藏

51CTO技术栈公众号