ClipboardManager.java revision 327fbd2c8fa294b919475feb4c74a74ee1981e02
1/** 2 * Copyright (c) 2010, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.content; 18 19import android.content.Context; 20import android.os.Message; 21import android.os.RemoteException; 22import android.os.Handler; 23import android.os.IBinder; 24import android.os.ServiceManager; 25import android.util.Log; 26 27import java.util.ArrayList; 28 29/** 30 * Interface to the clipboard service, for placing and retrieving text in 31 * the global clipboard. 32 * 33 * <p> 34 * You do not instantiate this class directly; instead, retrieve it through 35 * {@link android.content.Context#getSystemService}. 36 * 37 * <p> 38 * The ClipboardManager API itself is very simple: it consists of methods 39 * to atomically get and set the current primary clipboard data. That data 40 * is expressed as a {@link ClipData} object, which defines the protocol 41 * for data exchange between applications. 42 * 43 * @see android.content.Context#getSystemService 44 */ 45public class ClipboardManager extends android.text.ClipboardManager { 46 private final static Object sStaticLock = new Object(); 47 private static IClipboard sService; 48 49 private final Context mContext; 50 51 private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners 52 = new ArrayList<OnPrimaryClipChangedListener>(); 53 54 private final IOnPrimaryClipChangedListener.Stub mPrimaryClipChangedServiceListener 55 = new IOnPrimaryClipChangedListener.Stub() { 56 public void dispatchPrimaryClipChanged() { 57 mHandler.sendEmptyMessage(MSG_REPORT_PRIMARY_CLIP_CHANGED); 58 } 59 }; 60 61 static final int MSG_REPORT_PRIMARY_CLIP_CHANGED = 1; 62 63 private final Handler mHandler = new Handler() { 64 @Override 65 public void handleMessage(Message msg) { 66 switch (msg.what) { 67 case MSG_REPORT_PRIMARY_CLIP_CHANGED: 68 reportPrimaryClipChanged(); 69 } 70 } 71 }; 72 73 public interface OnPrimaryClipChangedListener { 74 void onPrimaryClipChanged(); 75 } 76 77 static private IClipboard getService() { 78 synchronized (sStaticLock) { 79 if (sService != null) { 80 return sService; 81 } 82 IBinder b = ServiceManager.getService("clipboard"); 83 sService = IClipboard.Stub.asInterface(b); 84 return sService; 85 } 86 } 87 88 /** {@hide} */ 89 public ClipboardManager(Context context, Handler handler) { 90 mContext = context; 91 } 92 93 /** 94 * Sets the current primary clip on the clipboard. This is the clip that 95 * is involved in normal cut and paste operations. 96 * 97 * @param clip The clipped data item to set. 98 */ 99 public void setPrimaryClip(ClipData clip) { 100 try { 101 getService().setPrimaryClip(clip); 102 } catch (RemoteException e) { 103 } 104 } 105 106 /** 107 * Returns the current primary clip on the clipboard. 108 */ 109 public ClipData getPrimaryClip() { 110 try { 111 return getService().getPrimaryClip(mContext.getPackageName()); 112 } catch (RemoteException e) { 113 return null; 114 } 115 } 116 117 /** 118 * Returns a description of the current primary clip on the clipboard 119 * but not a copy of its data. 120 */ 121 public ClipDescription getPrimaryClipDescription() { 122 try { 123 return getService().getPrimaryClipDescription(); 124 } catch (RemoteException e) { 125 return null; 126 } 127 } 128 129 /** 130 * Returns true if there is currently a primary clip on the clipboard. 131 */ 132 public boolean hasPrimaryClip() { 133 try { 134 return getService().hasPrimaryClip(); 135 } catch (RemoteException e) { 136 return false; 137 } 138 } 139 140 public void addPrimaryClipChangedListener(OnPrimaryClipChangedListener what) { 141 synchronized (mPrimaryClipChangedListeners) { 142 if (mPrimaryClipChangedListeners.size() == 0) { 143 try { 144 getService().addPrimaryClipChangedListener( 145 mPrimaryClipChangedServiceListener); 146 } catch (RemoteException e) { 147 } 148 } 149 mPrimaryClipChangedListeners.add(what); 150 } 151 } 152 153 public void removePrimaryClipChangedListener(OnPrimaryClipChangedListener what) { 154 synchronized (mPrimaryClipChangedListeners) { 155 mPrimaryClipChangedListeners.remove(what); 156 if (mPrimaryClipChangedListeners.size() == 0) { 157 try { 158 getService().removePrimaryClipChangedListener( 159 mPrimaryClipChangedServiceListener); 160 } catch (RemoteException e) { 161 } 162 } 163 } 164 } 165 166 /** 167 * @deprecated Use {@link #getPrimaryClip()} instead. This retrieves 168 * the primary clip and tries to coerce it to a string. 169 */ 170 public CharSequence getText() { 171 ClipData clip = getPrimaryClip(); 172 if (clip != null && clip.getItemCount() > 0) { 173 return clip.getItemAt(0).coerceToText(mContext); 174 } 175 return null; 176 } 177 178 /** 179 * @deprecated Use {@link #setPrimaryClip(ClipData)} instead. This 180 * creates a ClippedItem holding the given text and sets it as the 181 * primary clip. It has no label or icon. 182 */ 183 public void setText(CharSequence text) { 184 setPrimaryClip(ClipData.newPlainText(null, text)); 185 } 186 187 /** 188 * @deprecated Use {@link #hasPrimaryClip()} instead. 189 */ 190 public boolean hasText() { 191 try { 192 return getService().hasClipboardText(); 193 } catch (RemoteException e) { 194 return false; 195 } 196 } 197 198 void reportPrimaryClipChanged() { 199 Object[] listeners; 200 201 synchronized (mPrimaryClipChangedListeners) { 202 final int N = mPrimaryClipChangedListeners.size(); 203 if (N <= 0) { 204 return; 205 } 206 listeners = mPrimaryClipChangedListeners.toArray(); 207 } 208 209 for (int i=0; i<listeners.length; i++) { 210 ((OnPrimaryClipChangedListener)listeners[i]).onPrimaryClipChanged(); 211 } 212 } 213} 214