ComponentName.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/*
2 * Copyright (C) 2006 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.os.Parcel;
20import android.os.Parcelable;
21
22/**
23 * Identifier for a specific application component
24 * ({@link android.app.Activity}, {@link android.app.Service},
25 * {@link android.content.BroadcastReceiver}, or
26 * {@link android.content.ContentProvider}) that is available.  Two
27 * pieces of information, encapsulated here, are required to identify
28 * a component: the package (a String) it exists in, and the class (a String)
29 * name inside of that package.
30 *
31 */
32public final class ComponentName implements Parcelable {
33    private final String mPackage;
34    private final String mClass;
35
36    /**
37     * Create a new component identifier.
38     *
39     * @param pkg The name of the package that the component exists in.  Can
40     * not be null.
41     * @param cls The name of the class inside of <var>pkg</var> that
42     * implements the component.  Can not be null.
43     */
44    public ComponentName(String pkg, String cls) {
45        if (pkg == null) throw new NullPointerException("package name is null");
46        if (cls == null) throw new NullPointerException("class name is null");
47        mPackage = pkg;
48        mClass = cls;
49    }
50
51    /**
52     * Create a new component identifier from a Context and class name.
53     *
54     * @param pkg A Context for the package implementing the component,
55     * from which the actual package name will be retrieved.
56     * @param cls The name of the class inside of <var>pkg</var> that
57     * implements the component.
58     */
59    public ComponentName(Context pkg, String cls) {
60        if (cls == null) throw new NullPointerException("class name is null");
61        mPackage = pkg.getPackageName();
62        mClass = cls;
63    }
64
65    /**
66     * Create a new component identifier from a Context and Class object.
67     *
68     * @param pkg A Context for the package implementing the component, from
69     * which the actual package name will be retrieved.
70     * @param cls The Class object of the desired component, from which the
71     * actual class name will be retrieved.
72     */
73    public ComponentName(Context pkg, Class<?> cls) {
74        mPackage = pkg.getPackageName();
75        mClass = cls.getName();
76    }
77
78    /**
79     * Return the package name of this component.
80     */
81    public String getPackageName() {
82        return mPackage;
83    }
84
85    /**
86     * Return the class name of this component.
87     */
88    public String getClassName() {
89        return mClass;
90    }
91
92    /**
93     * Return the class name, either fully qualified or in a shortened form
94     * (with a leading '.') if it is a suffix of the package.
95     */
96    public String getShortClassName() {
97        if (mClass.startsWith(mPackage)) {
98            int PN = mPackage.length();
99            int CN = mClass.length();
100            if (CN > PN && mClass.charAt(PN) == '.') {
101                return mClass.substring(PN, CN);
102            }
103        }
104        return mClass;
105    }
106
107    /**
108     * Return a String that unambiguously describes both the package and
109     * class names contained in the ComponentName.  You can later recover
110     * the ComponentName from this string through
111     * {@link #unflattenFromString(String)}.
112     *
113     * @return Returns a new String holding the package and class names.  This
114     * is represented as the package name, concatenated with a '/' and then the
115     * class name.
116     *
117     * @see #unflattenFromString(String)
118     */
119    public String flattenToString() {
120        return mPackage + "/" + mClass;
121    }
122
123    /**
124     * The samee as {@link #flattenToString()}, but abbreviates the class
125     * name if it is a suffix of the package.  The result can still be used
126     * with {@link #unflattenFromString(String)}.
127     *
128     * @return Returns a new String holding the package and class names.  This
129     * is represented as the package name, concatenated with a '/' and then the
130     * class name.
131     *
132     * @see #unflattenFromString(String)
133     */
134    public String flattenToShortString() {
135        return mPackage + "/" + getShortClassName();
136    }
137
138    /**
139     * Recover a ComponentName from a String that was previously created with
140     * {@link #flattenToString()}.  It splits the string at the first '/',
141     * taking the part before as the package name and the part after as the
142     * class name.  As a special convenience (to use, for example, when
143     * parsing component names on the command line), if the '/' is immediately
144     * followed by a '.' then the final class name will be the concatenation
145     * of the package name with the string following the '/'.  Thus
146     * "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah".
147     *
148     * @param str The String that was returned by flattenToString().
149     * @return Returns a new ComponentName containing the package and class
150     * names that were encoded in <var>str</var>
151     *
152     * @see #flattenToString()
153     */
154    public static ComponentName unflattenFromString(String str) {
155        int sep = str.indexOf('/');
156        if (sep < 0 || (sep+1) >= str.length()) {
157            return null;
158        }
159        String pkg = str.substring(0, sep);
160        String cls = str.substring(sep+1);
161        if (cls.length() > 0 && cls.charAt(0) == '.') {
162            cls = pkg + cls;
163        }
164        return new ComponentName(pkg, cls);
165    }
166
167    /**
168     * Return string representation of this class without the class's name
169     * as a prefix.
170     */
171    public String toShortString() {
172        return "{" + mPackage + "/" + mClass + "}";
173    }
174
175    @Override
176    public String toString() {
177        return "ComponentInfo{" + mPackage + "/" + mClass + "}";
178    }
179
180    @Override
181    public boolean equals(Object obj) {
182        try {
183            if (obj != null) {
184                ComponentName other = (ComponentName)obj;
185                // Note: no null checks, because mPackage and mClass can
186                // never be null.
187                return mPackage.equals(other.mPackage)
188                        && mClass.equals(other.mClass);
189            }
190        } catch (ClassCastException e) {
191        }
192        return false;
193    }
194
195    @Override
196    public int hashCode() {
197        return mPackage.hashCode() + mClass.hashCode();
198    }
199
200    public int describeContents() {
201        return 0;
202    }
203
204    public void writeToParcel(Parcel out, int flags) {
205        out.writeString(mPackage);
206        out.writeString(mClass);
207    }
208
209    /**
210     * Write a ComponentName to a Parcel, handling null pointers.  Must be
211     * read with {@link #readFromParcel(Parcel)}.
212     *
213     * @param c The ComponentName to be written.
214     * @param out The Parcel in which the ComponentName will be placed.
215     *
216     * @see #readFromParcel(Parcel)
217     */
218    public static void writeToParcel(ComponentName c, Parcel out) {
219        if (c != null) {
220            c.writeToParcel(out, 0);
221        } else {
222            out.writeString(null);
223        }
224    }
225
226    /**
227     * Read a ComponentName from a Parcel that was previously written
228     * with {@link #writeToParcel(ComponentName, Parcel)}, returning either
229     * a null or new object as appropriate.
230     *
231     * @param in The Parcel from which to read the ComponentName
232     * @return Returns a new ComponentName matching the previously written
233     * object, or null if a null had been written.
234     *
235     * @see #writeToParcel(ComponentName, Parcel)
236     */
237    public static ComponentName readFromParcel(Parcel in) {
238        String pkg = in.readString();
239        return pkg != null ? new ComponentName(pkg, in) : null;
240    }
241
242    public static final Parcelable.Creator<ComponentName> CREATOR
243            = new Parcelable.Creator<ComponentName>() {
244        public ComponentName createFromParcel(Parcel in) {
245            return new ComponentName(in);
246        }
247
248        public ComponentName[] newArray(int size) {
249            return new ComponentName[size];
250        }
251    };
252
253    /**
254     * Instantiate a new ComponentName from the data in a Parcel that was
255     * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
256     * must not use this with data written by
257     * {@link #writeToParcel(ComponentName, Parcel)} since it is not possible
258     * to handle a null ComponentObject here.
259     *
260     * @param in The Parcel containing the previously written ComponentName,
261     * positioned at the location in the buffer where it was written.
262     */
263    public ComponentName(Parcel in) {
264        mPackage = in.readString();
265        if (mPackage == null) throw new NullPointerException(
266                "package name is null");
267        mClass = in.readString();
268        if (mClass == null) throw new NullPointerException(
269                "class name is null");
270    }
271
272    private ComponentName(String pkg, Parcel in) {
273        mPackage = pkg;
274        mClass = in.readString();
275    }
276}
277