blob: 800d0d248005ccf5b48438c453aa158f93371717 [file] [log] [blame]
Dianne Hackborn9f531192010-08-04 17:48:03 -07001/**
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 *
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070037 * <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
Dianne Hackborn1040dc42010-08-26 22:11:06 -070040 * is expressed as a {@link ClipData} object, which defines the protocol
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070041 * for data exchange between applications.
42 *
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080043 * <div class="special reference">
44 * <h3>Developer Guides</h3>
45 * <p>For more information about using the clipboard framework, read the
46 * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
47 * developer guide.</p>
48 * </div>
49 *
Dianne Hackborn9f531192010-08-04 17:48:03 -070050 * @see android.content.Context#getSystemService
51 */
52public class ClipboardManager extends android.text.ClipboardManager {
53 private final static Object sStaticLock = new Object();
54 private static IClipboard sService;
55
56 private final Context mContext;
57
58 private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners
59 = new ArrayList<OnPrimaryClipChangedListener>();
60
61 private final IOnPrimaryClipChangedListener.Stub mPrimaryClipChangedServiceListener
62 = new IOnPrimaryClipChangedListener.Stub() {
63 public void dispatchPrimaryClipChanged() {
64 mHandler.sendEmptyMessage(MSG_REPORT_PRIMARY_CLIP_CHANGED);
65 }
66 };
67
68 static final int MSG_REPORT_PRIMARY_CLIP_CHANGED = 1;
69
70 private final Handler mHandler = new Handler() {
71 @Override
72 public void handleMessage(Message msg) {
73 switch (msg.what) {
74 case MSG_REPORT_PRIMARY_CLIP_CHANGED:
75 reportPrimaryClipChanged();
76 }
77 }
78 };
79
80 public interface OnPrimaryClipChangedListener {
81 void onPrimaryClipChanged();
82 }
83
84 static private IClipboard getService() {
85 synchronized (sStaticLock) {
86 if (sService != null) {
87 return sService;
88 }
89 IBinder b = ServiceManager.getService("clipboard");
90 sService = IClipboard.Stub.asInterface(b);
91 return sService;
92 }
93 }
94
95 /** {@hide} */
96 public ClipboardManager(Context context, Handler handler) {
97 mContext = context;
98 }
99
100 /**
101 * Sets the current primary clip on the clipboard. This is the clip that
102 * is involved in normal cut and paste operations.
103 *
104 * @param clip The clipped data item to set.
105 */
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700106 public void setPrimaryClip(ClipData clip) {
Dianne Hackborn9f531192010-08-04 17:48:03 -0700107 try {
108 getService().setPrimaryClip(clip);
109 } catch (RemoteException e) {
110 }
111 }
112
113 /**
114 * Returns the current primary clip on the clipboard.
115 */
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700116 public ClipData getPrimaryClip() {
Dianne Hackborn9f531192010-08-04 17:48:03 -0700117 try {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -0700118 return getService().getPrimaryClip(mContext.getPackageName());
Dianne Hackborn9f531192010-08-04 17:48:03 -0700119 } catch (RemoteException e) {
120 return null;
121 }
122 }
123
124 /**
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700125 * Returns a description of the current primary clip on the clipboard
126 * but not a copy of its data.
127 */
128 public ClipDescription getPrimaryClipDescription() {
129 try {
130 return getService().getPrimaryClipDescription();
131 } catch (RemoteException e) {
132 return null;
133 }
134 }
135
136 /**
Dianne Hackborn9f531192010-08-04 17:48:03 -0700137 * Returns true if there is currently a primary clip on the clipboard.
138 */
139 public boolean hasPrimaryClip() {
140 try {
141 return getService().hasPrimaryClip();
142 } catch (RemoteException e) {
143 return false;
144 }
145 }
146
147 public void addPrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
148 synchronized (mPrimaryClipChangedListeners) {
149 if (mPrimaryClipChangedListeners.size() == 0) {
150 try {
151 getService().addPrimaryClipChangedListener(
152 mPrimaryClipChangedServiceListener);
153 } catch (RemoteException e) {
154 }
155 }
156 mPrimaryClipChangedListeners.add(what);
157 }
158 }
159
160 public void removePrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
161 synchronized (mPrimaryClipChangedListeners) {
162 mPrimaryClipChangedListeners.remove(what);
163 if (mPrimaryClipChangedListeners.size() == 0) {
164 try {
165 getService().removePrimaryClipChangedListener(
166 mPrimaryClipChangedServiceListener);
167 } catch (RemoteException e) {
168 }
169 }
170 }
171 }
172
173 /**
174 * @deprecated Use {@link #getPrimaryClip()} instead. This retrieves
175 * the primary clip and tries to coerce it to a string.
176 */
177 public CharSequence getText() {
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700178 ClipData clip = getPrimaryClip();
Dianne Hackborn9f531192010-08-04 17:48:03 -0700179 if (clip != null && clip.getItemCount() > 0) {
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800180 return clip.getItemAt(0).coerceToText(mContext);
Dianne Hackborn9f531192010-08-04 17:48:03 -0700181 }
182 return null;
183 }
184
185 /**
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700186 * @deprecated Use {@link #setPrimaryClip(ClipData)} instead. This
Dianne Hackborn9f531192010-08-04 17:48:03 -0700187 * creates a ClippedItem holding the given text and sets it as the
188 * primary clip. It has no label or icon.
189 */
190 public void setText(CharSequence text) {
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800191 setPrimaryClip(ClipData.newPlainText(null, text));
Dianne Hackborn9f531192010-08-04 17:48:03 -0700192 }
193
194 /**
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700195 * @deprecated Use {@link #hasPrimaryClip()} instead.
Dianne Hackborn9f531192010-08-04 17:48:03 -0700196 */
197 public boolean hasText() {
198 try {
Brian Muramatsu3f6b3b62010-11-19 15:28:06 -0800199 return getService().hasClipboardText();
Dianne Hackborn9f531192010-08-04 17:48:03 -0700200 } catch (RemoteException e) {
201 return false;
202 }
203 }
204
205 void reportPrimaryClipChanged() {
206 Object[] listeners;
207
208 synchronized (mPrimaryClipChangedListeners) {
209 final int N = mPrimaryClipChangedListeners.size();
210 if (N <= 0) {
211 return;
212 }
213 listeners = mPrimaryClipChangedListeners.toArray();
214 }
215
216 for (int i=0; i<listeners.length; i++) {
217 ((OnPrimaryClipChangedListener)listeners[i]).onPrimaryClipChanged();
218 }
219 }
220}