blob: a79f0602ad11bca62809d6fca2cb5fd432b553be [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 *
Dianne Hackborn9f531192010-08-04 17:48:03 -070043 * @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 */
Dianne Hackborn1040dc42010-08-26 22:11:06 -070099 public void setPrimaryClip(ClipData clip) {
Dianne Hackborn9f531192010-08-04 17:48:03 -0700100 try {
101 getService().setPrimaryClip(clip);
102 } catch (RemoteException e) {
103 }
104 }
105
106 /**
107 * Returns the current primary clip on the clipboard.
108 */
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700109 public ClipData getPrimaryClip() {
Dianne Hackborn9f531192010-08-04 17:48:03 -0700110 try {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -0700111 return getService().getPrimaryClip(mContext.getPackageName());
Dianne Hackborn9f531192010-08-04 17:48:03 -0700112 } catch (RemoteException e) {
113 return null;
114 }
115 }
116
117 /**
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700118 * 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 /**
Dianne Hackborn9f531192010-08-04 17:48:03 -0700130 * 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() {
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700171 ClipData clip = getPrimaryClip();
Dianne Hackborn9f531192010-08-04 17:48:03 -0700172 if (clip != null && clip.getItemCount() > 0) {
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800173 return clip.getItemAt(0).coerceToText(mContext);
Dianne Hackborn9f531192010-08-04 17:48:03 -0700174 }
175 return null;
176 }
177
178 /**
Dianne Hackborn1040dc42010-08-26 22:11:06 -0700179 * @deprecated Use {@link #setPrimaryClip(ClipData)} instead. This
Dianne Hackborn9f531192010-08-04 17:48:03 -0700180 * 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) {
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800184 setPrimaryClip(ClipData.newPlainText(null, text));
Dianne Hackborn9f531192010-08-04 17:48:03 -0700185 }
186
187 /**
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700188 * @deprecated Use {@link #hasPrimaryClip()} instead.
Dianne Hackborn9f531192010-08-04 17:48:03 -0700189 */
190 public boolean hasText() {
191 try {
Brian Muramatsu3f6b3b62010-11-19 15:28:06 -0800192 return getService().hasClipboardText();
Dianne Hackborn9f531192010-08-04 17:48:03 -0700193 } 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}