6

I have implemented Background Service to listen to clipboard events system wide..

Service Implementation:

public class ClipService extends Service {
ClipboardManager cm;

@Override
public void onCreate() {
    Log.d("FRAG","onCreate called...");
    super.onCreate();
    cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
    cm.addPrimaryClipChangedListener(new ClipboardListener());
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    super.onDestroy();
    cm.removePrimaryClipChangedListener(new ClipboardListener());
}

class ClipboardListener implements ClipboardManager.OnPrimaryClipChangedListener{

     @Override
     public void onPrimaryClipChanged() {
        Log.d("FRAG","onPrimaryClipChanged called..");
        if(cm!=null) {
            String s1 = cm.getPrimaryClip().getItemAt(0).coerceToText(ClipService.this).toString();
            ContentValues cv = new ContentValues();
            cv.put(DatabaseHelper.CONTENT,s1);
            getContentResolver().insert(DataProvider.CONTENT_URI, cv);//Insert using Content provider
        }
     }
}
}

Now my concern is that for every text copied to clipboard three entries are getting inserted for single copy event...i.e. onPrimaryClipChanged is getting called three times..

i am using `Log.d("FRAG","onPrimaryClipChanged called.."); and it is getting logged 3 times so problem seems to be with function being called 3 times for each clipboard change event and not insert part of the code.

What might be the cause of it getting called 3 times?

Chin
  • 19,717
  • 37
  • 107
  • 164
PunitD
  • 2,293
  • 1
  • 20
  • 29
  • I have no idea, though you might consider adding the listener object ID value to your `Log` statement, to confirm that it is the same listener instance getting called. While the code you show here *should* only result in a single instance, perhaps something else floating around your code is also getting registered, and so your problem is multiple listeners more than multiple events. – CommonsWare Feb 14 '15 at 11:50
  • Hi CommonsWare..Being a newbie in Android & Java learning it through your book..can you please help me how can i get listener's id to put into log statement to check which instance getting called? – PunitD Feb 14 '15 at 12:34
  • The simplest way to log a unique ID of the object, for most objects, is to call `toString()` on the object. Most Java classes do not have a custom `toString()` implementation, and the default implementation will return the class name plus an object ID. – CommonsWare Feb 14 '15 at 12:53
  • ok..great..and one thing i will like you to know is that onPrimaryClipChanged() is getting called 3 times only when i am copying from Chrome Browser and gets called only once while copying something from other Apps.. – PunitD Feb 14 '15 at 13:04
  • Then there is something strange with what Chrome is doing with the clipboard. That is not something you can control. – CommonsWare Feb 14 '15 at 13:07
  • Sorry.. my one last question..won't spam you again..Then how do other clipboard manager apps in play store are able to handle such situations..any workaround you could think of..?Thanks very much for your help!! Really Appreciate it!! :) – PunitD Feb 14 '15 at 13:19
  • "Then how do other clipboard manager apps in play store are able to handle such situations" -- I have no idea. – CommonsWare Feb 14 '15 at 13:21
  • I have the same situation... in here. This repeats only when the text is copied from the chrome browser. – codeMan May 18 '15 at 06:38

1 Answers1

1

This is a known issue with WebView/Chrome. I got around it by ignoring the duplicated events within a certain threshold (e.g. 50ms)

ClipboardManager.OnPrimaryClipChangedListener primaryClipChangedListener = new ClipboardManager.OnPrimaryClipChangedListener() {
    private static final long THRESHOLD_MS = 50;
    private long lastChangedTime = 0;
    private String lastString = "";
    @Override
    public void onPrimaryClipChanged() {
        try {
            String str = clipMan.getText().toString();

            // Copying text from certain places will trigger multiple events (e.g. Chrome/WebView generates 3 events)
            // Ignore the duplicated events
            if (System.currentTimeMillis() - lastChangedTime < THRESHOLD_MS && Objects.equals(lastString, str)) {
                return;
            }

            lastChangedTime = System.currentTimeMillis();
            lastString = str;

            // Rest of the logic
            ...
        }
    }
}
Chin
  • 19,717
  • 37
  • 107
  • 164