mobile/android/base/util/Clipboard.java

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 package org.mozilla.gecko.util;
michael@0 6
michael@0 7 import android.content.ClipData;
michael@0 8 import android.content.Context;
michael@0 9 import android.os.Build;
michael@0 10 import android.util.Log;
michael@0 11
michael@0 12 import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
michael@0 13
michael@0 14 import java.util.concurrent.SynchronousQueue;
michael@0 15
michael@0 16 public final class Clipboard {
michael@0 17 private static Context mContext;
michael@0 18 private final static String LOGTAG = "GeckoClipboard";
michael@0 19 private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
michael@0 20
michael@0 21 private Clipboard() {
michael@0 22 }
michael@0 23
michael@0 24 public static void init(final Context c) {
michael@0 25 if (mContext != null) {
michael@0 26 Log.w(LOGTAG, "Clipboard.init() called twice!");
michael@0 27 return;
michael@0 28 }
michael@0 29 mContext = c.getApplicationContext();
michael@0 30 }
michael@0 31
michael@0 32 @WrapElementForJNI(stubName = "GetClipboardTextWrapper")
michael@0 33 public static String getText() {
michael@0 34 // If we're on the UI thread or the background thread, we have a looper on the thread
michael@0 35 // and can just call this directly. For any other threads, post the call to the
michael@0 36 // background thread.
michael@0 37
michael@0 38 if (ThreadUtils.isOnUiThread() || ThreadUtils.isOnBackgroundThread()) {
michael@0 39 return getClipboardTextImpl();
michael@0 40 }
michael@0 41
michael@0 42 ThreadUtils.postToBackgroundThread(new Runnable() {
michael@0 43 @Override
michael@0 44 public void run() {
michael@0 45 String text = getClipboardTextImpl();
michael@0 46 try {
michael@0 47 sClipboardQueue.put(text != null ? text : "");
michael@0 48 } catch (InterruptedException ie) {}
michael@0 49 }
michael@0 50 });
michael@0 51 try {
michael@0 52 return sClipboardQueue.take();
michael@0 53 } catch (InterruptedException ie) {
michael@0 54 return "";
michael@0 55 }
michael@0 56 }
michael@0 57
michael@0 58 @WrapElementForJNI(stubName = "SetClipboardText")
michael@0 59 public static void setText(final CharSequence text) {
michael@0 60 ThreadUtils.postToBackgroundThread(new Runnable() {
michael@0 61 @Override
michael@0 62 @SuppressWarnings("deprecation")
michael@0 63 public void run() {
michael@0 64 if (Build.VERSION.SDK_INT >= 11) {
michael@0 65 android.content.ClipboardManager cm = getClipboardManager(mContext);
michael@0 66 ClipData clip = ClipData.newPlainText("Text", text);
michael@0 67 try {
michael@0 68 cm.setPrimaryClip(clip);
michael@0 69 } catch (NullPointerException e) {
michael@0 70 // Bug 776223: This is a Samsung clipboard bug. setPrimaryClip() can throw
michael@0 71 // a NullPointerException if Samsung's /data/clipboard directory is full.
michael@0 72 // Fortunately, the text is still successfully copied to the clipboard.
michael@0 73 }
michael@0 74 } else {
michael@0 75 android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
michael@0 76 cm.setText(text);
michael@0 77 }
michael@0 78 }
michael@0 79 });
michael@0 80 }
michael@0 81
michael@0 82 /**
michael@0 83 * Returns true if the clipboard is nonempty, false otherwise.
michael@0 84 *
michael@0 85 * @return true if the clipboard is nonempty, false otherwise.
michael@0 86 */
michael@0 87 @WrapElementForJNI
michael@0 88 public static boolean hasText() {
michael@0 89 if (Build.VERSION.SDK_INT >= 11) {
michael@0 90 android.content.ClipboardManager cm = getClipboardManager(mContext);
michael@0 91 return cm.hasPrimaryClip();
michael@0 92 }
michael@0 93
michael@0 94 android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
michael@0 95 return cm.hasText();
michael@0 96 }
michael@0 97
michael@0 98 /**
michael@0 99 * Deletes all text from the clipboard.
michael@0 100 */
michael@0 101 @WrapElementForJNI
michael@0 102 public static void clearText() {
michael@0 103 setText(null);
michael@0 104 }
michael@0 105
michael@0 106 private static android.content.ClipboardManager getClipboardManager(Context context) {
michael@0 107 // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
michael@0 108 // which is a subclass of android.text.ClipboardManager.
michael@0 109 return (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
michael@0 110 }
michael@0 111
michael@0 112 private static android.text.ClipboardManager getDeprecatedClipboardManager(Context context) {
michael@0 113 return (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
michael@0 114 }
michael@0 115
michael@0 116 /* On some devices, access to the clipboard service needs to happen
michael@0 117 * on a thread with a looper, so this function requires a looper is
michael@0 118 * present on the thread. */
michael@0 119 @SuppressWarnings("deprecation")
michael@0 120 private static String getClipboardTextImpl() {
michael@0 121 if (Build.VERSION.SDK_INT >= 11) {
michael@0 122 android.content.ClipboardManager cm = getClipboardManager(mContext);
michael@0 123 if (cm.hasPrimaryClip()) {
michael@0 124 ClipData clip = cm.getPrimaryClip();
michael@0 125 if (clip != null) {
michael@0 126 ClipData.Item item = clip.getItemAt(0);
michael@0 127 return item.coerceToText(mContext).toString();
michael@0 128 }
michael@0 129 }
michael@0 130 } else {
michael@0 131 android.text.ClipboardManager cm = getDeprecatedClipboardManager(mContext);
michael@0 132 if (cm.hasText()) {
michael@0 133 return cm.getText().toString();
michael@0 134 }
michael@0 135 }
michael@0 136 return null;
michael@0 137 }
michael@0 138 }

mercurial