• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.content;
18 
19 import android.annotation.SystemService;
20 import android.os.Handler;
21 import android.os.Message;
22 import android.os.RemoteException;
23 import android.os.ServiceManager;
24 import android.os.ServiceManager.ServiceNotFoundException;
25 
26 import java.util.ArrayList;
27 
28 /**
29  * Interface to the clipboard service, for placing and retrieving text in
30  * the global clipboard.
31  *
32  * <p>
33  * The ClipboardManager API itself is very simple: it consists of methods
34  * to atomically get and set the current primary clipboard data.  That data
35  * is expressed as a {@link ClipData} object, which defines the protocol
36  * for data exchange between applications.
37  *
38  * <div class="special reference">
39  * <h3>Developer Guides</h3>
40  * <p>For more information about using the clipboard framework, read the
41  * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
42  * developer guide.</p>
43  * </div>
44  */
45 @SystemService(Context.CLIPBOARD_SERVICE)
46 public class ClipboardManager extends android.text.ClipboardManager {
47     private final Context mContext;
48     private final IClipboard mService;
49 
50     private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners
51              = new ArrayList<OnPrimaryClipChangedListener>();
52 
53     private final IOnPrimaryClipChangedListener.Stub mPrimaryClipChangedServiceListener
54             = new IOnPrimaryClipChangedListener.Stub() {
55         public void dispatchPrimaryClipChanged() {
56             mHandler.sendEmptyMessage(MSG_REPORT_PRIMARY_CLIP_CHANGED);
57         }
58     };
59 
60     static final int MSG_REPORT_PRIMARY_CLIP_CHANGED = 1;
61 
62     private final Handler mHandler = new Handler() {
63         @Override
64         public void handleMessage(Message msg) {
65             switch (msg.what) {
66                 case MSG_REPORT_PRIMARY_CLIP_CHANGED:
67                     reportPrimaryClipChanged();
68             }
69         }
70     };
71 
72     /**
73      * Defines a listener callback that is invoked when the primary clip on the clipboard changes.
74      * Objects that want to register a listener call
75      * {@link android.content.ClipboardManager#addPrimaryClipChangedListener(OnPrimaryClipChangedListener)
76      * addPrimaryClipChangedListener()} with an
77      * object that implements OnPrimaryClipChangedListener.
78      *
79      */
80     public interface OnPrimaryClipChangedListener {
81 
82         /**
83          * Callback that is invoked by {@link android.content.ClipboardManager} when the primary
84          * clip changes.
85          */
onPrimaryClipChanged()86         void onPrimaryClipChanged();
87     }
88 
89     /** {@hide} */
ClipboardManager(Context context, Handler handler)90     public ClipboardManager(Context context, Handler handler) throws ServiceNotFoundException {
91         mContext = context;
92         mService = IClipboard.Stub.asInterface(
93                 ServiceManager.getServiceOrThrow(Context.CLIPBOARD_SERVICE));
94     }
95 
96     /**
97      * Sets the current primary clip on the clipboard.  This is the clip that
98      * is involved in normal cut and paste operations.
99      *
100      * @param clip The clipped data item to set.
101      */
setPrimaryClip(ClipData clip)102     public void setPrimaryClip(ClipData clip) {
103         try {
104             if (clip != null) {
105                 clip.prepareToLeaveProcess(true);
106             }
107             mService.setPrimaryClip(clip, mContext.getOpPackageName());
108         } catch (RemoteException e) {
109             throw e.rethrowFromSystemServer();
110         }
111     }
112 
113     /**
114      * Returns the current primary clip on the clipboard.
115      */
getPrimaryClip()116     public ClipData getPrimaryClip() {
117         try {
118             return mService.getPrimaryClip(mContext.getOpPackageName());
119         } catch (RemoteException e) {
120             throw e.rethrowFromSystemServer();
121         }
122     }
123 
124     /**
125      * Returns a description of the current primary clip on the clipboard
126      * but not a copy of its data.
127      */
getPrimaryClipDescription()128     public ClipDescription getPrimaryClipDescription() {
129         try {
130             return mService.getPrimaryClipDescription(mContext.getOpPackageName());
131         } catch (RemoteException e) {
132             throw e.rethrowFromSystemServer();
133         }
134     }
135 
136     /**
137      * Returns true if there is currently a primary clip on the clipboard.
138      */
hasPrimaryClip()139     public boolean hasPrimaryClip() {
140         try {
141             return mService.hasPrimaryClip(mContext.getOpPackageName());
142         } catch (RemoteException e) {
143             throw e.rethrowFromSystemServer();
144         }
145     }
146 
addPrimaryClipChangedListener(OnPrimaryClipChangedListener what)147     public void addPrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
148         synchronized (mPrimaryClipChangedListeners) {
149             if (mPrimaryClipChangedListeners.isEmpty()) {
150                 try {
151                     mService.addPrimaryClipChangedListener(
152                             mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
153                 } catch (RemoteException e) {
154                     throw e.rethrowFromSystemServer();
155                 }
156             }
157             mPrimaryClipChangedListeners.add(what);
158         }
159     }
160 
removePrimaryClipChangedListener(OnPrimaryClipChangedListener what)161     public void removePrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
162         synchronized (mPrimaryClipChangedListeners) {
163             mPrimaryClipChangedListeners.remove(what);
164             if (mPrimaryClipChangedListeners.isEmpty()) {
165                 try {
166                     mService.removePrimaryClipChangedListener(
167                             mPrimaryClipChangedServiceListener);
168                 } catch (RemoteException e) {
169                     throw e.rethrowFromSystemServer();
170                 }
171             }
172         }
173     }
174 
175     /**
176      * @deprecated Use {@link #getPrimaryClip()} instead.  This retrieves
177      * the primary clip and tries to coerce it to a string.
178      */
179     @Deprecated
getText()180     public CharSequence getText() {
181         ClipData clip = getPrimaryClip();
182         if (clip != null && clip.getItemCount() > 0) {
183             return clip.getItemAt(0).coerceToText(mContext);
184         }
185         return null;
186     }
187 
188     /**
189      * @deprecated Use {@link #setPrimaryClip(ClipData)} instead.  This
190      * creates a ClippedItem holding the given text and sets it as the
191      * primary clip.  It has no label or icon.
192      */
193     @Deprecated
setText(CharSequence text)194     public void setText(CharSequence text) {
195         setPrimaryClip(ClipData.newPlainText(null, text));
196     }
197 
198     /**
199      * @deprecated Use {@link #hasPrimaryClip()} instead.
200      */
201     @Deprecated
hasText()202     public boolean hasText() {
203         try {
204             return mService.hasClipboardText(mContext.getOpPackageName());
205         } catch (RemoteException e) {
206             throw e.rethrowFromSystemServer();
207         }
208     }
209 
reportPrimaryClipChanged()210     void reportPrimaryClipChanged() {
211         Object[] listeners;
212 
213         synchronized (mPrimaryClipChangedListeners) {
214             final int N = mPrimaryClipChangedListeners.size();
215             if (N <= 0) {
216                 return;
217             }
218             listeners = mPrimaryClipChangedListeners.toArray();
219         }
220 
221         for (int i=0; i<listeners.length; i++) {
222             ((OnPrimaryClipChangedListener)listeners[i]).onPrimaryClipChanged();
223         }
224     }
225 }
226