当前位置:   article > 正文

深入浅出 Android Service(4)_public void throws android.os.remoteexception;

public void throws android.os.remoteexception;
       在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. package com.zuiniuwang.service;
  14. /**
  15. * ClassName:IMusicService
  16. * Function: TODO ADD FUNCTION
  17. * Reason: TODO ADD REASON
  18. *
  19. * @author Leon
  20. * @version
  21. * @since Ver 1.1
  22. * @Date 2011-5-19
  23. */
  24. interface IMusicService{
  25. void play();
  26. void pause();
  27. void stop();
  28. }

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

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://download.csdn.net/detail/internetman/3967828  
有问题可以发表评论或者微博私信我。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/245336
推荐阅读
相关标签
  

闽ICP备14008679号