1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 4 import static android.os.Build.VERSION_CODES.N; 5 import static org.robolectric.RuntimeEnvironment.getApiLevel; 6 import static org.robolectric.shadow.api.Shadow.directlyOn; 7 8 import android.content.ClipData; 9 import android.content.ClipDescription; 10 import android.content.ClipboardManager; 11 import android.content.ClipboardManager.OnPrimaryClipChangedListener; 12 import java.util.Collection; 13 import java.util.concurrent.CopyOnWriteArrayList; 14 import org.robolectric.annotation.Implementation; 15 import org.robolectric.annotation.Implements; 16 import org.robolectric.annotation.RealObject; 17 import org.robolectric.util.ReflectionHelpers; 18 19 @SuppressWarnings("UnusedDeclaration") 20 @Implements(ClipboardManager.class) 21 public class ShadowClipboardManager { 22 @RealObject private ClipboardManager realClipboardManager; 23 private final Collection<OnPrimaryClipChangedListener> listeners = new CopyOnWriteArrayList<OnPrimaryClipChangedListener>(); 24 private ClipData clip; 25 26 @Implementation setPrimaryClip(ClipData clip)27 protected void setPrimaryClip(ClipData clip) { 28 if (getApiLevel() >= N) { 29 if (clip != null) { 30 clip.prepareToLeaveProcess(true); 31 } 32 } else if (getApiLevel() >= JELLY_BEAN_MR2) { 33 if (clip != null) { 34 ReflectionHelpers.callInstanceMethod(ClipData.class, clip, "prepareToLeaveProcess"); 35 } 36 } 37 38 this.clip = clip; 39 40 for (OnPrimaryClipChangedListener listener : listeners) { 41 listener.onPrimaryClipChanged(); 42 } 43 } 44 45 @Implementation getPrimaryClip()46 protected ClipData getPrimaryClip() { 47 return clip; 48 } 49 50 @Implementation getPrimaryClipDescription()51 protected ClipDescription getPrimaryClipDescription() { 52 return clip == null ? null : clip.getDescription(); 53 } 54 55 @Implementation hasPrimaryClip()56 protected boolean hasPrimaryClip() { 57 return clip != null; 58 } 59 60 @Implementation addPrimaryClipChangedListener(OnPrimaryClipChangedListener listener)61 protected void addPrimaryClipChangedListener(OnPrimaryClipChangedListener listener) { 62 listeners.add(listener); 63 } 64 65 @Implementation removePrimaryClipChangedListener(OnPrimaryClipChangedListener listener)66 protected void removePrimaryClipChangedListener(OnPrimaryClipChangedListener listener) { 67 listeners.remove(listener); 68 } 69 70 @Implementation setText(CharSequence text)71 protected void setText(CharSequence text) { 72 setPrimaryClip(ClipData.newPlainText(null, text)); 73 } 74 75 @Implementation hasText()76 protected boolean hasText() { 77 CharSequence text = directlyOn(realClipboardManager, ClipboardManager.class).getText(); 78 return text != null && text.length() > 0; 79 } 80 } 81