Android应用程序类方法onCreate被多次调用

15
我已经在我的Android应用中重载了Application类,并使用ACRA报告系统。 我的应用程序代码看起来像(真实源代码在此处):
public class MyApplication extends Application 
{
    @Override
    public void onCreate() {        
        ACRA.init( this );

        /*
         * Initialize my singletons etc
         * ...
         * ...
         */
        super.onCreate();
    }
}

据我所知,Application对象应该只创建一次,因此onCreate方法应该只被调用一次。问题是,在我的崩溃报告中(来自ACRA),我发现了这个问题:
java.lang.RuntimeException: Unable to create service it.evilsocket.myapp.net.N ...
java.lang.RuntimeException: Unable to create service it.evilsocket.myapp.net.NetworkMonitorService: java.lang.RuntimeException: Unable to create application it.evilsocket.myapp.MyApplication: **java.lang.IllegalStateException: ACRA#init called more than once**
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:2283)
    at android.app.ActivityThread.access$1600(ActivityThread.java:127)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4441)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Unable to create application it.evilsocket.myapp.MyApplication: java.lang.IllegalStateException: ACRA#init called more than once
    at android.app.LoadedApk.makeApplication(LoadedApk.java:495)
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:2269)
    ... 10 more
Caused by: java.lang.IllegalStateException: ACRA#init called more than once
    at org.acra.ACRA.init(ACRA.java:118)
    at it.evilsocket.myapp.MyApplication.onCreate(MyApplication.java:46)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
    at android.app.LoadedApk.makeApplication(LoadedApk.java:492)
    ... 11 more
java.lang.RuntimeException: Unable to create application it.evilsocket.myapp.MyApplication: java.lang.IllegalStateException: ACRA#init called more than once
    at android.app.LoadedApk.makeApplication(LoadedApk.java:495)
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:2269)
    at android.app.ActivityThread.access$1600(ActivityThread.java:127)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4441)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: ACRA#init called more than once
    at org.acra.ACRA.init(ACRA.java:118)
    at it.evilsocket.myapp.MyApplication.onCreate(MyApplication.java:46)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
    at android.app.LoadedApk.makeApplication(LoadedApk.java:492)
    ... 11 more
java.lang.IllegalStateException: ACRA#init called more than once
    at org.acra.ACRA.init(ACRA.java:118)
    at it.evilsocket.myapp.MyApplication.onCreate(MyApplication.java:46)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
    at android.app.LoadedApk.makeApplication(LoadedApk.java:492)
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:2269)
    at android.app.ActivityThread.access$1600(ActivityThread.java:127)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4441)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    at dalvik.system.NativeStart.main(Native Method)

似乎应用程序的onCreate被调用了多次,有什么想法吗?
注意事项:
- 在我的Android XML清单中,我没有使用android:process="string"属性。 - 是的,我确定在我的初始化程序中,我不会意外地调用MyApplication.onCreate。

3
我不是在谈论Activity.onCreate(通常在每次配置更改时调用),而是Application.onCreate! - Simone Margaritelli
你尝试过在这里设置断点吗? - CommonsWare
这是我在设备上无法复现的问题,我只是从ACRA报告中看到了这个问题...如果我在那里打断点或者放置一个Log.d,onCreate方法只会在我的智能手机和平板电脑上被调用一次。 - Simone Margaritelli
这个问题与所参考的问题并非重复。所参考的问题涉及到Activity.onCreate(),而这里则是关于Application.onCreate()。答案无法合并。 - Kevin Gaudin
你是怎么解决这个问题的? - Harsha M V
在我的情况下,应用程序类的onCreate方法仅在我将应用程序安装到移动设备上时被调用,当我杀死应用程序并重新启动它时,并不会每次都被调用。 - Shubham Mogarkar
4个回答

33

我认为你的应用程序中有额外的进程。这就是为什么Application.onCreate会被调用多次的原因。请查看您的清单文件,并尝试查找类似android:process = 的活动或服务。这意味着活动/服务正在第二个Dalvik VM中启动,这就是为什么会创建另一个应用程序实例的原因。


10
如果你查看堆栈跟踪,它看起来像是ACRA.init在调用makeApplication。我怀疑有一些代码检查应用程序是否已经创建,如果没有,则创建它。这可能是由于在调用super.onCreate之前调用了ACRA.init引起的。通常,在覆盖onCreate方法(无论是Application还是Activity)时,建议将super.onCreate作为实现的第一行调用,然后再执行自定义操作。我建议尝试这种方法,看看是否可以解决问题。

这可能是一个解释。我在super.onCreate()之前使用了init来记录ACRA,以便让ACRA尽早报告应用程序创建过程中可能发生的异常。如果更多用户报告此行为,我可能会重新考虑这一点。 - Kevin Gaudin
6
@KevinGaudin - 我已经尝试在 super.onCreate() 之后使用 Acra 的 init 方法,但是有时仍会出现 "ACRA#init called more than once" 错误。 - Amir Uval
3
我可以确认,即使在super()之后调用ACRA.init(),此问题仍然会发生。 - Aswin Kumar
1
我同意你的观点,@AswinKumar - thecr0w

6

我发现ACRA 4.4.0在实际应用中也存在这个问题。

也许只需要在init方法下加入这样简单的代码?

if (mApplication != null) {
    throw new IllegalStateException("ACRA#init called more than once");
    //(return or finish or gracefully exit somehow)       
} else {
    mApplication = app;
    //and then continue with rest of acra init...

编辑:2012年12月27日作为对此事的跟进,看起来Kevin已经采用了这些更改。详情请参见:https://github.com/ACRA/acra/commit/cda06f5b803a09e9e7cc7dafae2c65c8fa69b861


1

最近我一直在查看ACRA源代码,认为这个问题已经有两种方式在ACRA中得到解决:

  1. 现在ACRA的文档建议在attachBaseContext中初始化ACRA,而不是onCreate()。
  2. ACRA确实有一些逻辑来检查初始化期间是否存在其他ACRA实例。如果是,则ACRA将注销现有的报告者并通过某些代理处理绕过当前报告者。

请检查ACRA.kt中的init函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接