2017-07-03 09:33:28 +02:00
|
|
|
/*!
|
2018-03-28 15:10:51 +02:00
|
|
|
* \copyright Copyright (c) 2016-2018 Governikus GmbH & Co. KG, Germany
|
2017-07-03 09:33:28 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "QmlExtension.h"
|
|
|
|
|
|
|
|
#include "LogHandler.h"
|
|
|
|
|
|
|
|
#include <QAndroidJniEnvironment>
|
|
|
|
#include <QAndroidJniObject>
|
|
|
|
#include <QCoreApplication>
|
|
|
|
#include <QDateTime>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QLoggingCategory>
|
|
|
|
#include <QStandardPaths>
|
|
|
|
#include <QtAndroid>
|
|
|
|
|
|
|
|
Q_DECLARE_LOGGING_CATEGORY(qml)
|
|
|
|
|
|
|
|
|
|
|
|
using namespace governikus;
|
|
|
|
|
|
|
|
void QmlExtension::showSettings(const QString& pAction)
|
|
|
|
{
|
|
|
|
QAndroidJniEnvironment env;
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
const QAndroidJniObject& jAction = QAndroidJniObject::fromString(pAction);
|
2017-07-03 09:33:28 +02:00
|
|
|
QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", jAction.object<jstring>());
|
2017-12-20 14:54:05 +01:00
|
|
|
const jint flag = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_ACTIVITY_NEW_TASK");
|
2017-07-03 09:33:28 +02:00
|
|
|
intent.callObjectMethod("setFlags", "(I)V", flag);
|
|
|
|
|
|
|
|
if (intent.isValid())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Call action:" << pAction;
|
|
|
|
QtAndroid::startActivity(intent, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Cannot call an action as activity:" << pAction;
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QmlExtension::shareText(const QString& pText, const QString& pChooserTitle)
|
|
|
|
{
|
|
|
|
QAndroidJniEnvironment env;
|
2017-12-20 14:54:05 +01:00
|
|
|
const QAndroidJniObject javaActivity(QtAndroid::androidActivity());
|
|
|
|
if (!javaActivity.isValid())
|
2017-07-03 09:33:28 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
qCCritical(qml) << "Cannot determine android activity.";
|
2017-07-03 09:33:28 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
const QAndroidJniObject& jText = QAndroidJniObject::fromString(pText);
|
|
|
|
const QAndroidJniObject& jTitle = QAndroidJniObject::fromString(pChooserTitle);
|
2017-07-03 09:33:28 +02:00
|
|
|
QAndroidJniObject::callStaticMethod<void>("com/governikus/ausweisapp2/ShareUtil",
|
|
|
|
"shareText",
|
|
|
|
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V",
|
|
|
|
javaActivity.object<jobject>(),
|
|
|
|
jText.object<jstring>(),
|
|
|
|
jTitle.object<jstring>());
|
|
|
|
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Cannot call ShareUtil.shareText()";
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QmlExtension::showFeedback(const QString& pMessage)
|
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
// Wait for toast activation synchronously so that the app can not be deactivated
|
|
|
|
// in the meantime and all used Java objects are still alive when accessed.
|
|
|
|
QtAndroid::runOnAndroidThreadSync([pMessage](){
|
|
|
|
QAndroidJniEnvironment env;
|
|
|
|
|
|
|
|
const QAndroidJniObject& jMessage = QAndroidJniObject::fromString(pMessage);
|
|
|
|
const QAndroidJniObject& toast = QAndroidJniObject::callStaticObjectMethod(
|
2017-07-03 09:33:28 +02:00
|
|
|
"android/widget/Toast",
|
|
|
|
"makeText",
|
|
|
|
"(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;",
|
2017-12-20 14:54:05 +01:00
|
|
|
QtAndroid::androidActivity().object(),
|
|
|
|
jMessage.object(),
|
2017-07-03 09:33:28 +02:00
|
|
|
jint(1));
|
|
|
|
toast.callMethod<void>("show");
|
2017-12-20 14:54:05 +01:00
|
|
|
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Suppressing an unexpected exception.";
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
// The toast was probably not displayed (e.g. DeadObjectException). We halt on error
|
|
|
|
// since it is used to display information to the user as required by the TR.
|
|
|
|
Q_ASSERT(false);
|
|
|
|
}
|
2017-07-03 09:33:28 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calling
|
|
|
|
* QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).last()
|
|
|
|
* does the same but we don't want to rely on Qt internals, so we do it on our own.
|
|
|
|
*/
|
|
|
|
QString getPublicLogFileName(QAndroidJniEnvironment& env, const QAndroidJniObject& javaActivity)
|
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
const auto& jEmptyString = QAndroidJniObject::fromString(QLatin1String(""));
|
2017-07-03 09:33:28 +02:00
|
|
|
const auto& jExternalFilesDir = javaActivity.callObjectMethod("getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;", jEmptyString.object<jstring>());
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Exception determining externalFilesDir";
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
return QString();
|
|
|
|
}
|
2017-12-20 14:54:05 +01:00
|
|
|
if (!jExternalFilesDir.isValid())
|
2017-07-03 09:33:28 +02:00
|
|
|
{
|
|
|
|
qCCritical(qml) << "Cannot determine externalFilesDir";
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto& jExternalFilesDirPath = jExternalFilesDir.callObjectMethod("getAbsolutePath", "()Ljava/lang/String;");
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Exception determining externalFilesDir absolute path";
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
return QString();
|
|
|
|
}
|
2017-12-20 14:54:05 +01:00
|
|
|
if (!jExternalFilesDirPath.isValid())
|
2017-07-03 09:33:28 +02:00
|
|
|
{
|
|
|
|
qCCritical(qml) << "Cannot determine externalFilesDir absolute path";
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
const auto& nowAsISO = QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd'T'HH:mm:ss-t"));
|
2017-07-03 09:33:28 +02:00
|
|
|
return QStringLiteral("%1/AusweisApp2-%2.log").arg(jExternalFilesDirPath.toString(), nowAsISO);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QmlExtension::mailLog(const QString& pEmail, const QString& pSubject, const QString& pMsg)
|
|
|
|
{
|
|
|
|
QAndroidJniEnvironment env;
|
2017-12-20 14:54:05 +01:00
|
|
|
const QAndroidJniObject javaActivity(QtAndroid::androidActivity());
|
|
|
|
if (!javaActivity.isValid())
|
2017-07-03 09:33:28 +02:00
|
|
|
{
|
|
|
|
qCCritical(qml) << "Cannot determine android activity";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto& jEmail = QAndroidJniObject::fromString(pEmail);
|
|
|
|
const auto& jSubject = QAndroidJniObject::fromString(pSubject);
|
|
|
|
const auto& jMsg = QAndroidJniObject::fromString(pMsg);
|
|
|
|
const auto& jChooserTitle = QAndroidJniObject::fromString(tr("Send application log per email..."));
|
|
|
|
const auto& publicLogFile = getPublicLogFileName(env, javaActivity);
|
|
|
|
const auto& jPublicLogFile = QAndroidJniObject::fromString(publicLogFile);
|
|
|
|
|
|
|
|
qCDebug(qml) << "Copy log file to" << publicLogFile;
|
|
|
|
if (!LogHandler::getInstance().copy(publicLogFile))
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Cannot copy log file to" << publicLogFile;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QAndroidJniObject::callStaticMethod<void>("com/governikus/ausweisapp2/ShareUtil",
|
|
|
|
"shareLog",
|
|
|
|
"(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
|
|
|
javaActivity.object<jobject>(),
|
|
|
|
jEmail.object<jstring>(),
|
|
|
|
jSubject.object<jstring>(),
|
|
|
|
jMsg.object<jstring>(),
|
|
|
|
jPublicLogFile.object<jstring>(),
|
|
|
|
jChooserTitle.object<jstring>());
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Exception calling ShareUtil.shareLog()";
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool QmlExtension::exportHistory(const QString&) const
|
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
qCWarning(qml) << "NOT IMPLEMENTED";
|
2017-07-03 09:33:28 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
void QmlExtension::keepScreenOn(bool pActive)
|
|
|
|
{
|
|
|
|
QtAndroid::runOnAndroidThread([pActive](){
|
|
|
|
QtAndroid::androidActivity().callMethod<void>("keepScreenOn", "(Z)V", pActive);
|
|
|
|
QAndroidJniEnvironment env;
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
{
|
|
|
|
qCCritical(qml) << "Exception calling java native function.";
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
env->ExceptionClear();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-03 09:33:28 +02:00
|
|
|
#include "moc_QmlExtension.cpp"
|