1/*
2 * Copyright (C) 2007 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.app;
18
19import org.xmlpull.v1.XmlPullParser;
20import org.xmlpull.v1.XmlPullParserException;
21
22import android.content.Intent;
23import android.content.pm.ActivityInfo;
24import android.content.pm.PackageManager;
25import android.content.res.XmlResourceParser;
26import android.os.Bundle;
27import android.util.AttributeSet;
28import android.util.Xml;
29
30import com.android.internal.util.XmlUtils;
31
32import java.io.IOException;
33
34/**
35 * Stub activity that launches another activity (and then finishes itself)
36 * based on information in its component's manifest meta-data.  This is a
37 * simple way to implement an alias-like mechanism.
38 *
39 * To use this activity, you should include in the manifest for the associated
40 * component an entry named "android.app.alias".  It is a reference to an XML
41 * resource describing an intent that launches the real application.
42 */
43public class AliasActivity extends Activity {
44    /**
45     * This is the name under which you should store in your component the
46     * meta-data information about the alias.  It is a reference to an XML
47     * resource describing an intent that launches the real application.
48     * {@hide}
49     */
50    public final String ALIAS_META_DATA = "android.app.alias";
51
52    @Override
53    protected void onCreate(Bundle savedInstanceState) {
54        super.onCreate(savedInstanceState);
55
56        XmlResourceParser parser = null;
57        try {
58            ActivityInfo ai = getPackageManager().getActivityInfo(
59                    getComponentName(), PackageManager.GET_META_DATA);
60            parser = ai.loadXmlMetaData(getPackageManager(),
61                    ALIAS_META_DATA);
62            if (parser == null) {
63                throw new RuntimeException("Alias requires a meta-data field "
64                        + ALIAS_META_DATA);
65            }
66
67            Intent intent = parseAlias(parser);
68            if (intent == null) {
69                throw new RuntimeException(
70                        "No <intent> tag found in alias description");
71            }
72
73            startActivity(intent);
74            finish();
75
76        } catch (PackageManager.NameNotFoundException e) {
77            throw new RuntimeException("Error parsing alias", e);
78        } catch (XmlPullParserException e) {
79            throw new RuntimeException("Error parsing alias", e);
80        } catch (IOException e) {
81            throw new RuntimeException("Error parsing alias", e);
82        } finally {
83            if (parser != null) parser.close();
84        }
85    }
86
87    private Intent parseAlias(XmlPullParser parser)
88            throws XmlPullParserException, IOException {
89        AttributeSet attrs = Xml.asAttributeSet(parser);
90
91        Intent intent = null;
92
93        int type;
94        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
95                && type != XmlPullParser.START_TAG) {
96        }
97
98        String nodeName = parser.getName();
99        if (!"alias".equals(nodeName)) {
100            throw new RuntimeException(
101                    "Alias meta-data must start with <alias> tag; found"
102                    + nodeName + " at " + parser.getPositionDescription());
103        }
104
105        int outerDepth = parser.getDepth();
106        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
107               && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
108            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
109                continue;
110            }
111
112            nodeName = parser.getName();
113            if ("intent".equals(nodeName)) {
114                Intent gotIntent = Intent.parseIntent(getResources(), parser, attrs);
115                if (intent == null) intent = gotIntent;
116            } else {
117                XmlUtils.skipCurrentTag(parser);
118            }
119        }
120
121        return intent;
122    }
123
124}
125