Как перезапускать приложение при любом его краше?

Приложение разработано с помощью QT 5.9. Запущено в режиме киоска, пользователь ее выключить не может. Встала задача обеспечить живучесть приложения при его падении по любой причине. Нарыл на просторах интернета вот такую перезагрузку приложения и она даже чуть чуть работает:
MainActivity.java
...
public class MainActivity extends org.qtproject.qt5.android.bindings.QtActivity {
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new Restarter(this));
        if (getIntent().getBooleanExtra("crash", false)) {
			Toast.makeText(this, "Приложение перезапущено после аварийной остановки", Toast.LENGTH_SHORT).show();
		}
...
    }
    public void raiseException() {
        throw new NullPointerException();
    }
}

Restarter.java
public class Restarter implements Thread.UncaughtExceptionHandler {
  private Activity activity;
  public Restarter(Activity a) {
    activity = a;
  }
  @Override
  public void uncaughtException(Thread thread, Throwable ex) {
    Intent intent = new Intent(activity, MainActivity.class);
    intent.putExtra("crash", true);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
      | Intent.FLAG_ACTIVITY_CLEAR_TASK
      | Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(MyApplication.getInstance().getBaseContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager mgr = (AlarmManager) MyApplication.getInstance().getBaseContext().getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
    activity.finish();
    System.exit(2);
  }
}

main.cpp
#if defined(Q_OS_ANDROID)
            QtAndroid::runOnAndroidThread([]{
                QAndroidJniObject myJavaObject("inc.garage.MainActivity");
                myJavaObject.callMethod<void>("raiseException","()V");
            });
#endif

Такой код вызывает java метод raiseException и в результате приложение успешно заваливается и через секунду вновь загружается.

Теперь самое интересное. Как обработать любое падение приложения?
Элементарный throw, вызванный из кода c++ убивает приложение и перезапуска не происходит.
Пробовал и так:
main.cpp
int main(int argc, char *argv[])
{
    int result = 0;
    try {
        qmlRegisterType<Utils>("Utils", 1, 0, "Utils");
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        ncfApp app(argc, argv);
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/interface/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);

        engine.load(url);
        #if defined(Q_OS_ANDROID)
            QQuickWindow *window = qobject_cast<QQuickWindow *>(engine.rootObjects().first());
            window->showFullScreen();
        #endif
throw; //эта ошибка ловится и приложение перезапускается
        result = app.exec();
    } catch (...) {
#if defined(Q_OS_ANDROID)
            QtAndroid::runOnAndroidThread([]{
                QAndroidJniObject myJavaObject("inc.garage.MainActivity");
                myJavaObject.callMethod<void>("raiseException","()V");
            });
#endif
    }
    return result;
}

Но, если из qml части вызывать в обработчике нажатия не кнопку cpp-ный throw, то приложение не идет на перезагруз.

и так:
ncfApp::ncfApp(int &argc, char **argv) : QGuiApplication(argc, argv) {}
bool ncfApp::notify(QObject* receiver, QEvent* event) {
    bool done = false;
    try {
        done = QGuiApplication::notify(receiver, event);
    } catch (...) {
//этот catch не срабатывает никогда
#if defined(Q_OS_ANDROID)
            QtAndroid::runOnAndroidThread([]{
                QAndroidJniObject myJavaObject("inc.garage.MainActivity");
                myJavaObject.callMethod<void>("raiseException","()V");
            });
#endif
    }

    return done;
}


И даже так:
#include <csignal>
void abortSignalHandler( int signum ) {
    qDebug() << "эта функция вызывается при краше, но рестарта нет";
    #if defined(Q_OS_ANDROID)
        QtAndroid::runOnAndroidThread([]{
            QAndroidJniObject myJavaObject("inc.garage.MainActivity");
            myJavaObject.callMethod<void>("raiseException","()V");
        });
    #endif
}
void main(...
    signal(SIGABRT, abortSignalHandler);
}


В общем уже думаю писать отдельную службу, которая следит за работой приложения. Подскажите кто как сделал, если встречались с подобным
  • Вопрос задан
  • 458 просмотров
Пригласить эксперта
Ответы на вопрос 1
gigacoder
@gigacoder
Программист для Android
Попробуйте сделать watchdog с помощью AlarmManager.

https://medium.com/@valeriachub/classic-chain-alar...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы