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

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

mercurial