09-28 18:20:06.480 I/ActivityManager( 83): Process
edu.cmu.pocketsphinx.demo (pid 1303) has died.
09-28 18:20:06.480 E/ActivityManager( 83): fail to set top app changed!
09-28 18:20:06.490 D/Sensors ( 83): close_akm, fd=120
09-28 18:20:06.490 D/Zygote ( 56): Process 1303 exited cleanly (255)
...but whenever I've seen a spontaneous application death like that,
it's been accompanied by a stack trace, which doesn't seem to appear in
your log. :/
If I had to guess, I'd say that something in the JNI is calling exit(),
possibly due to an error condition...or that the main application is
exiting, again possibly due to some kind of failure. Even if it were to
throw a signal or otherwise crash, it should end up with a stack trace.
Does it just exit when you run it? It looks like it does. You might be
stuck throwing in log messages to get an idea of how far it gets before
> I think that is the problem. Because when i running this program in
> emulator, when i startup the program again once return to home, the
> emulator show black screen. I need to clicked the icon of the program
> more than one times than only the program can start.
So sometimes it runs correctly, but sometimes it fails? Sounds like the
program isn't handling "onStop/onDestroy" correctly.
Due to the Java-centric nature of Android, it assumes it can reuse an
instance of an executable by simply handing it a new Java object. See
the Activity lifecycle on this page:
With respect to Java, this may be technically correct, but it's
deceptive, and with respect to the NDK, it's wrong: after "onDestroy"
the application is NOT shut down, it simply goes back to onCreate()
again. So if your NDK code has any static variables, they're still
And it gets worse, actually: The onCreate() can (and tends to) happen
before the onDestroy() from the previous run. I discovered this by
reading Android platform source code, where they were handling that case
internally. So you can't be safe in killing your app in onDestroy(),
because the next instance's onCreate() might have already happened, and
then onDestroy() will destroy the state from the NEW instance that's
trying to start up.
I track the main Java object, and if it changes, I destroy the old state
and ignore any additional JNI calls coming from the old state (like the
inevitable onDestroy() call that would otherwise kill my state). To
compare the Java objects, you should use the JNI call IsSameObject(),
since the pointers aren't guaranteed to be equal (though in fact they
tend to be).
I really can't tell you specifically what you need to do, pretty much at
all. My intent was to let you know of a pitfall that may be biting you.
In particular, TWO different instances of the Java application may
coexist for a short time, and depending on your Java code, may be trying
to access the same C++ code simultaneously (maybe even from different
threads? I don't recall). Look at how your JNI code is bound to Java,
what state it contains, and how it manages that state.
Your objective is to understand what is REALLY going on, and once you
have that understanding, then you'll know whether you need an
onDestroy(), or a flag to prevent a double-initialization in JNI, or
what other change you need to make to fix it. Worst case, pepper the
code with log statements, especially around anywhere there's a call to
"assert" or "exit", directly or indirectly. Track down WHY (or at least
WHERE) it's exiting. Once you understand THAT, you'll have a better
chance of understanding the big picture.