1 package org.robolectric.shadows; 2 3 import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; 4 import static android.app.PendingIntent.FLAG_IMMUTABLE; 5 import static android.app.PendingIntent.FLAG_NO_CREATE; 6 import static android.app.PendingIntent.FLAG_ONE_SHOT; 7 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; 8 import static org.assertj.core.api.Assertions.assertThat; 9 import static org.junit.Assert.fail; 10 import static org.robolectric.Shadows.shadowOf; 11 12 import android.app.Activity; 13 import android.app.PendingIntent; 14 import android.app.PendingIntent.CanceledException; 15 import android.content.Context; 16 import android.content.Intent; 17 import android.os.Build; 18 import android.os.Bundle; 19 import org.junit.Before; 20 import org.junit.Test; 21 import org.junit.runner.RunWith; 22 import org.robolectric.Robolectric; 23 import org.robolectric.RobolectricTestRunner; 24 import org.robolectric.RuntimeEnvironment; 25 import org.robolectric.annotation.Config; 26 27 @RunWith(RobolectricTestRunner.class) 28 public class ShadowPendingIntentTest { 29 30 private Context context; 31 32 @Before 33 public void setUp() { 34 context = RuntimeEnvironment.application; 35 } 36 37 @Test 38 public void getBroadcast_shouldCreateIntentForBroadcast() { 39 Intent intent = new Intent(); 40 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 99, intent, 100); 41 42 ShadowPendingIntent shadow = shadowOf(pendingIntent); 43 assertThat(shadow.isActivityIntent()).isFalse(); 44 assertThat(shadow.isBroadcastIntent()).isTrue(); 45 assertThat(shadow.isServiceIntent()).isFalse(); 46 assertThat(intent).isEqualTo(shadow.getSavedIntent()); 47 assertThat(context).isEqualTo(shadow.getSavedContext()); 48 assertThat(shadow.getRequestCode()).isEqualTo(99); 49 assertThat(shadow.getFlags()).isEqualTo(100); 50 } 51 52 @Test 53 public void getActivity_shouldCreateIntentForBroadcast() { 54 Intent intent = new Intent(); 55 PendingIntent pendingIntent = PendingIntent.getActivity(context, 99, intent, 100); 56 57 ShadowPendingIntent shadow = shadowOf(pendingIntent); 58 assertThat(shadow.isActivityIntent()).isTrue(); 59 assertThat(shadow.isBroadcastIntent()).isFalse(); 60 assertThat(shadow.isServiceIntent()).isFalse(); 61 assertThat(intent).isEqualTo(shadow.getSavedIntent()); 62 assertThat(context).isEqualTo(shadow.getSavedContext()); 63 assertThat(shadow.getRequestCode()).isEqualTo(99); 64 assertThat(shadow.getFlags()).isEqualTo(100); 65 } 66 67 @Test 68 public void getActivities_shouldCreateIntentForBroadcast() throws Exception { 69 Intent[] intents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 70 PendingIntent pendingIntent = PendingIntent.getActivities(context, 99, intents, 100); 71 72 ShadowPendingIntent shadow = shadowOf(pendingIntent); 73 assertThat(shadow.getSavedIntents()).isEqualTo(intents); 74 75 pendingIntent.send(); 76 ShadowApplication application = shadowOf(RuntimeEnvironment.application); 77 assertThat(application.getNextStartedActivity()).isEqualTo(intents[0]); 78 assertThat(application.getNextStartedActivity()).isEqualTo(intents[1]); 79 } 80 81 @Test 82 public void getActivities_withBundle_shouldCreateIntentForBroadcast() throws Exception { 83 Intent[] intents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 84 PendingIntent pendingIntent = 85 PendingIntent.getActivities(context, 99, intents, 100, Bundle.EMPTY); 86 87 ShadowPendingIntent shadow = shadowOf(pendingIntent); 88 assertThat(shadow.getSavedIntents()).isEqualTo(intents); 89 90 pendingIntent.send(); 91 ShadowApplication application = shadowOf(RuntimeEnvironment.application); 92 assertThat(application.getNextStartedActivity()).isEqualTo(intents[0]); 93 assertThat(application.getNextStartedActivity()).isEqualTo(intents[1]); 94 } 95 96 @Test 97 public void getService_shouldCreateIntentForBroadcast() { 98 Intent intent = new Intent(); 99 PendingIntent pendingIntent = PendingIntent.getService(context, 99, intent, 100); 100 101 ShadowPendingIntent shadow = shadowOf(pendingIntent); 102 assertThat(shadow.isActivityIntent()).isFalse(); 103 assertThat(shadow.isBroadcastIntent()).isFalse(); 104 assertThat(shadow.isServiceIntent()).isTrue(); 105 assertThat(intent).isEqualTo(shadow.getSavedIntent()); 106 assertThat(context).isEqualTo(shadow.getSavedContext()); 107 assertThat(shadow.getRequestCode()).isEqualTo(99); 108 assertThat(shadow.getFlags()).isEqualTo(100); 109 } 110 111 @Test 112 public void getActivities_nullIntent() { 113 try { 114 PendingIntent.getActivities(context, 99, null, 100); 115 fail("Expected NullPointerException when creating PendingIntent with null Intent[]"); 116 } catch (NullPointerException ignore) { 117 // expected 118 } 119 } 120 121 @Test 122 public void getActivities_withBundle_nullIntent() { 123 try { 124 PendingIntent.getActivities(context, 99, null, 100, Bundle.EMPTY); 125 fail("Expected NullPointerException when creating PendingIntent with null Intent[]"); 126 } catch (NullPointerException ignore) { 127 // expected 128 } 129 } 130 131 @Test 132 public void send_shouldFillInIntentData() throws Exception { 133 Intent intent = new Intent(); 134 Context context = Robolectric.setupActivity(Activity.class); 135 PendingIntent pendingIntent = PendingIntent.getActivity(context, 99, intent, 100); 136 137 Activity otherContext = Robolectric.setupActivity(Activity.class); 138 Intent fillIntent = new Intent().putExtra("TEST", 23); 139 pendingIntent.send(otherContext, 0, fillIntent); 140 141 Intent i = shadowOf(otherContext).getNextStartedActivity(); 142 assertThat(i).isNotNull(); 143 assertThat(i).isSameAs(intent); 144 assertThat(i.getIntExtra("TEST", -1)).isEqualTo(23); 145 } 146 147 @Test 148 public void send_shouldFillInLastIntentData() throws Exception { 149 Intent[] intents = {new Intent("first"), new Intent("second")}; 150 Context context = Robolectric.setupActivity(Activity.class); 151 PendingIntent pendingIntent = PendingIntent.getActivities(context, 99, intents, 100); 152 153 Activity otherContext = Robolectric.setupActivity(Activity.class); 154 Intent fillIntent = new Intent(); 155 fillIntent.putExtra("TEST", 23); 156 pendingIntent.send(otherContext, 0, fillIntent); 157 158 ShadowActivity shadowActivity = shadowOf(otherContext); 159 Intent first = shadowActivity.getNextStartedActivity(); 160 assertThat(first).isNotNull(); 161 assertThat(first).isSameAs(intents[0]); 162 assertThat(first.hasExtra("TEST")).isFalse(); 163 164 Intent second = shadowActivity.getNextStartedActivity(); 165 assertThat(second).isNotNull(); 166 assertThat(second).isSameAs(intents[1]); 167 assertThat(second.getIntExtra("TEST", -1)).isEqualTo(23); 168 } 169 170 @Test 171 public void send_shouldNotFillIn_whenPendingIntentIsImmutable() throws Exception { 172 Intent intent = new Intent(); 173 Context context = Robolectric.setupActivity(Activity.class); 174 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE); 175 176 Activity otherContext = Robolectric.setupActivity(Activity.class); 177 Intent fillIntent = new Intent().putExtra("TEST", 23); 178 pendingIntent.send(otherContext, 0, fillIntent); 179 180 Intent i = shadowOf(otherContext).getNextStartedActivity(); 181 assertThat(i).isNotNull(); 182 assertThat(i).isSameAs(intent); 183 assertThat(i.hasExtra("TEST")).isFalse(); 184 } 185 186 @Test 187 public void updatePendingIntent() { 188 Intent intent = new Intent().putExtra("whatever", 5); 189 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 190 ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent); 191 192 // Absent FLAG_UPDATE_CURRENT, this should fail to update the Intent extra. 193 intent = new Intent().putExtra("whatever", 77); 194 PendingIntent.getBroadcast(context, 0, intent, 0); 195 assertThat(shadowPendingIntent.getSavedIntent().getIntExtra("whatever", -1)).isEqualTo(5); 196 197 // With FLAG_UPDATE_CURRENT, this should succeed in updating the Intent extra. 198 PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT); 199 assertThat(shadowPendingIntent.getSavedIntent().getIntExtra("whatever", -1)).isEqualTo(77); 200 } 201 202 @Test 203 public void getActivity_withFlagNoCreate_shouldReturnNullIfNoPendingIntentExists() { 204 Intent intent = new Intent(); 205 assertThat(PendingIntent.getActivity(context, 99, intent, FLAG_NO_CREATE)).isNull(); 206 } 207 208 @Test 209 public void getActivity_withFlagNoCreate_shouldReturnNullIfRequestCodeIsUnmatched() { 210 Intent intent = new Intent(); 211 PendingIntent.getActivity(context, 99, intent, 0); 212 assertThat(PendingIntent.getActivity(context, 98, intent, FLAG_NO_CREATE)).isNull(); 213 } 214 215 @Test 216 public void getActivity_withFlagNoCreate_shouldReturnExistingIntent() { 217 Intent intent = new Intent(); 218 PendingIntent.getActivity(context, 99, intent, 100); 219 220 Intent identical = new Intent(); 221 PendingIntent saved = PendingIntent.getActivity(context, 99, identical, FLAG_NO_CREATE); 222 assertThat(saved).isNotNull(); 223 assertThat(intent).isSameAs(shadowOf(saved).getSavedIntent()); 224 } 225 226 @Test 227 public void getActivity_withNoFlags_shouldReturnExistingIntent() { 228 Intent intent = new Intent(); 229 PendingIntent.getActivity(context, 99, intent, 100); 230 231 Intent updated = new Intent(); 232 PendingIntent saved = PendingIntent.getActivity(context, 99, updated, 0); 233 assertThat(saved).isNotNull(); 234 assertThat(intent).isSameAs(shadowOf(saved).getSavedIntent()); 235 } 236 237 @Test 238 public void getActivities_withFlagNoCreate_shouldReturnNullIfNoPendingIntentExists() { 239 Intent[] intents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 240 PendingIntent pendingIntent = PendingIntent.getActivities(context, 99, intents, FLAG_NO_CREATE); 241 assertThat(pendingIntent).isNull(); 242 } 243 244 @Test 245 public void getActivities_withFlagNoCreate_shouldReturnNullIfRequestCodeIsUnmatched() { 246 Intent[] intents = {new Intent()}; 247 PendingIntent.getActivities(context, 99, intents, 0); 248 assertThat(PendingIntent.getActivities(context, 98, intents, FLAG_NO_CREATE)).isNull(); 249 } 250 251 @Test 252 public void getActivities_withFlagNoCreate_shouldReturnExistingIntent() { 253 Intent[] intents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 254 PendingIntent.getActivities(RuntimeEnvironment.application, 99, intents, 100); 255 256 Intent[] identicalIntents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 257 PendingIntent saved = 258 PendingIntent.getActivities(context, 99, identicalIntents, FLAG_NO_CREATE); 259 assertThat(saved).isNotNull(); 260 assertThat(intents).isSameAs(shadowOf(saved).getSavedIntents()); 261 } 262 263 @Test 264 public void getActivities_withNoFlags_shouldReturnExistingIntent() { 265 Intent[] intents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 266 PendingIntent.getActivities(RuntimeEnvironment.application, 99, intents, 100); 267 268 Intent[] identicalIntents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 269 PendingIntent saved = PendingIntent.getActivities(context, 99, identicalIntents, 0); 270 assertThat(saved).isNotNull(); 271 assertThat(intents).isSameAs(shadowOf(saved).getSavedIntents()); 272 } 273 274 @Test 275 public void getBroadcast_withFlagNoCreate_shouldReturnNullIfNoPendingIntentExists() { 276 Intent intent = new Intent(); 277 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 99, intent, FLAG_NO_CREATE); 278 assertThat(pendingIntent).isNull(); 279 } 280 281 @Test 282 public void getBroadcast_withFlagNoCreate_shouldReturnNullIfRequestCodeIsUnmatched() { 283 Intent intent = new Intent(); 284 PendingIntent.getBroadcast(context, 99, intent, 0); 285 assertThat(PendingIntent.getBroadcast(context, 98, intent, FLAG_NO_CREATE)).isNull(); 286 } 287 288 @Test 289 public void getBroadcast_withFlagNoCreate_shouldReturnExistingIntent() { 290 Intent intent = new Intent(); 291 PendingIntent.getBroadcast(context, 99, intent, 100); 292 293 Intent identical = new Intent(); 294 PendingIntent saved = PendingIntent.getBroadcast(context, 99, identical, FLAG_NO_CREATE); 295 assertThat(saved).isNotNull(); 296 assertThat(intent).isSameAs(shadowOf(saved).getSavedIntent()); 297 } 298 299 @Test 300 public void getBroadcast_withNoFlags_shouldReturnExistingIntent() { 301 Intent intent = new Intent(); 302 PendingIntent.getBroadcast(context, 99, intent, 100); 303 304 Intent identical = new Intent(); 305 PendingIntent saved = PendingIntent.getBroadcast(context, 99, identical, 0); 306 assertThat(saved).isNotNull(); 307 assertThat(intent).isSameAs(shadowOf(saved).getSavedIntent()); 308 } 309 310 @Test 311 public void getService_withFlagNoCreate_shouldReturnNullIfNoPendingIntentExists() { 312 Intent intent = new Intent(); 313 PendingIntent pendingIntent = PendingIntent.getService(context, 99, intent, FLAG_NO_CREATE); 314 assertThat(pendingIntent).isNull(); 315 } 316 317 @Test 318 public void getService_withFlagNoCreate_shouldReturnNullIfRequestCodeIsUnmatched() { 319 Intent intent = new Intent(); 320 PendingIntent.getService(context, 99, intent, 0); 321 assertThat(PendingIntent.getService(context, 98, intent, FLAG_NO_CREATE)).isNull(); 322 } 323 324 @Test 325 public void getService_withFlagNoCreate_shouldReturnExistingIntent() { 326 Intent intent = new Intent(); 327 PendingIntent.getService(context, 99, intent, 100); 328 329 Intent identical = new Intent(); 330 PendingIntent saved = PendingIntent.getService(context, 99, identical, FLAG_NO_CREATE); 331 assertThat(saved).isNotNull(); 332 assertThat(intent).isSameAs(shadowOf(saved).getSavedIntent()); 333 } 334 335 @Test 336 public void getService_withNoFlags_shouldReturnExistingIntent() { 337 Intent intent = new Intent(); 338 PendingIntent.getService(context, 99, intent, 100); 339 340 Intent identical = new Intent(); 341 PendingIntent saved = PendingIntent.getService(context, 99, identical, 0); 342 assertThat(saved).isNotNull(); 343 assertThat(intent).isSameAs(shadowOf(saved).getSavedIntent()); 344 } 345 346 @Test 347 public void cancel_shouldRemovePendingIntentForBroadcast() { 348 Intent intent = new Intent(); 349 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 99, intent, 100); 350 assertThat(pendingIntent).isNotNull(); 351 352 pendingIntent.cancel(); 353 assertThat(PendingIntent.getBroadcast(context, 99, intent, FLAG_NO_CREATE)).isNull(); 354 } 355 356 @Test 357 public void cancel_shouldRemovePendingIntentForActivity() { 358 Intent intent = new Intent(); 359 PendingIntent pendingIntent = PendingIntent.getActivity(context, 99, intent, 100); 360 assertThat(pendingIntent).isNotNull(); 361 362 pendingIntent.cancel(); 363 assertThat(PendingIntent.getActivity(context, 99, intent, FLAG_NO_CREATE)).isNull(); 364 } 365 366 @Test 367 public void cancel_shouldRemovePendingIntentForActivities() { 368 Intent[] intents = {new Intent(Intent.ACTION_VIEW), new Intent(Intent.ACTION_PICK)}; 369 PendingIntent pendingIntent = PendingIntent.getActivities(context, 99, intents, 100); 370 assertThat(pendingIntent).isNotNull(); 371 372 pendingIntent.cancel(); 373 assertThat(PendingIntent.getActivities(context, 99, intents, FLAG_NO_CREATE)).isNull(); 374 } 375 376 @Test 377 public void cancel_shouldRemovePendingIntentForService() { 378 Intent intent = new Intent(); 379 PendingIntent pendingIntent = PendingIntent.getService(context, 99, intent, 100); 380 assertThat(pendingIntent).isNotNull(); 381 382 pendingIntent.cancel(); 383 assertThat(PendingIntent.getService(context, 99, intent, FLAG_NO_CREATE)).isNull(); 384 } 385 386 @Test 387 public void send_canceledPendingIntent_throwsCanceledException() throws CanceledException { 388 Intent intent = new Intent(); 389 PendingIntent canceled = PendingIntent.getService(context, 99, intent, 100); 390 assertThat(canceled).isNotNull(); 391 392 // Cancel the existing PendingIntent and create a new one in its place. 393 PendingIntent current = PendingIntent.getService(context, 99, intent, FLAG_CANCEL_CURRENT); 394 assertThat(current).isNotNull(); 395 396 assertThat(shadowOf(canceled).isCanceled()).isTrue(); 397 assertThat(shadowOf(current).isCanceled()).isFalse(); 398 399 // Sending the new PendingIntent should work as expected. 400 current.send(); 401 402 // Sending the canceled PendingIntent should produce a CanceledException. 403 try { 404 canceled.send(); 405 fail("CanceledException expected when sending a canceled PendingIntent"); 406 } catch (CanceledException ignore) { 407 // expected 408 } 409 } 410 411 @Test 412 public void send_oneShotPendingIntent_shouldCancel() throws CanceledException { 413 Intent intent = new Intent(); 414 PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, FLAG_ONE_SHOT); 415 assertThat(shadowOf(pendingIntent).isCanceled()).isFalse(); 416 417 pendingIntent.send(); 418 assertThat(shadowOf(pendingIntent).isCanceled()).isTrue(); 419 assertThat(PendingIntent.getService(context, 0, intent, FLAG_ONE_SHOT | FLAG_NO_CREATE)) 420 .isNull(); 421 } 422 423 @Test 424 public void oneShotFlag_differentiatesPendingIntents() { 425 Intent intent = new Intent(); 426 PendingIntent oneShot = PendingIntent.getService(context, 0, intent, FLAG_ONE_SHOT); 427 PendingIntent notOneShot = PendingIntent.getService(context, 0, intent, FLAG_UPDATE_CURRENT); 428 assertThat(oneShot).isNotSameAs(notOneShot); 429 } 430 431 @Test 432 public void immutableFlag_differentiatesPendingIntents() { 433 Intent intent = new Intent(); 434 PendingIntent immutable = PendingIntent.getService(context, 0, intent, FLAG_IMMUTABLE); 435 PendingIntent notImmutable = PendingIntent.getService(context, 0, intent, FLAG_UPDATE_CURRENT); 436 assertThat(immutable).isNotSameAs(notImmutable); 437 } 438 439 @Test 440 public void testEquals() { 441 PendingIntent pendingIntent = 442 PendingIntent.getActivity(context, 99, new Intent("activity"), 100); 443 444 // Same type, requestCode and Intent action implies equality. 445 assertThat(PendingIntent.getActivity(context, 99, new Intent("activity"), FLAG_NO_CREATE)) 446 .isSameAs(pendingIntent); 447 448 // Mismatched Intent action implies inequality. 449 assertThat(PendingIntent.getActivity(context, 99, new Intent("activity2"), FLAG_NO_CREATE)) 450 .isNull(); 451 452 // Mismatched requestCode implies inequality. 453 assertThat(PendingIntent.getActivity(context, 999, new Intent("activity"), FLAG_NO_CREATE)) 454 .isNull(); 455 456 // Mismatched types imply inequality. 457 assertThat(PendingIntent.getBroadcast(context, 99, new Intent("activity"), FLAG_NO_CREATE)) 458 .isNull(); 459 assertThat(PendingIntent.getService(context, 99, new Intent("activity"), FLAG_NO_CREATE)) 460 .isNull(); 461 } 462 463 @Test 464 public void testEquals_getActivities() { 465 Intent[] intents = {new Intent("activity"), new Intent("activity2")}; 466 PendingIntent pendingIntent = PendingIntent.getActivities(context, 99, intents, 100); 467 468 Intent[] forward = {new Intent("activity"), new Intent("activity2")}; 469 assertThat(PendingIntent.getActivities(context, 99, forward, FLAG_NO_CREATE)) 470 .isSameAs(pendingIntent); 471 472 Intent[] irrelevant = {new Intent("irrelevant"), new Intent("activity2")}; 473 assertThat(PendingIntent.getActivities(context, 99, irrelevant, FLAG_NO_CREATE)) 474 .isSameAs(pendingIntent); 475 476 Intent single = new Intent("activity2"); 477 assertThat(PendingIntent.getActivity(context, 99, single, FLAG_NO_CREATE)) 478 .isSameAs(pendingIntent); 479 480 Intent[] backward = {new Intent("activity2"), new Intent("activity")}; 481 assertThat(PendingIntent.getActivities(context, 99, backward, FLAG_NO_CREATE)).isNull(); 482 } 483 484 @Test 485 @Config(minSdk = Build.VERSION_CODES.JELLY_BEAN_MR1) 486 public void testGetCreatorPackage_nothingSet() { 487 PendingIntent pendingIntent = 488 PendingIntent.getActivity(context, 99, new Intent("activity"), 100); 489 assertThat(pendingIntent.getCreatorPackage()).isEqualTo(context.getPackageName()); 490 assertThat(pendingIntent.getTargetPackage()).isEqualTo(context.getPackageName()); 491 } 492 493 @Test 494 @Config(minSdk = Build.VERSION_CODES.JELLY_BEAN_MR1) 495 public void testGetCreatorPackage_explicitlySetPackage() { 496 String fakePackage = "some.fake.package"; 497 PendingIntent pendingIntent = 498 PendingIntent.getActivity(context, 99, new Intent("activity"), 100); 499 shadowOf(pendingIntent).setCreatorPackage(fakePackage); 500 assertThat(pendingIntent.getCreatorPackage()).isEqualTo(fakePackage); 501 assertThat(pendingIntent.getTargetPackage()).isEqualTo(fakePackage); 502 } 503 } 504