1 package org.robolectric.shadows; 2 3 import static org.robolectric.util.reflector.Reflector.reflector; 4 5 import android.content.BroadcastReceiver; 6 import android.content.BroadcastReceiver.PendingResult; 7 import android.content.Context; 8 import android.content.Intent; 9 import java.util.concurrent.atomic.AtomicBoolean; 10 import org.robolectric.annotation.Implementation; 11 import org.robolectric.annotation.Implements; 12 import org.robolectric.annotation.RealObject; 13 import org.robolectric.util.reflector.Direct; 14 import org.robolectric.util.reflector.ForType; 15 16 @Implements(BroadcastReceiver.class) 17 public class ShadowBroadcastReceiver { 18 @RealObject BroadcastReceiver receiver; 19 20 // The abort state of the currently processed broadcast 21 private AtomicBoolean abort = new AtomicBoolean(false); 22 private boolean wentAsync = false; 23 private PendingResult originalPendingResult; 24 25 @Implementation abortBroadcast()26 protected void abortBroadcast() { 27 // TODO probably needs a check to prevent calling this method from ordinary Broadcasts 28 abort.set(true); 29 } 30 31 @Implementation onReceive(Context context, Intent intent)32 protected void onReceive(Context context, Intent intent) { 33 if (abort == null || !abort.get()) { 34 receiver.onReceive(context, intent); 35 } 36 } 37 onReceive(Context context, Intent intent, AtomicBoolean abort)38 public void onReceive(Context context, Intent intent, AtomicBoolean abort) { 39 this.abort = abort; 40 onReceive(context, intent); 41 // If the underlying receiver has called goAsync(), we should not finish the pending result yet 42 // - they'll do that 43 // for us. 44 if (receiver.getPendingResult() != null) { 45 receiver.getPendingResult().finish(); 46 } 47 } 48 49 @Implementation goAsync()50 protected PendingResult goAsync() { 51 // Save the PendingResult before goAsync() clears it. 52 originalPendingResult = receiver.getPendingResult(); 53 wentAsync = true; 54 return reflector(BroadcastReceiverReflector.class, receiver).goAsync(); 55 } 56 wentAsync()57 public boolean wentAsync() { 58 return wentAsync; 59 } 60 getOriginalPendingResult()61 public PendingResult getOriginalPendingResult() { 62 if (wentAsync) { 63 return originalPendingResult; 64 } else { 65 return receiver.getPendingResult(); 66 } 67 } 68 69 @ForType(BroadcastReceiver.class) 70 interface BroadcastReceiverReflector { 71 72 @Direct goAsync()73 PendingResult goAsync(); 74 } 75 } 76