11

Please help me to solve this problem. This is my code

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);

        clipboard.addPrimaryClipChangedListener(this);


        return START_STICKY;
    }

    @Override
    public void onPrimaryClipChanged() {

        Log.d("log",clipboard.getPrimaryClip()+"");

        ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);

        String clipText = item.getText().toString();

        Log.d("log",clipText);

        new SendClipBoardData().execute(postClipDataUrl,clipText);
    }

Sometimes i'm getting error at ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);

Error: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String java.lang.CharSequence.toString()' on a null object reference

The clipboard.getPrimaryClip() returns ClipData { text/plain {NULL} }, but when i paste the same copied text in my note, i can see the text, i can't detect the problem,sometimes it work sometimes not.

And one more question, when copy works fine, i'm getting copied text result two or three times,but my event is working one time, what it can be ? Thanks in advance.

Gog Avagyan
  • 135
  • 1
  • 7

1 Answers1

9

First of all, there's no guarantees that the clipboard actually has any data on it at all - for example, when you first turn on your phone, you'd expect the clipboard to be empty. Secondly, if there is data, you need to check if it is in the right format. It doesn't make sense to try to paste an image into a textbox.

If there is no content, then clipboard.getPrimaryClip() will return null. If there is content, but it isn't text (a URL, for example, is treated differently to text), then item.getText() will return null. This is causing an exception in your code, because you are calling toString() on a null reference.

The Android developer docs show a short sample, a bit like this:

if (clipboard.hasPrimaryClip()
    && clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))
{
    // Put your paste code here
}

But as I have mentioned, certain things, like a URL, will not match this pattern, even though they could be safely converted to text. To handle all these things, you can try this:

if (clipboard.hasPrimaryClip())
{
    ClipData data = clipboard.getPrimaryClip();
    if (data.getItemCount() > 0)
    {
        CharSequence text = data.getItemAt(0).coerceToText(this);
        if (text != null)
        {
            // Put your paste-handling code here
        }
    }
}
Andrew Williamson
  • 8,299
  • 3
  • 34
  • 62
  • why `getItemAt(0)` and not `getItemAt(clipData.getItemCount()-1)` and what items even mean here? – user25 Aug 18 '18 at 10:34
  • 1
    Although most of the stock Android apps don't support it, Android was designed to allow copy-paste of multiple things at once. E.g. if you had a contact list, and you wanted to copy three contacts, you would probably put the content for each contact in a separate `ClipData.Item`. If you only intend to support single items, and there are multiple items in the ClipData, the most intuitive approach is to take the first item in the list. See the section in the [Android developer docs](https://developer.android.com/guide/topics/text/copy-paste#ClipClasses) for more details. – Andrew Williamson Aug 19 '18 at 20:19
  • @Andrew, I know that. The editor `MonoSpace` does it. But it's weird. If I empty a Clipboard `ClipData.newPlainText("", s); clipboard.setPrimaryClip(clip);` my app only empty logically for itself. Outside one can see in `MonoSpace` the original copied string. – Paulo Buchsbaum Nov 22 '19 at 17:34