La aplicación de Android se reinicia automáticamente después de un error
Mi aplicación está parcialmente escrita en aplicación nativa mediante C / C ++. El problema es que cada vez que C / C ++ parte se bloquea por alguna razón la aplicación muere y luego se reinicia automáticamente. Esto causa todo tipo de problemas desordenados
Ahora, por supuesto, no debe estrellarse en la parte nativa y estoy tratando de eliminar todas las razones por las que sucedería. Sin embargo, si sucede, me gustaría:
- Cómo agregar la biblioteca preconstruida * .so en android studio 2.2
- Utilizar una clase simple de C ++ en Android NDK
- ¿Cómo puedo vincular la biblioteca compartida precompuesta al proyecto NDK de Android?
- Android sólo juego en OpenGL: rendimiento en C ++ (NDK) vs Java (Dalvik)
- ¿Cómo ejecuto valgrind con una aplicación de Android?
- Salir con gracia
- Si se muere, por lo menos no intentar reiniciar automáticamente.
Tengo curiosidad por saber por qué ocurre este comportamiento. Después de una cierta búsqueda intenté poner la línea siguiente en el elemento principal de la actividad del AndroidManifest.xml:
android:finishOnTaskLaunch="true"
Pero la restauración automática todavía sucede.
¿Alguien sabe por qué está sucediendo esto y cómo cambiarlo?
UPDATE: Creo que una pregunta más fundamental es,
¿Hay algo similar a una devolución de llamada si hay un fallo nativo?
Una de las respuestas sugirió "manejar señales de choque". Estaría agradecido por cualquier vínculo sobre cómo se puede hacer en una aplicación o nivel de módulo.
En este momento, si hay un bloqueo de la aplicación simplemente desaparece, no hay nada en logcat, por lo que no es posible la depuración.
- Depuración de la biblioteca estática NDK de Android (¿combinar proyectos?)
- Enviar tareas a un grupo de subprocesos proporciona RejectedExecutionException
- Cómo obtener efecto de color mágico como escáner de cámara utilizando OpenCV
- SIG33 al depurar el Android nativo
- ¿Qué es el Native Development Kit (NDK) de Android?
- Ubicación grabable y ejecutable en Android
- Compila OpenSSL 1.1.0 para Android
- No se puede escribir en el registro ARM R4: feature o bug?
Trate de manejar las señales de choque (SIGSEGV etc) y enviar matar a ti mismo en el controlador de señales. Este truco me ayuda.
Ejemplo:
#include <signal.h> #include <unistd.h> static void signal_handler(int signal, siginfo_t *info, void *reserved) { kill(getpid(),SIGKILL); } extern "C" jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) { struct sigaction handler; memset(&handler, 0, sizeof(handler)); handler.sa_sigaction = signal_handler; handler.sa_flags = SA_SIGINFO; sigaction(SIGILL, &handler, NULL); sigaction(SIGABRT, &handler, NULL); sigaction(SIGBUS, &handler, NULL); sigaction(SIGFPE, &handler, NULL); sigaction(SIGSEGV, &handler, NULL); sigaction(SIGSTKFLT, &handler, NULL); return(JNI_VERSION_1_6); }
UPDATE2
Si quieres ver crashlog en android logcat deberías usar este controlador de señales
static void signal_handler(int signal, siginfo_t *info, void *reserved) { struct sockaddr_un addr; size_t namelen; socklen_t alen; int s, err; char name[] = "android:debuggerd"; namelen = strlen(name); // Test with length +1 for the *initial* '\0'. if ((namelen + 1) > sizeof(addr.sun_path)) { errno = EINVAL; return; } /* This is used for abstract socket namespace, we need * an initial '\0' at the start of the Unix socket path. * * Note: The path in this case is *not* supposed to be * '\0'-terminated. ("man 7 unix" for the gory details.) */ memset (&addr, 0, sizeof addr); addr.sun_family = AF_LOCAL; addr.sun_path[0] = 0; memcpy(addr.sun_path + 1, name, namelen); alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; s = socket(AF_LOCAL, SOCK_STREAM, 0); if(s < 0) return; RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen)); if (err < 0) { close(s); s = -1; } pid_t tid = gettid(); if(s>=0) { /* debugger knows our pid from the credentials on the * local socket but we need to tell it our tid. It * is paranoid and will verify that we are giving a tid * that's actually in our process */ int ret; RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned))); if (ret == sizeof(unsigned)) { /* if the write failed, there is no point to read on * the file descriptor. */ RETRY_ON_EINTR(ret, read(s, &tid, 1)); //notify_gdb_of_libraries(); } close(s); } wait(NULL); kill(getpid(),SIGKILL); }
Lo tomé de la fuente de android (no puedo insertar el enlace porque android.git.kernel.org está inactivo), pero no estoy seguro de que funcione en futuras versiones de Android
De forma predeterminada, su aplicación no debe reiniciarse automáticamente. Por lo general uno tendría que registrarse para este tipo de cosas, por ejemplo, a través de AlarmManager / keep alives.
¿Tiene un servicio como parte de su aplicación?
- Cómo puedo ver el diseño largo en vista previa en Android Studio
- SearchView no filtrar en cada niño Tab de TabLayout