4

I have been experiencing some weird behavior. My app randomly fails to detect/pick up clipboard content (other apps do detect and paste it correctly). I am following these guidelines.

My code looks like this.

public class ClipboardProvider {

    private final ClipboardManager clipboard;

    @Inject
    public ClipboardProvider(Context context) {
        clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
    }

    /**
     * Copy some text to the clipboard.
     *
     * @param label User-visible label for the pasted data.
     * @param text The actual text to copy.
     */
    public void copy(String label, String text) {

        final ClipData clip = ClipData.newPlainText(label, text);

        clipboard.setPrimaryClip(clip);
    }

    /**
     * Grab some text from the clipboard.
     */
    public Optional<String> paste() {

        if (!clipboard.hasPrimaryClip()) {
            return Optional.empty();
        }

        final ClipData primaryClip = clipboard.getPrimaryClip();
        if (primaryClip.getItemCount() == 0) {
            return Optional.empty();
        }

        final ClipData.Item item = primaryClip.getItemAt(0);
        if (item == null) {
            return Optional.empty();
        }

        final CharSequence text = item.getText();
        if (text == null) {
            return Optional.empty();
        }

        return Optional.of(text.toString());
    }

    /**
     * Create an Observable that reports changes on the system clipboard (fires immediately upon
     * subscribe).
     */
    public Observable<String> watchPrimaryClip() {
        return Observable.using(
                ClipboardListener::new,

                clipboardListener -> Observable.create((Observable.OnSubscribe<String>)
                        (subscriber) -> {
                            clipboardListener.setSubscriber(subscriber);
                            clipboardListener.onPrimaryClipChanged();

                            clipboard.addPrimaryClipChangedListener(clipboardListener);
                        }
                ),

                clipboard::removePrimaryClipChangedListener

        ).distinctUntilChanged();
    }

    private class ClipboardListener implements ClipboardManager.OnPrimaryClipChangedListener {
        Subscriber<? super String> subscriber;

        public void setSubscriber(Subscriber<? super String> subscriber) {
            this.subscriber = subscriber;
        }

        @Override
        public void onPrimaryClipChanged() {
            if (subscriber != null && !subscriber.isUnsubscribed()) {
                subscriber.onNext(paste().orElse(""));
            }
        }
    }
}

I am using android.content.ClipboardManager and using a targetSdk = 28 and ClipboardProvider is injected using Dagger. It's being injected an applicationContext.

In particular, what I'm seeing is that watchPrimaryClip() emits events with null because inside paste(), clipboard.hasPrimaryClip() returns false.

Anyone experiencing something similar? Couldn't find nothing resembling this. Any ideas?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
acrespo
  • 1,134
  • 1
  • 10
  • 33

0 Answers0