ClipboardManager.java revision 9f53119b72e6da865bcd53173d3dacd1eba01aee
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 * @see android.content.Context#getSystemService
38 */
39public class ClipboardManager extends android.text.ClipboardManager {
40    private final static Object sStaticLock = new Object();
41    private static IClipboard sService;
42
43    private final Context mContext;
44
45    private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners
46             = new ArrayList<OnPrimaryClipChangedListener>();
47
48    private final IOnPrimaryClipChangedListener.Stub mPrimaryClipChangedServiceListener
49            = new IOnPrimaryClipChangedListener.Stub() {
50        public void dispatchPrimaryClipChanged() {
51            mHandler.sendEmptyMessage(MSG_REPORT_PRIMARY_CLIP_CHANGED);
52        }
53    };
54
55    static final int MSG_REPORT_PRIMARY_CLIP_CHANGED = 1;
56
57    private final Handler mHandler = new Handler() {
58        @Override
59        public void handleMessage(Message msg) {
60            switch (msg.what) {
61                case MSG_REPORT_PRIMARY_CLIP_CHANGED:
62                    reportPrimaryClipChanged();
63            }
64        }
65    };
66
67    public interface OnPrimaryClipChangedListener {
68        void onPrimaryClipChanged();
69    }
70
71    static private IClipboard getService() {
72        synchronized (sStaticLock) {
73            if (sService != null) {
74                return sService;
75            }
76            IBinder b = ServiceManager.getService("clipboard");
77            sService = IClipboard.Stub.asInterface(b);
78            return sService;
79        }
80    }
81
82    /** {@hide} */
83    public ClipboardManager(Context context, Handler handler) {
84        mContext = context;
85    }
86
87    /**
88     * Sets the current primary clip on the clipboard.  This is the clip that
89     * is involved in normal cut and paste operations.
90     *
91     * @param clip The clipped data item to set.
92     */
93    public void setPrimaryClip(ClippedData clip) {
94        try {
95            getService().setPrimaryClip(clip);
96        } catch (RemoteException e) {
97        }
98    }
99
100    /**
101     * Returns the current primary clip on the clipboard.
102     */
103    public ClippedData getPrimaryClip() {
104        try {
105            return getService().getPrimaryClip();
106        } catch (RemoteException e) {
107            return null;
108        }
109    }
110
111    /**
112     * Returns true if there is currently a primary clip on the clipboard.
113     */
114    public boolean hasPrimaryClip() {
115        try {
116            return getService().hasPrimaryClip();
117        } catch (RemoteException e) {
118            return false;
119        }
120    }
121
122    public void addPrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
123        synchronized (mPrimaryClipChangedListeners) {
124            if (mPrimaryClipChangedListeners.size() == 0) {
125                try {
126                    getService().addPrimaryClipChangedListener(
127                            mPrimaryClipChangedServiceListener);
128                } catch (RemoteException e) {
129                }
130            }
131            mPrimaryClipChangedListeners.add(what);
132        }
133    }
134
135    public void removePrimaryClipChangedListener(OnPrimaryClipChangedListener what) {
136        synchronized (mPrimaryClipChangedListeners) {
137            mPrimaryClipChangedListeners.remove(what);
138            if (mPrimaryClipChangedListeners.size() == 0) {
139                try {
140                    getService().removePrimaryClipChangedListener(
141                            mPrimaryClipChangedServiceListener);
142                } catch (RemoteException e) {
143                }
144            }
145        }
146    }
147
148    /**
149     * @deprecated Use {@link #getPrimaryClip()} instead.  This retrieves
150     * the primary clip and tries to coerce it to a string.
151     */
152    public CharSequence getText() {
153        ClippedData clip = getPrimaryClip();
154        if (clip != null && clip.getItemCount() > 0) {
155            return clip.getItem(0).getText();
156        }
157        return null;
158    }
159
160    /**
161     * @deprecated Use {@link #setPrimaryClip(ClippedData)} instead.  This
162     * creates a ClippedItem holding the given text and sets it as the
163     * primary clip.  It has no label or icon.
164     */
165    public void setText(CharSequence text) {
166        setPrimaryClip(new ClippedData(null, null, new ClippedData.Item(text)));
167    }
168
169    /**
170     * Returns true if the clipboard has a primary clip containing text; false otherwise.
171     */
172    public boolean hasText() {
173        try {
174            return getService().hasClipboardText();
175        } catch (RemoteException e) {
176            return false;
177        }
178    }
179
180    void reportPrimaryClipChanged() {
181        Object[] listeners;
182
183        synchronized (mPrimaryClipChangedListeners) {
184            final int N = mPrimaryClipChangedListeners.size();
185            if (N <= 0) {
186                return;
187            }
188            listeners = mPrimaryClipChangedListeners.toArray();
189        }
190
191        for (int i=0; i<listeners.length; i++) {
192            ((OnPrimaryClipChangedListener)listeners[i]).onPrimaryClipChanged();
193        }
194    }
195}
196