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.app;
18
19import java.util.ArrayList;
20
21import android.content.ComponentCallbacks;
22import android.content.ComponentCallbacks2;
23import android.content.Context;
24import android.content.ContextWrapper;
25import android.content.res.Configuration;
26import android.os.Bundle;
27
28/**
29 * Base class for those who need to maintain global application state. You can
30 * provide your own implementation by specifying its name in your
31 * AndroidManifest.xml's <application> tag, which will cause that class
32 * to be instantiated for you when the process for your application/package is
33 * created.
34 *
35 * <p class="note">There is normally no need to subclass Application.  In
36 * most situation, static singletons can provide the same functionality in a
37 * more modular way.  If your singleton needs a global context (for example
38 * to register broadcast receivers), the function to retrieve it can be
39 * given a {@link android.content.Context} which internally uses
40 * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
41 * when first constructing the singleton.</p>
42 */
43public class Application extends ContextWrapper implements ComponentCallbacks2 {
44    private ArrayList<ComponentCallbacks> mComponentCallbacks =
45            new ArrayList<ComponentCallbacks>();
46    private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
47            new ArrayList<ActivityLifecycleCallbacks>();
48
49    /** @hide */
50    public LoadedApk mLoadedApk;
51
52    public interface ActivityLifecycleCallbacks {
53        void onActivityCreated(Activity activity, Bundle savedInstanceState);
54        void onActivityStarted(Activity activity);
55        void onActivityResumed(Activity activity);
56        void onActivityPaused(Activity activity);
57        void onActivityStopped(Activity activity);
58        void onActivitySaveInstanceState(Activity activity, Bundle outState);
59        void onActivityDestroyed(Activity activity);
60    }
61
62    public Application() {
63        super(null);
64    }
65
66    /**
67     * Called when the application is starting, before any activity, service,
68     * or receiver objects (excluding content providers) have been created.
69     * Implementations should be as quick as possible (for example using
70     * lazy initialization of state) since the time spent in this function
71     * directly impacts the performance of starting the first activity,
72     * service, or receiver in a process.
73     * If you override this method, be sure to call super.onCreate().
74     */
75    public void onCreate() {
76    }
77
78    /**
79     * This method is for use in emulated process environments.  It will
80     * never be called on a production Android device, where processes are
81     * removed by simply killing them; no user code (including this callback)
82     * is executed when doing so.
83     */
84    public void onTerminate() {
85    }
86
87    public void onConfigurationChanged(Configuration newConfig) {
88        Object[] callbacks = collectComponentCallbacks();
89        if (callbacks != null) {
90            for (int i=0; i<callbacks.length; i++) {
91                ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
92            }
93        }
94    }
95
96    public void onLowMemory() {
97        Object[] callbacks = collectComponentCallbacks();
98        if (callbacks != null) {
99            for (int i=0; i<callbacks.length; i++) {
100                ((ComponentCallbacks)callbacks[i]).onLowMemory();
101            }
102        }
103    }
104
105    public void onTrimMemory(int level) {
106        Object[] callbacks = collectComponentCallbacks();
107        if (callbacks != null) {
108            for (int i=0; i<callbacks.length; i++) {
109                Object c = callbacks[i];
110                if (c instanceof ComponentCallbacks2) {
111                    ((ComponentCallbacks2)c).onTrimMemory(level);
112                }
113            }
114        }
115    }
116
117    public void registerComponentCallbacks(ComponentCallbacks callback) {
118        synchronized (mComponentCallbacks) {
119            mComponentCallbacks.add(callback);
120        }
121    }
122
123    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
124        synchronized (mComponentCallbacks) {
125            mComponentCallbacks.remove(callback);
126        }
127    }
128
129    public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
130        synchronized (mActivityLifecycleCallbacks) {
131            mActivityLifecycleCallbacks.add(callback);
132        }
133    }
134
135    public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
136        synchronized (mActivityLifecycleCallbacks) {
137            mActivityLifecycleCallbacks.remove(callback);
138        }
139    }
140
141    // ------------------ Internal API ------------------
142
143    /**
144     * @hide
145     */
146    /* package */ final void attach(Context context) {
147        attachBaseContext(context);
148        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
149    }
150
151    /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
152        Object[] callbacks = collectActivityLifecycleCallbacks();
153        if (callbacks != null) {
154            for (int i=0; i<callbacks.length; i++) {
155                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
156                        savedInstanceState);
157            }
158        }
159    }
160
161    /* package */ void dispatchActivityStarted(Activity activity) {
162        Object[] callbacks = collectActivityLifecycleCallbacks();
163        if (callbacks != null) {
164            for (int i=0; i<callbacks.length; i++) {
165                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
166            }
167        }
168    }
169
170    /* package */ void dispatchActivityResumed(Activity activity) {
171        Object[] callbacks = collectActivityLifecycleCallbacks();
172        if (callbacks != null) {
173            for (int i=0; i<callbacks.length; i++) {
174                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
175            }
176        }
177    }
178
179    /* package */ void dispatchActivityPaused(Activity activity) {
180        Object[] callbacks = collectActivityLifecycleCallbacks();
181        if (callbacks != null) {
182            for (int i=0; i<callbacks.length; i++) {
183                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
184            }
185        }
186    }
187
188    /* package */ void dispatchActivityStopped(Activity activity) {
189        Object[] callbacks = collectActivityLifecycleCallbacks();
190        if (callbacks != null) {
191            for (int i=0; i<callbacks.length; i++) {
192                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
193            }
194        }
195    }
196
197    /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
198        Object[] callbacks = collectActivityLifecycleCallbacks();
199        if (callbacks != null) {
200            for (int i=0; i<callbacks.length; i++) {
201                ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
202                        outState);
203            }
204        }
205    }
206
207    /* package */ void dispatchActivityDestroyed(Activity activity) {
208        Object[] callbacks = collectActivityLifecycleCallbacks();
209        if (callbacks != null) {
210            for (int i=0; i<callbacks.length; i++) {
211                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
212            }
213        }
214    }
215
216    private Object[] collectComponentCallbacks() {
217        Object[] callbacks = null;
218        synchronized (mComponentCallbacks) {
219            if (mComponentCallbacks.size() > 0) {
220                callbacks = mComponentCallbacks.toArray();
221            }
222        }
223        return callbacks;
224    }
225
226    private Object[] collectActivityLifecycleCallbacks() {
227        Object[] callbacks = null;
228        synchronized (mActivityLifecycleCallbacks) {
229            if (mActivityLifecycleCallbacks.size() > 0) {
230                callbacks = mActivityLifecycleCallbacks.toArray();
231            }
232        }
233        return callbacks;
234    }
235}
236