A
A
Anton Misyagin2020-05-06 01:10:30
Android
Anton Misyagin, 2020-05-06 01:10:30

How to restart the application in case of any crash?

The application is developed using QT 5.9. Launched in kiosk mode, the user cannot turn it off. The task was to ensure the survivability of the application if it crashes for any reason. I dug up such a reload of the application on the Internet and it even works a little bit:
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

This code calls the raiseException java method and as a result the application crashes successfully and reloads in a second.

Now the most interesting. How to handle any application crash?
An elementary throw called from c++ code kills the application and does not restart.
I also tried this:
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;
}

But, if the cpp-th throw button is not called from the qml part in the click handler, then the application does not go to reboot.

so:
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;
}


And even like this:
#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);
}


In general, I'm already thinking of writing a separate service that monitors the operation of the application. Tell me who did it, if you met with a similar

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
Roman Vasilenko, 2020-05-14
@gigacoder

Try making a watchdog using the AlarmManager.
https://medium.com/@valeriachub/classic-chain-alar...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question