Commit 25860484 authored by Karel Slaný's avatar Karel Slaný

Merge branch 'android-email' into 'develop'

Allow to send email with attachments on Android

Closes #138

See merge request !144
parents c771929e 9b271b90
......@@ -25,6 +25,9 @@
#include <QtAndroidExtras>
#include <QDesktopServices>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QUrl>
#include "android/src/android_io.h"
......@@ -44,7 +47,6 @@ bool AndroidIO::isSDKVersion24OrNewest(void)
bool AndroidIO::openFile(const QString &filePath)
{
/*
* TODO - must be tested and reimplement.
* Use file provider only because SDK detection fails.
......@@ -68,8 +70,29 @@ bool AndroidIO::openWithFileProvider(const QString &filePath)
QAndroidJniObject jsPath = QAndroidJniObject::fromString(filePath);
jboolean ok = QAndroidJniObject::callStaticMethod<jboolean>(
"cz/nic/mobiledatovka/java/QFileProvider",
"viewFile", "(Ljava/lang/String;I)Z",
jsPath.object<jstring>(), 0);
"viewFile", "(Ljava/lang/String;)Z",
jsPath.object<jstring>());
return (ok);
}
bool AndroidIO::createEmail(const QString &subject, const QString &to,
const QString &body, const QStringList &filePaths)
{
QAndroidJniObject jsSubject = QAndroidJniObject::fromString(subject);
QAndroidJniObject jsTo = QAndroidJniObject::fromString(to);
QAndroidJniObject jsBody = QAndroidJniObject::fromString(body);
QJsonArray arr = QJsonArray::fromStringList(filePaths);
QJsonObject jsonObj;
jsonObj[QLatin1String("attachments")] = arr;
QJsonDocument doc(jsonObj);
QAndroidJniObject jsJsonPathList = QAndroidJniObject::fromString(doc.toJson(QJsonDocument::Compact));
jboolean ok = QAndroidJniObject::callStaticMethod<jboolean>(
"cz/nic/mobiledatovka/java/QFileProvider",
"sendEmail", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
jsSubject.object<jstring>(), jsTo.object<jstring>(),
jsBody.object<jstring>(), jsJsonPathList.object<jstring>());
return (ok);
}
......@@ -59,6 +59,19 @@ public:
static
bool openFile(const QString &filePath);
/*!
* @brief Create email.
*
* @param[in] subject Email subject.
* @param[in] to Email recipient.
* @param[in] body Email body text.
* @param[in] filePaths Attachments paths.
* @return True if success.
*/
static
bool createEmail(const QString &subject, const QString &to,
const QString &body, const QStringList &filePaths);
private:
/*!
......
......@@ -53,6 +53,8 @@ import android.os.Build;
import android.support.v4.content.FileProvider;
import android.support.v4.app.ShareCompat;
import org.json.*;
public class QFileProvider
{
// Authority defined in AndroidManifest.xml
......@@ -128,7 +130,7 @@ public class QFileProvider
return false;
}
public static boolean viewFile(String filePath, int id) {
public static boolean viewFile(String filePath) {
if (QtNative.activity() == null) {
return false;
......@@ -160,4 +162,62 @@ public class QFileProvider
return startActivity(viewIntent, uri);
}
public static boolean sendEmail(String subject, String to, String body, String filePathsJson) {
if (QtNative.activity() == null) {
return false;
}
ArrayList<Uri> uris = new ArrayList<Uri>();
try {
JSONObject jsonObj = new JSONObject(filePathsJson);
JSONArray attachments = jsonObj.getJSONArray("attachments");
for (int i=0; i<attachments.length(); i++) {
File attachment = new File(attachments.getString(i));
if (!attachment.exists() || !attachment.canRead()) {
System.out.println("FileProvider: Cannot read file " + attachment);
return false;
}
Uri uri;
try {
uri = FileProvider.getUriForFile(QtNative.activity(), AUTHORITY, attachment);
uris.add(uri);
} catch (IllegalArgumentException ex) {
System.out.println("FileProvider: " + ex.getMessage());
return false;
}
}
} catch (JSONException ex) {
System.out.println("JSONException: " + ex.getMessage());
return false;
}
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
emailIntent.setType("plain/text");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {to});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
try {
Intent i = Intent.createChooser(emailIntent, "Send mail...");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
QtNative.activity().startActivity(i);
} catch (android.content.ActivityNotFoundException ex) {
System.out.println("There are no email clients installed.");
return false;
} catch (java.lang.RuntimeException ex) {
System.out.println("RuntimeException: " + ex.getMessage());
return false;
} catch (java.lang.Exception ex) {
System.out.println("Exception: " + ex.getMessage());
return false;
}
System.out.println("Email has created.");
return true;
}
}
......@@ -28,6 +28,9 @@
#include <QObject>
#include <QUrl>
#if defined (Q_OS_ANDROID)
#include "android/src/android_io.h"
#endif
#include "ios/src/url_opener.h"
#include "src/auxiliaries/email_helper.h"
#include "src/io/filesystem.h"
......@@ -132,8 +135,12 @@ void sendEmail(const QString &emailMessage, const QStringList &fileList,
#elif defined Q_OS_ANDROID
QDesktopServices::openUrl(QUrl("mailto:" + to + "?"
+ "subject=" + subject + "&body=" + body));
AndroidIO::createEmail(subject, to, body, fileList);
// Old send message method for android.
// It creates email without attachments.
//QDesktopServices::openUrl(QUrl("mailto:" + to + "?"
// + "subject=" + subject + "&body=" + body));
#else
......
......@@ -200,22 +200,7 @@ void Files::openAttachment(const QString &fileName,
QString docLocationRoot = appTmpDirPath();
#if defined (Q_OS_ANDROID)
docLocationRoot = QStandardPaths::standardLocations(
QStandardPaths::AppDataLocation).value(0);
QString documentsWorkPath = docLocationRoot.append("/share_example_x_files");
if (!QDir(documentsWorkPath).exists()) {
if (!QDir("").mkpath(documentsWorkPath)) {
logErrorNL("Failed to create share directory: '%s'.",
documentsWorkPath.toUtf8().constData());
Dialogues::errorMessage(Dialogues::CRITICAL,
tr("Open attachment error"),
tr("Cannot save selected file to disk for opening."),
QString());
return;
}
}
docLocationRoot = getAndroidFileProviderBasePath();
#endif
QString filePath(writeFile(docLocationRoot, fileName, binaryData));
......@@ -358,6 +343,10 @@ void Files::sendMsgFilesWithEmail(const QString &userName, qint64 msgId,
boundary);
QStringList filePathList;
#if defined (Q_OS_ANDROID)
targetPath = getAndroidFileProviderBasePath();
#endif
/* Write attachment files to email directory */
foreach (const Isds::Document &document, documents) {
QString fileName = document.fileDescr();
......@@ -604,6 +593,10 @@ void Files::sendAttachmentEmailZfo(const QVariant &attachModelVariant,
removeDirFromDocLoc(DATOVKA_MAIL_DIR_NAME);
QString targetPath(appEmailDirPath(msgIdStr));
#if defined (Q_OS_ANDROID)
targetPath = getAndroidFileProviderBasePath();
#endif
for (int row = 0; row < attachModel->rowCount(); ++row) {
QModelIndex idx(attachModel->index(row));
/*
......
......@@ -272,3 +272,24 @@ QString constructLogFileName(void) {
+ ".log");
return appLogDirPath() + QDir::separator() + logFileName;
}
QString getAndroidFileProviderBasePath(void) {
QString basePath = QStandardPaths::standardLocations(
QStandardPaths::AppDataLocation).value(0);
QString fileProviderDir = basePath.append("/share_example_x_files");
QDir dir(fileProviderDir);
dir.removeRecursively();
if (!QDir(fileProviderDir).exists()) {
if (!QDir("").mkpath(fileProviderDir)) {
logErrorNL("Failed to create share directory: '%s'.",
fileProviderDir.toUtf8().constData());
return QString();
}
}
return basePath;
}
......@@ -190,3 +190,10 @@ void deleteOldestLogFile(void);
* @return Full path including log file name.
*/
QString constructLogFileName(void);
/*!
* @brief Return Android file provider base path.
*
* @return Android file provider base path.
*/
QString getAndroidFileProviderBasePath(void);
......@@ -104,6 +104,11 @@ void Log::sendLogViaEmail(const QString &logContent)
removeDirFromDocLoc(DATOVKA_MAIL_DIR_NAME);
QString targetPath(appEmailDirPath("Log"));
#if defined (Q_OS_ANDROID)
targetPath = getAndroidFileProviderBasePath();
#endif
QString filePath(writeFile(targetPath, "mobile-datovka.log",
logContent.toUtf8()));
QStringList attachmentList;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment