可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
When I copy text to the clipboard onPrimaryClipChanged method is called twice. Any ideas why?
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); final ClipboardManager cliboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); cliboardManager .addPrimaryClipChangedListener(new OnPrimaryClipChangedListener() { @Override public void onPrimaryClipChanged() { ClipData clipData = cliboardManager.getPrimaryClip(); System.out .println("********** clip changed, clipData: " + clipData.getItemAt(0)); } }); return true; }
Test case: Copying the text "continue" from the BBC web site will result in the following output:
continue
continue
But if I debug the program I can see that the clipData object has value:
ClipData { text/plain {T:continue } }
the first time onPrimaryClipChanged() is called and
ClipData { text/plain "BBC - Homepage" {T:continue } }
the next time onPrimaryClipChanged() is called.
So basically the first time ClipDescription is { text/plain } and the second time is ClipDescription { text/plain "BBC - Homepage" } (i.e including the title of the web page)
回答1:
I assume you didn't register multiple listeners, I can't say it is bug, you still you can workaround it. Try something like this:
String mPreviousText = ""; cliboardManager .addPrimaryClipChangedListener(new OnPrimaryClipChangedListener() { @Override public void onPrimaryClipChanged() { ClipData clipData = cliboardManager.getPrimaryClip(); System.out .println("********** clip changed, clipData: " + clipData.getItemAt(0)); ClipData.Item item = clipData.getItemAt(0); if(mPreviousText.equals(item.getText().toString())) return; else{ /// do something mPrevousText = item.getText().toString(); } } });
回答2:
I meet this problem too, finally I know why it will call multi times!!!
Usually we addPrimaryClipChangedListener()
, but we don't removePrimaryClipChangedListener()
.
See: http://developer.android.com/reference/android/content/Context.html#CLIPBOARD_SERVICE
Use with getSystemService(String) to retrieve a ClipboardManager for accessing and modifying the contents of the global clipboard.
It means we should removePrimaryClipChangedListener()
manually!
My solution code :
ClipboardManager myClipBoard ; static boolean bHasClipChangedListener = false; ClipboardManager.OnPrimaryClipChangedListener mPrimaryClipChangedListener = new ClipboardManager.OnPrimaryClipChangedListener() { public void onPrimaryClipChanged() { ClipData clipData = myClipBoard.getPrimaryClip(); Log.d("henrytest", "********** clip changed, clipData: " + clipData.getItemAt(0)); } }; private void RegPrimaryClipChanged(){ if(!bHasClipChangedListener){ myClipBoard.addPrimaryClipChangedListener(mPrimaryClipChangedListener); bHasClipChangedListener = true; } } private void UnRegPrimaryClipChanged(){ if(bHasClipChangedListener){ myClipBoard.removePrimaryClipChangedListener(mPrimaryClipChangedListener); bHasClipChangedListener = false; } } @Override protected void onCreate(Bundle savedInstanceState) { myClipBoard = (ClipboardManager) Clipboard.this.getSystemService(android.content.Context.CLIPBOARD_SERVICE); } @Override protected void onResume() { super.onResume(); RegPrimaryClipChanged(); } @Override protected void onPause() { super.onPause(); UnRegPrimaryClipChanged(); } @Override protected void onStop() { super.onStop(); //UnRegPrimaryClipChanged(); } @Override protected void onDestroy() { super.onDestroy(); //UnRegPrimaryClipChanged(); }
回答3:
// Prevention duplicate action of OnPrimaryClipChangedListener.
private ExecutorService mThreadPool = Executors.newSingleThreadExecutor(); static boolean isExpireData = true; class hasExpireData implements Runnable { @Override public void run() { // TODO Auto-generated method stub isExpireData = true; } } private ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener = new ClipboardManager.OnPrimaryClipChangedListener() { @Override public void onPrimaryClipChanged() { Log.d(TAG, "onPrimaryClipChanged"); ClipData clip = mClipboardManager.getPrimaryClip(); Thread expireData = new Thread(new hasExpireData()); new Handler().postDelayed(expireData, 500); // 0.5 seconds wait... if(isExpireData) { isExpireData = false; mThreadPool.execute(new TextRunnable( clip.getItemAt(0).getText())); } } }; private class TextRunnable implements Runnable { public TextRunnable(CharSequence text) { // text store to this class } @Override public void run() { // text other process } }