1 package com.xtremelabs.robolectric.shadows; 2 3 import android.content.ComponentName; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.net.Uri; 7 import android.os.Bundle; 8 import android.os.Parcel; 9 import android.os.Parcelable; 10 import com.xtremelabs.robolectric.Robolectric; 11 import com.xtremelabs.robolectric.internal.Implementation; 12 import com.xtremelabs.robolectric.internal.Implements; 13 import com.xtremelabs.robolectric.internal.RealObject; 14 import com.xtremelabs.robolectric.util.Join; 15 16 import java.io.*; 17 import java.util.*; 18 19 import static android.content.Intent.*; 20 import static com.xtremelabs.robolectric.Robolectric.shadowOf; 21 22 @SuppressWarnings({"UnusedDeclaration"}) 23 @Implements(Intent.class) 24 public class ShadowIntent { 25 @RealObject private Intent realIntent; 26 27 private final Bundle extras = new Bundle(); 28 private String action; 29 private ComponentName componentName; 30 private String type; 31 private Uri data; 32 private int flags; 33 private Class<?> intentClass; 34 private String packageName; 35 private final Set<String> categories = new HashSet<String>(); 36 private String uri; 37 __constructor__(Context packageContext, Class cls)38 public void __constructor__(Context packageContext, Class cls) { 39 componentName = new ComponentName(packageContext, cls); 40 intentClass = cls; 41 } 42 __constructor__(String action, Uri uri)43 public void __constructor__(String action, Uri uri) { 44 this.action = action; 45 data = uri; 46 } 47 __constructor__(String action)48 public void __constructor__(String action) { 49 __constructor__(action, null); 50 } 51 __constructor__(Intent intent)52 public void __constructor__(Intent intent) { 53 ShadowIntent other = shadowOf(intent); 54 extras.putAll(other.extras); 55 action = other.action; 56 componentName = other.componentName; 57 type = other.type; 58 data = other.data; 59 flags = other.flags; 60 intentClass = other.intentClass; 61 packageName = other.packageName; 62 categories.addAll(other.categories); 63 uri = other.uri; 64 } 65 66 @Implementation createChooser(Intent target, CharSequence title)67 public static Intent createChooser(Intent target, CharSequence title) { 68 Intent intent = new Intent(Intent.ACTION_CHOOSER); 69 intent.putExtra(Intent.EXTRA_INTENT, target); 70 if (title != null) { 71 intent.putExtra(Intent.EXTRA_TITLE, title); 72 } 73 return intent; 74 } 75 76 @Implementation setAction(String action)77 public Intent setAction(String action) { 78 this.action = action; 79 return realIntent; 80 } 81 82 @Implementation getAction()83 public String getAction() { 84 return action; 85 } 86 87 @Implementation setType(String type)88 public Intent setType(String type) { 89 this.type = type; 90 this.data = null; 91 return realIntent; 92 } 93 94 @Implementation setDataAndType(Uri data, String type)95 public Intent setDataAndType(Uri data, String type) { 96 this.data = data; 97 this.type = type; 98 return realIntent; 99 } 100 101 @Implementation getType()102 public String getType() { 103 return type; 104 } 105 106 @Implementation addCategory(String category)107 public Intent addCategory(String category) { 108 categories.add(category); 109 return realIntent; 110 } 111 112 @Implementation removeCategory(String category)113 public void removeCategory(String category) { 114 categories.remove(category); 115 } 116 117 @Implementation hasCategory(String category)118 public boolean hasCategory(String category) { 119 return categories.contains(category); 120 } 121 122 @Implementation getCategories()123 public Set<String> getCategories() { 124 return categories; 125 } 126 127 @Implementation setPackage(String packageName)128 public Intent setPackage(String packageName) { 129 this.packageName = packageName; 130 return realIntent; 131 } 132 133 @Implementation getPackage()134 public String getPackage() { 135 return packageName; 136 } 137 138 @Implementation getData()139 public Uri getData() { 140 return data; 141 } 142 143 @Implementation setClass(Context packageContext, Class<?> cls)144 public Intent setClass(Context packageContext, Class<?> cls) { 145 this.intentClass = cls; 146 return realIntent; 147 } 148 149 @Implementation setClassName(String packageName, String className)150 public Intent setClassName(String packageName, String className) { 151 componentName = new ComponentName(packageName, className); 152 try { 153 this.intentClass = Class.forName(className); 154 } catch (ClassNotFoundException e) { 155 // ignore 156 } 157 return realIntent; 158 } 159 160 @Implementation setClassName(Context packageContext, String className)161 public Intent setClassName(Context packageContext, String className) { 162 componentName = new ComponentName(packageContext.getPackageName(), className); 163 return realIntent; 164 } 165 166 @Implementation setData(Uri data)167 public Intent setData(Uri data) { 168 this.data = data; 169 this.type = null; 170 return realIntent; 171 } 172 173 @Implementation getFlags()174 public int getFlags() { 175 return flags; 176 } 177 178 @Implementation setFlags(int flags)179 public Intent setFlags(int flags) { 180 this.flags = flags; 181 return realIntent; 182 } 183 184 @Implementation addFlags(int flags)185 public Intent addFlags(int flags) { 186 this.flags |= flags; 187 return realIntent; 188 } 189 190 @Implementation putExtras(Bundle src)191 public Intent putExtras(Bundle src) { 192 extras.putAll(src); 193 return realIntent; 194 } 195 196 @Implementation putExtras(Intent src)197 public Intent putExtras(Intent src) { 198 ShadowIntent srcShadowIntent = shadowOf(src); 199 extras.putAll(srcShadowIntent.extras); 200 return realIntent; 201 } 202 203 @Implementation getExtras()204 public Bundle getExtras() { 205 return extras != null ? new Bundle(extras) : null; 206 } 207 208 @Implementation putExtra(String key, int value)209 public Intent putExtra(String key, int value) { 210 extras.putInt(key, value); 211 return realIntent; 212 } 213 214 @Implementation putExtra(String key, double value)215 public Intent putExtra(String key, double value) { 216 extras.putDouble(key, value); 217 return realIntent; 218 } 219 220 @Implementation putExtra(String key, float value)221 public Intent putExtra(String key, float value) { 222 extras.putFloat(key, value); 223 return realIntent; 224 } 225 226 @Implementation putExtra(String key, long value)227 public Intent putExtra(String key, long value) { 228 extras.putLong(key, value); 229 return realIntent; 230 } 231 232 @Implementation putExtra(String key, Serializable value)233 public Intent putExtra(String key, Serializable value) { 234 extras.putSerializable(key, serializeCycle(value)); 235 return realIntent; 236 } 237 238 @Implementation putExtra(String key, Parcelable value)239 public Intent putExtra(String key, Parcelable value) { 240 extras.putParcelable(key, value); 241 return realIntent; 242 } 243 244 @Implementation putExtra(String key, Parcelable[] value)245 public Intent putExtra(String key, Parcelable[] value) { 246 extras.putParcelableArray(key, value); 247 return realIntent; 248 } 249 250 @Implementation putExtra(String key, String value)251 public Intent putExtra(String key, String value) { 252 extras.putString(key, value); 253 return realIntent; 254 } 255 256 @Implementation putExtra(String key, String[] value)257 public Intent putExtra(String key, String[] value) { 258 extras.putStringArray(key, value); 259 return realIntent; 260 } 261 262 @Implementation putExtra(String key, Bundle value)263 public Intent putExtra(String key, Bundle value) { 264 extras.putBundle(key, value); 265 return realIntent; 266 } 267 268 @Implementation putExtra(String key, boolean value)269 public Intent putExtra(String key, boolean value) { 270 extras.putBoolean(key, value); 271 return realIntent; 272 } 273 274 @Implementation putExtra(String key, int[] value)275 public Intent putExtra(String key, int[] value) { 276 extras.putIntArray(key, value); 277 return realIntent; 278 } 279 280 @Implementation putExtra(String key, long[] value)281 public Intent putExtra(String key, long[] value) { 282 extras.putLongArray(key, value); 283 return realIntent; 284 } 285 286 @Implementation getIntArrayExtra(String name)287 public int[] getIntArrayExtra(String name) { 288 return extras.getIntArray(name); 289 } 290 291 @Implementation getLongArrayExtra(String name)292 public long[] getLongArrayExtra(String name) { 293 return extras.getLongArray(name); 294 } 295 296 @Implementation getBooleanExtra(String name, boolean defaultValue)297 public boolean getBooleanExtra(String name, boolean defaultValue) { 298 return extras.getBoolean(name, defaultValue); 299 } 300 301 @Implementation getStringArrayExtra(String name)302 public String[] getStringArrayExtra(String name) { 303 return extras.getStringArray(name); 304 } 305 306 @Implementation putExtra(String key, CharSequence value)307 public Intent putExtra(String key, CharSequence value) { 308 extras.putCharSequence(key, value); 309 return realIntent; 310 } 311 312 @Implementation getCharSequenceExtra(String name)313 public CharSequence getCharSequenceExtra(String name) { 314 return extras.getCharSequence(name); 315 } 316 317 @Implementation putExtra(String key, byte[] value)318 public void putExtra(String key, byte[] value) { 319 extras.putByteArray(key, value); 320 } 321 322 @Implementation putStringArrayListExtra(String key, ArrayList<String> value)323 public Intent putStringArrayListExtra(String key, ArrayList<String> value) { 324 extras.putStringArrayList(key, value); 325 return realIntent; 326 } 327 328 @Implementation getStringArrayListExtra(String name)329 public ArrayList<String> getStringArrayListExtra(String name) { 330 return extras.getStringArrayList(name); 331 } 332 333 @Implementation putIntegerArrayListExtra(String key, ArrayList<Integer> value)334 public Intent putIntegerArrayListExtra(String key, ArrayList<Integer> value) { 335 extras.putIntegerArrayList(key, value); 336 return realIntent; 337 } 338 339 @Implementation getIntegerArrayListExtra(String name)340 public ArrayList<Integer> getIntegerArrayListExtra(String name) { 341 return extras.getIntegerArrayList(name); 342 } 343 344 @Implementation putParcelableArrayListExtra(String key, ArrayList<Parcelable> value)345 public Intent putParcelableArrayListExtra(String key, ArrayList<Parcelable> value) { 346 extras.putParcelableArrayList(key, value); 347 return realIntent; 348 } 349 350 @Implementation getParcelableArrayListExtra(String key)351 public ArrayList<Parcelable> getParcelableArrayListExtra(String key) { 352 return extras.getParcelableArrayList(key); 353 } 354 355 @Implementation hasExtra(String name)356 public boolean hasExtra(String name) { 357 return extras.containsKey(name); 358 } 359 360 @Implementation getStringExtra(String name)361 public String getStringExtra(String name) { 362 return extras.getString(name); 363 } 364 365 @Implementation getParcelableExtra(String name)366 public Parcelable getParcelableExtra(String name) { 367 return extras.getParcelable(name); 368 } 369 370 @Implementation getParcelableArrayExtra(String name)371 public Parcelable[] getParcelableArrayExtra(String name) { 372 return extras.getParcelableArray(name); 373 } 374 375 @Implementation getIntExtra(String name, int defaultValue)376 public int getIntExtra(String name, int defaultValue) { 377 return extras.getInt(name, defaultValue); 378 } 379 380 @Implementation getLongExtra(String name, long defaultValue)381 public long getLongExtra(String name, long defaultValue) { 382 return extras.getLong(name, defaultValue); 383 } 384 385 @Implementation getDoubleExtra(String name, double defaultValue)386 public double getDoubleExtra(String name, double defaultValue) { 387 return extras.getDouble(name, defaultValue); 388 } 389 390 @Implementation getBundleExtra(String name)391 public Bundle getBundleExtra(String name) { 392 return extras.getBundle(name); 393 } 394 395 @Implementation getFloatExtra(String name, float defaultValue)396 public float getFloatExtra(String name, float defaultValue) { 397 return extras.getFloat(name, defaultValue); 398 } 399 400 @Implementation getByteArrayExtra(String name)401 public byte[] getByteArrayExtra(String name) { 402 return extras.getByteArray(name); 403 } 404 405 @Implementation getSerializableExtra(String name)406 public Serializable getSerializableExtra(String name) { 407 return extras.getSerializable(name); 408 } 409 410 @Implementation removeExtra(String name)411 public void removeExtra(String name) { 412 extras.remove(name); 413 } 414 415 @Implementation setComponent(ComponentName componentName)416 public Intent setComponent(ComponentName componentName) { 417 this.componentName = componentName; 418 return realIntent; 419 } 420 421 @Implementation getComponent()422 public ComponentName getComponent() { 423 return componentName; 424 } 425 426 @Implementation toURI()427 public String toURI() { 428 return uri; 429 } 430 431 @Implementation fillIn(Intent otherIntent, int flags)432 public int fillIn(Intent otherIntent, int flags) { 433 int changes = 0; 434 ShadowIntent other = shadowOf(otherIntent); 435 436 if (other.action != null && (action == null || (flags & FILL_IN_ACTION) != 0)) { 437 action = other.action; 438 changes |= FILL_IN_ACTION; 439 } 440 if ((other.data != null || other.type != null) 441 && ((data == null && type == null) || (flags & FILL_IN_DATA) != 0)) { 442 data = other.data; 443 type = other.type; 444 changes |= FILL_IN_DATA; 445 } 446 if (!other.categories.isEmpty() 447 && (categories.isEmpty() || (flags & FILL_IN_CATEGORIES) != 0)) { 448 categories.addAll(other.categories); 449 changes |= FILL_IN_CATEGORIES; 450 } 451 if (other.packageName != null 452 && (packageName == null || (flags & FILL_IN_PACKAGE) != 0)) { 453 packageName = other.packageName; 454 changes |= FILL_IN_PACKAGE; 455 } 456 if (other.componentName != null && (flags & FILL_IN_COMPONENT) != 0) { 457 componentName = other.componentName; 458 changes |= FILL_IN_COMPONENT; 459 } 460 461 extras.putAll(other.extras); 462 return changes; 463 } 464 465 @Implementation 466 // cribbed from Android source filterEquals(Intent other)467 public boolean filterEquals(Intent other) { 468 if (other == null) { 469 return false; 470 } 471 if (getAction() != other.getAction()) { 472 if (getAction() != null) { 473 if (!getAction().equals(other.getAction())) { 474 return false; 475 } 476 } else { 477 if (!other.getAction().equals(getAction())) { 478 return false; 479 } 480 } 481 } 482 if (getData() != other.getData()) { 483 if (getData() != null) { 484 if (!getData().equals(other.getData())) { 485 return false; 486 } 487 } else { 488 if (!other.getData().equals(getData())) { 489 return false; 490 } 491 } 492 } 493 if (getType() != other.getType()) { 494 if (getType() != null) { 495 if (!getType().equals(other.getType())) { 496 return false; 497 } 498 } else { 499 if (!other.getType().equals(getType())) { 500 return false; 501 } 502 } 503 } 504 if (getPackage() != other.getPackage()) { 505 if (getPackage() != null) { 506 if (!getPackage().equals(other.getPackage())) { 507 return false; 508 } 509 } else { 510 if (!other.getPackage().equals(getPackage())) { 511 return false; 512 } 513 } 514 } 515 if (getComponent() != other.getComponent()) { 516 if (getComponent() != null) { 517 if (!getComponent().equals(other.getComponent())) { 518 return false; 519 } 520 } else { 521 if (!other.getComponent().equals(getComponent())) { 522 return false; 523 } 524 } 525 } 526 if (getCategories() != other.getCategories()) { 527 if (getCategories() != null) { 528 if (!getCategories().equals(other.getCategories())) { 529 return false; 530 } 531 } else { 532 if (!other.getCategories().equals(getCategories())) { 533 return false; 534 } 535 } 536 } 537 538 return true; 539 } 540 541 /** 542 * Compares an {@code Intent} with a {@code ShadowIntent} (obtained via a call to 543 * {@link Robolectric#shadowOf(android.content.Intent)}) 544 * 545 * @param o a {@code ShadowIntent} 546 * @return whether they are equivalent 547 */ 548 @Deprecated realIntentEquals(ShadowIntent o)549 public boolean realIntentEquals(ShadowIntent o) { 550 if (this == o) return true; 551 if (o == null || getClass() != o.getClass()) return false; 552 553 if (action != null ? !action.equals(o.action) : o.action != null) return false; 554 if (componentName != null ? !componentName.equals(o.componentName) : o.componentName != null) 555 return false; 556 if (data != null ? !data.equals(o.data) : o.data != null) return false; 557 if (extras != null ? !extras.equals(o.extras) : o.extras != null) return false; 558 if (type != null ? !type.equals(o.type) : o.type != null) return false; 559 if (categories != null ? !categories.equals(o.categories) : o.categories != null) return false; 560 561 return true; 562 } 563 564 @Override 565 @Implementation hashCode()566 public int hashCode() { 567 int result = extras != null ? extras.hashCode() : 0; 568 result = 31 * result + (action != null ? action.hashCode() : 0); 569 result = 31 * result + (componentName != null ? componentName.hashCode() : 0); 570 result = 31 * result + (data != null ? data.hashCode() : 0); 571 result = 31 * result + (type != null ? type.hashCode() : 0); 572 result = 31 * result + flags; 573 return result; 574 } 575 576 @Override 577 @Implementation equals(Object o)578 public boolean equals(Object o) { 579 if (!(o instanceof Intent)) return false; 580 return realIntentEquals(shadowOf((Intent) o)); 581 } 582 583 /** 584 * Non-Android accessor that returns the {@code Class} object set by 585 * {@link #setClass(android.content.Context, Class)} 586 * 587 * @return the {@code Class} object set by 588 * {@link #setClass(android.content.Context, Class)} 589 */ getIntentClass()590 public Class<?> getIntentClass() { 591 return intentClass; 592 } 593 594 @Override 595 @Implementation toString()596 public String toString() { 597 return "Intent{" + 598 Join.join( 599 ", ", 600 ifWeHave(componentName, "componentName"), 601 ifWeHave(action, "action"), 602 ifWeHave(extras, "extras"), 603 ifWeHave(data, "data"), 604 ifWeHave(type, "type") 605 ) + 606 '}'; 607 } 608 609 @Implementation writeToParcel(Parcel out, int flags)610 public void writeToParcel(Parcel out, int flags) { 611 out.writeString(action); 612 if (data != null) { 613 out.writeInt(1); 614 Uri.writeToParcel(out, data); 615 } else { 616 out.writeInt(0); 617 } 618 out.writeString(type); 619 out.writeInt(flags); 620 out.writeString(packageName); 621 ComponentName.writeToParcel(componentName, out); 622 out.writeInt(categories.size()); 623 for (String category : categories) { 624 out.writeString(category); 625 } 626 out.writeBundle(extras); 627 } 628 629 @Implementation readFromParcel(Parcel in)630 public void readFromParcel(Parcel in) { 631 setAction(in.readString()); 632 if (in.readInt() != 0) { 633 data = Uri.CREATOR.createFromParcel(in); 634 } 635 type = in.readString(); 636 flags = in.readInt(); 637 packageName = in.readString(); 638 componentName = ComponentName.readFromParcel(in); 639 int N = in.readInt(); 640 for (int i = 0; i < N; i++) { 641 categories.add(in.readString().intern()); 642 } 643 extras.putAll(in.readBundle()); 644 } 645 serializeCycle(Serializable serializable)646 private Serializable serializeCycle(Serializable serializable) { 647 try { 648 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 649 ObjectOutputStream output = new ObjectOutputStream(byteArrayOutputStream); 650 output.writeObject(serializable); 651 output.close(); 652 653 byte[] bytes = byteArrayOutputStream.toByteArray(); 654 ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(bytes)); 655 return (Serializable) input.readObject(); 656 } catch (IOException e) { 657 throw new RuntimeException(e); 658 } catch (ClassNotFoundException e) { 659 throw new RuntimeException(e); 660 } 661 } 662 ifWeHave(Object o, String name)663 private String ifWeHave(Object o, String name) { 664 if (o == null) return null; 665 if (o instanceof Map && ((Map) o).isEmpty()) return null; 666 return name + "=" + o; 667 } 668 setURI(String uri)669 public void setURI(String uri) { 670 this.uri = uri; 671 } 672 } 673