1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.N; 4 import static android.os.Build.VERSION_CODES.Q; 5 6 import android.app.Notification; 7 import android.app.NotificationManager; 8 import android.app.Service; 9 import android.content.Context; 10 import android.content.pm.ServiceInfo.ForegroundServiceType; 11 import org.robolectric.RuntimeEnvironment; 12 import org.robolectric.annotation.Implementation; 13 import org.robolectric.annotation.Implements; 14 import org.robolectric.annotation.RealObject; 15 16 @SuppressWarnings({"UnusedDeclaration"}) 17 @Implements(Service.class) 18 public class ShadowService extends ShadowContextWrapper { 19 @RealObject Service realService; 20 21 private int lastForegroundNotificationId; 22 private Notification lastForegroundNotification; 23 private boolean lastForegroundNotificationAttached = false; 24 private boolean selfStopped = false; 25 private boolean foregroundStopped; 26 private boolean notificationShouldRemoved; 27 private int stopSelfId; 28 private int stopSelfResultId; 29 private int foregroundServiceType; 30 31 @Implementation onDestroy()32 protected void onDestroy() { 33 if (lastForegroundNotificationAttached) { 34 lastForegroundNotificationAttached = false; 35 removeForegroundNotification(); 36 } 37 } 38 39 @Implementation stopSelf()40 protected void stopSelf() { 41 selfStopped = true; 42 } 43 44 @Implementation stopSelf(int id)45 protected void stopSelf(int id) { 46 selfStopped = true; 47 stopSelfId = id; 48 } 49 50 @Implementation stopSelfResult(int id)51 protected boolean stopSelfResult(int id) { 52 selfStopped = true; 53 stopSelfResultId = id; 54 return true; 55 } 56 57 @Implementation startForeground(int id, Notification notification)58 protected void startForeground(int id, Notification notification) { 59 foregroundStopped = false; 60 lastForegroundNotificationId = id; 61 lastForegroundNotification = notification; 62 lastForegroundNotificationAttached = true; 63 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE; 64 NotificationManager nm = 65 (NotificationManager) 66 RuntimeEnvironment.getApplication().getSystemService(Context.NOTIFICATION_SERVICE); 67 nm.notify(id, notification); 68 this.foregroundServiceType = 0; 69 } 70 71 @Implementation(minSdk = Q) startForeground( int id, Notification notification, @ForegroundServiceType int foregroundServiceType)72 protected void startForeground( 73 int id, Notification notification, @ForegroundServiceType int foregroundServiceType) { 74 startForeground(id, notification); 75 this.foregroundServiceType = foregroundServiceType; 76 } 77 78 @Implementation stopForeground(boolean removeNotification)79 protected void stopForeground(boolean removeNotification) { 80 foregroundStopped = true; 81 notificationShouldRemoved = removeNotification; 82 if (removeNotification) { 83 removeForegroundNotification(); 84 } 85 } 86 87 @Implementation(minSdk = Q) 88 @ForegroundServiceType getForegroundServiceType()89 protected int getForegroundServiceType() { 90 return foregroundServiceType; 91 } 92 93 @Implementation(minSdk = N) stopForeground(int flags)94 protected void stopForeground(int flags) { 95 if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) { 96 lastForegroundNotificationAttached = false; 97 } 98 stopForeground((flags & Service.STOP_FOREGROUND_REMOVE) != 0); 99 } 100 removeForegroundNotification()101 private void removeForegroundNotification() { 102 NotificationManager nm = 103 (NotificationManager) 104 RuntimeEnvironment.getApplication().getSystemService(Context.NOTIFICATION_SERVICE); 105 nm.cancel(lastForegroundNotificationId); 106 lastForegroundNotification = null; 107 lastForegroundNotificationAttached = false; 108 } 109 getLastForegroundNotificationId()110 public int getLastForegroundNotificationId() { 111 return lastForegroundNotificationId; 112 } 113 getLastForegroundNotification()114 public Notification getLastForegroundNotification() { 115 return lastForegroundNotification; 116 } 117 118 /** 119 * Returns whether the last foreground notification is still "attached" to the service, meaning it 120 * will be removed when the service is destroyed. 121 */ isLastForegroundNotificationAttached()122 public boolean isLastForegroundNotificationAttached() { 123 return lastForegroundNotificationAttached; 124 } 125 126 /** 127 * @return Is this service stopped by self. 128 */ isStoppedBySelf()129 public boolean isStoppedBySelf() { 130 return selfStopped; 131 } 132 isForegroundStopped()133 public boolean isForegroundStopped() { 134 return foregroundStopped; 135 } 136 getNotificationShouldRemoved()137 public boolean getNotificationShouldRemoved() { 138 return notificationShouldRemoved; 139 } 140 141 /** 142 * Returns id passed to {@link #stopSelf(int)} method. Make sure to check result of {@link 143 * #isStoppedBySelf()} first. 144 */ getStopSelfId()145 public int getStopSelfId() { 146 return stopSelfId; 147 } 148 149 /** 150 * Returns id passed to {@link #stopSelfResult(int)} method. Make sure to check result of {@link 151 * #isStoppedBySelf()} first. 152 */ getStopSelfResultId()153 public int getStopSelfResultId() { 154 return stopSelfResultId; 155 } 156 } 157