Приложение Android автоматически перезагружается после сбоя - PullRequest
23 голосов
/ 30 августа 2011

Мое приложение частично написано в нативном приложении с использованием C / C ++.Проблема в том, что всякий раз, когда по какой-либо причине происходит сбой компонента C / C ++, приложение умирает, а затем автоматически перезапускается.Это вызывает все виды беспорядочных проблем

Теперь, конечно, он не должен не падать в исходной части, и я пытаюсь отсеять все причины, почемубывает.Однако, если это произойдет, я бы хотел:

  1. Изящно завершить работу
  2. Если это произойдет, по крайней мере, не пытайтесь перезапустить автоматически.

Мне любопытно, почему такое поведение происходит.После некоторого поиска я попытался вставить следующую строку в основной элемент активности AndroidManifest.xml:

android:finishOnTaskLaunch="true"

, но автоматическое восстановление все еще происходит.

Кто-нибудь знает, почему это происходит и какизменить это?

ОБНОВЛЕНИЕ: Я думаю, что более фундаментальный вопрос,
Есть ли что-то похожее на обратный вызов, если происходит собственный сбой?

В одном из ответов предлагалось «обработка сигналов сбоя».Я был бы признателен за любые ссылки на то, как это можно сделать на уровне приложения или модуля.

В настоящее время, если происходит сбой, приложение просто исчезает, в logcat ничего не происходит, поэтому отладки нет.возможно.

Ответы [ 2 ]

14 голосов
/ 12 сентября 2011

Попробуйте обработать сигналы сбоя (SIGSEGV и т. Д.) И отправьте уничтожение себе в обработчик сигналов.Этот трюк мне помогает.

Пример:

#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);
}

ОБНОВЛЕНИЕ2

, если вы хотите увидеть аварийный журнал в Android LogCat, вы должны использовать этот обработчик сигнала

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);
}

Я взял его из источника Android (не могу вставить ссылку, потому что android.git.kernel.org не работает), но я не уверен, что он будет работать в будущих выпусках Android

0 голосов
/ 06 сентября 2011

По умолчанию ваше приложение не должно автоматически перезагружаться.Как правило, для этого нужно зарегистрироваться, например, через AlarmManager / keep alives.

Есть ли у вас служба как часть вашего приложения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...