当前位置:   article > 正文

Android IBinder的linkToDeath介绍及情景模拟_android linktodeatch机制

android linktodeatch机制

最近查看Framework源码的时候,读到了AudioService处理音量的流程,在这里碰到了IBinder的linkToDeath()这个知识点,比较感兴趣,所以记录下来,并自己写demo尝试了一下。

我们简单来看下AudioService处理静音这一块。
/frameworks/base/media/Java/Android/media/AudioManager.java

  1. public class AudioManager {
  2. ......
  3. /**
  4. * {@hide}
  5. */
  6. private final IBinder mICallBack = new Binder();
  7. public void setStreamMute(int streamType, boolean state) {
  8. IAudioService service = getService();
  9. try {
  10. service.setStreamMute(streamType, state, mICallBack);
  11. } catch (RemoteException e) {
  12. Log.e(TAG, "Dead object in setStreamMute", e);
  13. }
  14. }
  15. ......
  16. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

service是一个IAudioService,它的实现类是AudioService,AudioManager.setStreamMute()中会调用AudioService.setStreamMute(streamType, state, mICallBack);其中mICallBack是一个Binder用来记录申请静音的客户端。

/frameworks/base/media/java/android/media/AudioService.java

  1. private VolumeStreamState[] mStreamStates;
  2. //第1步
  3. /** @see AudioManager#setStreamMute(int, boolean) */
  4. public void setStreamMute(int streamType, boolean state, IBinder cb) {
  5. if (isStreamAffectedByMute(streamType)) {
  6. mStreamStates[streamType].mute(cb, state);
  7. }
  8. }
  9. public class VolumeStreamState {
  10. private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death
  11. private VolumeStreamState(String settingName, int streamType) {
  12. mVolumeIndexSettingName = settingName;
  13. mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
  14. mStreamType = streamType;
  15. mIndexMax = MAX_STREAM_VOLUME[streamType];
  16. AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
  17. mIndexMax *= 10;
  18. // mDeathHandlers must be created before calling readSettings()
  19. mDeathHandlers = new ArrayList<VolumeDeathHandler>();
  20. readSettings();
  21. }
  22. }
  23. //第2步
  24. public synchronized void mute(IBinder cb, boolean state) {
  25. VolumeDeathHandler handler = getDeathHandler(cb, state);
  26. if (handler == null) {
  27. Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
  28. return;
  29. }
  30. handler.mute(state);
  31. }
  32. private class VolumeDeathHandler implements IBinder.DeathRecipient {
  33. private IBinder mICallback; // To be notified of client's death
  34. private int mMuteCount; // Number of active mutes for this client
  35. VolumeDeathHandler(IBinder cb) {
  36. mICallback = cb;
  37. }
  38. //第3步
  39. // must be called while synchronized on parent VolumeStreamState
  40. public void mute(boolean state) {
  41. if (state) {
  42. if (mMuteCount == 0) {
  43. // Register for client death notification
  44. try {
  45. // mICallback can be 0 if muted by AudioService
  46. if (mICallback != null) {
  47. mICallback.linkToDeath(this, 0);
  48. }
  49. mDeathHandlers.add(this);
  50. // If the stream is not yet muted by any client, set level to 0
  51. if (muteCount() == 0) {
  52. Set set = mIndex.entrySet();
  53. Iterator i = set.iterator();
  54. while (i.hasNext()) {
  55. Map.Entry entry = (Map.Entry)i.next();
  56. int device = ((Integer)entry.getKey()).intValue();
  57. setIndex(0, device, false /* lastAudible */);
  58. }
  59. sendMsg(mAudioHandler,
  60. MSG_SET_ALL_VOLUMES,
  61. SENDMSG_QUEUE,
  62. 0,
  63. 0,
  64. VolumeStreamState.this, 0);
  65. }
  66. } catch (RemoteException e) {
  67. // Client has died!
  68. binderDied();
  69. return;
  70. }
  71. } else {
  72. Log.w(TAG, "stream: "+mStreamType+" was already muted by this client");
  73. }
  74. mMuteCount++;
  75. } else {
  76. if (mMuteCount == 0) {
  77. Log.e(TAG, "unexpected unmute for stream: "+mStreamType);
  78. } else {
  79. mMuteCount--;
  80. if (mMuteCount == 0) {
  81. // Unregister from client death notification
  82. mDeathHandlers.remove(this);
  83. // mICallback can be 0 if muted by AudioService
  84. if (mICallback != null) {
  85. mICallback.unlinkToDeath(this, 0);
  86. }
  87. if (muteCount() == 0) {
  88. // If the stream is not muted any more, restore its volume if
  89. // ringer mode allows it
  90. if (!isStreamAffectedByRingerMode(mStreamType) ||
  91. mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
  92. Set set = mIndex.entrySet();
  93. Iterator i = set.iterator();
  94. while (i.hasNext()) {
  95. Map.Entry entry = (Map.Entry)i.next();
  96. int device = ((Integer)entry.getKey()).intValue();
  97. setIndex(getIndex(device,
  98. true /* lastAudible */),
  99. device,
  100. false /* lastAudible */);
  101. }
  102. sendMsg(mAudioHandler,
  103. MSG_SET_ALL_VOLUMES,
  104. SENDMSG_QUEUE,
  105. 0,
  106. 0,
  107. VolumeStreamState.this, 0);
  108. }
  109. }
  110. }
  111. }
  112. }
  113. }
  114. public void binderDied() {
  115. Log.w(TAG, "Volume service client died for stream: "+mStreamType);
  116. if (mMuteCount != 0) {
  117. // Reset all active mute requests from this client.
  118. mMuteCount = 1;
  119. mute(false);
  120. }
  121. }
  122. }
  123. private synchronized int muteCount() {
  124. int count = 0;
  125. int size = mDeathHandlers.size();
  126. for (int i = 0; i < size; i++) {
  127. count += mDeathHandlers.get(i).mMuteCount;
  128. }
  129. return count;
  130. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142

它们的流程图如下(markdown画的图,不怎么美观)

AudioManagerAudioManagerAudioServiceAudioServiceVolumeStreamStateVolumeStreamStateVolumeDeathHandlerVolumeDeathHandlermute()mute()mute()mICallback.linkToDeath(this, 0)或者mICallback.unlinkToDeath(this, 0);

通过上面的代码我们可以得知VolumeDeathHandler继承IBinder.DeathRecipient.它可以监听申请静音的客户端的存活状态变化。
好吧,下面进入主题。

IBinder.DeathRecipient

  1. /**
  2. * Interface for receiving a callback when the process hosting an IBinder has gone away.
  3. *
  4. * @see #linkToDeath
  5. */
  6. public interface DeathRecipient {
  7. public void binderDied();
  8. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

它是IBinder的内部接口,接口方法void binderDied()。注释的意思大概是这是一个接受Binder所在的宿主进程消失时的回调,并且建议我们去查看linkToDeath。

  1. /**
  2. * Register the recipient for a notification if this binder
  3. * goes away. If this binder object unexpectedly goes away
  4. * (typically because its hosting process has been killed),
  5. * then the given {@link DeathRecipient}'s
  6. * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
  7. * will be called.
  8. *
  9. * <p>You will only receive death notifications for remote binders,
  10. * as local binders by definition can't die without you dying as well.
  11. *
  12. * @throws Throws {@link RemoteException} if the target IBinder's
  13. * process has already died.
  14. *
  15. * @see #unlinkToDeath
  16. */
  17. public void linkToDeath(DeathRecipient recipient, int flags)
  18. throws RemoteException;
  19. /**
  20. * Remove a previously registered death notification.
  21. * The recipient will no longer be called if this object
  22. * dies.
  23. *
  24. * @return Returns true if the <var>recipient</var> is successfully
  25. * unlinked, assuring you that its
  26. * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
  27. * will not be called. Returns false if the target IBinder has already
  28. * died, meaning the method has been (or soon will be) called.
  29. *
  30. * @throws Throws {@link java.util.NoSuchElementException} if the given
  31. * <var>recipient</var> has not been registered with the IBinder, and
  32. * the IBinder is still alive. Note that if the <var>recipient</var>
  33. * was never registered, but the IBinder has already died, then this
  34. * exception will <em>not</em> be thrown, and you will receive a false
  35. * return value instead.
  36. */
  37. public boolean unlinkToDeath(DeathRecipient recipient, int flags);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

注释说的很清楚,通过一个IBinder.linkToDeath()可以监听这个Binder本身的消失,并调用回调DeathRecipient.binderDied().IBinder.unlinkToDeath()可以取消监听。

Android的c/s服务架构中,难免会发生服务端或者客户端异常终止的情况,而通过IBinder.DeathRecipient可以很好处理这种情况,当IBinder对象异常终止时可以做一些资源释放的处理。

实战 情景模拟

之前说过在Framework代码中AudioService出现过IBinder.DeathRecipient,但是我内心蠢蠢欲动,我就是想自己实践看看效果。有没有方法呢?自然有。

接下来的Demo中我会创建两个App应用,一个作为服务端,一个作为客户端。客户端通过IBinder.DeathRecipient来监听服务端的异常终止情况。
服务端
ITest.aidl

  1. package com.example.deathrecipientdemo;
  2. interface ITest{
  3. void test();
  4. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

TestService.java

  1. package com.example.deathrecipientdemo;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.Binder;
  5. import android.os.IBinder;
  6. import android.os.RemoteException;
  7. import android.util.Log;
  8. public class TestService extends Service {
  9. private static final String TAG = "frank";
  10. private Binder mBinder = new ITest.Stub() {
  11. @Override
  12. public void test() throws RemoteException {
  13. // TODO Auto-generated method stub
  14. Log.i(TAG, "server");
  15. }
  16. };
  17. @Override
  18. public IBinder onBind(Intent intent) {
  19. // TODO Auto-generated method stub
  20. Log.i(TAG, "onBind");
  21. new Thread(new Runnable() {
  22. @Override
  23. public void run() {
  24. // TODO Auto-generated method stub
  25. try {
  26. Thread.sleep(10000);
  27. } catch (InterruptedException e) {
  28. // TODO Auto-generated catch block
  29. e.printStackTrace();
  30. Log.i(TAG,e.toString());
  31. }
  32. //结束自己
  33. android.os.Process.killProcess(android.os.Process.myPid());
  34. //TestService.this.stopSelf();
  35. //Log.i("test", "stopSelf");
  36. }
  37. }).start();
  38. return mBinder;
  39. }
  40. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

可以看到,它会在被启动时过10秒后自杀。

  1. <service android:name="com.example.deathrecipientdemo.TestService"
  2. android:enabled="true"
  3. android:exported="true">
  4. <intent-filter >
  5. <action android:name="com.frank.test"/>
  6. </intent-filter>
  7. </service>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

好了,以上是服务器App的部分代码。
接下我新建一个客户端的App

  1. package com.example.testdemo;
  2. public class MainActivity extends Activity {
  3. private static final String TAG = "frank";
  4. private ServiceConnection mCon;
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. Intent intent = new Intent();
  10. intent.setComponent(new ComponentName("com.example.deathrecipientdemo","com.example.deathrecipientdemo.TestService"));
  11. intent.setAction("com.frank.test");
  12. final DeathRecipient deathHandle = new DeathRecipient() {
  13. @Override
  14. public void binderDied() {
  15. // TODO Auto-generated method stub
  16. Log.i(TAG, "binder is died");
  17. }
  18. };
  19. mCon = new ServiceConnection() {
  20. @Override
  21. public void onServiceDisconnected(ComponentName name) {
  22. // TODO Auto-generated method stub
  23. Log.i(TAG, "onServiceDisconnected "+name.toShortString());
  24. }
  25. @Override
  26. public void onServiceConnected(ComponentName name, IBinder service) {
  27. // TODO Auto-generated method stub
  28. try {
  29. Log.i(TAG, "onServiceConnected "+name.toShortString()+" "+service.getInterfaceDescriptor());
  30. service.linkToDeath(deathHandle, 0);
  31. } catch (RemoteException e) {
  32. // TODO Auto-generated catch block
  33. e.printStackTrace();
  34. }
  35. }
  36. };
  37. bindService(intent,mCon,Context.BIND_AUTO_CREATE);
  38. }
  39. @Override
  40. protected void onDestroy() {
  41. // TODO Auto-generated method stub
  42. super.onDestroy();
  43. unbindService(mCon);
  44. }
  45. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

接下来就是验证时间,把两个App都装进了手机,先启动服务App,再启动客户端App,然后查看Log。我习惯于打开CMD,然后adb logcat | findstr frank。因为我在demo中将Log的TAG都设置为了frank.

按照理想中的预期,服务端被启动后10秒就会自杀,而自杀时客户端能够监听得到,真实情况是不是这样的呢?看log

  1. I/frank (17732): onBind
  2. I/frank (17475): onServiceConnected {com.example.deathrecipientdemo/com.example.deathrecipientdemo
  3. .TestService} com.example.deathrecipientdemo.ITest
  4. D/ActivityThread(17732): SVC-BIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy
  5. @5ebc3b5 intent=Intent { act=com.frank.test cmp=com.example.deathrecipientdemo/.TestService }}
  6. I/frank (17475): binder is died
  7. I/frank (17475): onServiceDisconnected {com.example.deathrecipientdemo/com.example.deathrecipientd
  8. emo.TestService}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

I/frank (17475): binder is died
这个被成功打印,所以代表我们实现成功了,我们能够准确运用IBinder.DeathRecipient接口去监听服务端的消失变动。当然实际开发中,我们要根据业务是否存在这样的需求而去编码,这里只作为学习探讨之用,反正我觉得涉及到服务之间的交互这个功能是很有用武之地的。

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

闽ICP备14008679号