Compare commits
5 Commits
master
...
shareLogAn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4660ffe29 | ||
|
|
354fb15776 | ||
|
|
95e2ded5a4 | ||
|
|
ad0e346714 | ||
|
|
0629deb4b5 |
@ -1,3 +1,5 @@
|
||||
- mobile: fix profile scaling issue on high DPR devices
|
||||
- mobile/Android: add logfiles as attachment to support emails
|
||||
- planner: make ESC (cancel plan) work when moving handles
|
||||
- dive list: make dive guide visible in dive list [#3382]
|
||||
- general: rename dive master to dive guide
|
||||
|
||||
@ -77,6 +77,15 @@
|
||||
<meta-data android:name="android.max_aspect" android:value="3" />
|
||||
|
||||
</activity>
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="org.subsurfacedivelog.mobile.fileprovider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/filepaths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
<uses-sdk android:minSdkVersion="21"
|
||||
|
||||
@ -27,8 +27,9 @@ allprojects {
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.github.mik3y:usb-serial-for-android:v3.4.3'
|
||||
implementation 'com.android.support:support-v4:25.3.1'
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
4
android-mobile/res/xml/filepaths.xml
Normal file
4
android-mobile/res/xml/filepaths.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<files-path path="./" name="logfiles" />
|
||||
</paths>
|
||||
@ -20,10 +20,80 @@ import android.content.Intent;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.util.Log;
|
||||
import java.io.File;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v4.app.ShareCompat;
|
||||
import android.content.pm.PackageManager;
|
||||
import java.util.List;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
// this is the main class that will be run at start
|
||||
public class SubsurfaceMobileActivity extends QtActivity
|
||||
{
|
||||
// FileProvider declares an 'authority' in AndroidManifest.xml
|
||||
private static String fileProviderAuthority="org.subsurfacedivelog.mobile.fileprovider";
|
||||
|
||||
// you can share one file (for future use, I'm thinking divelist XML), or two files
|
||||
// which is assumed to be a support request - maybe that shouldn't be implicit?
|
||||
public boolean shareFiles(String path1, String path2) {
|
||||
// better save than sorry
|
||||
if (QtNative.activity() == null)
|
||||
return false;
|
||||
|
||||
Log.d(TAG + " shareFile - trying to share: ", path1 + " and " + path2);
|
||||
|
||||
// Can't get this to work building my own intent, so let's use the IntentBuilder
|
||||
Intent shareFileIntent = ShareCompat.IntentBuilder.from(QtNative.activity()).getIntent();
|
||||
shareFileIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
|
||||
|
||||
// now figure out the URI we need to share the first file
|
||||
File fileToShare = new File(path1);
|
||||
Uri uri;
|
||||
try {
|
||||
uri = FileProvider.getUriForFile(QtNative.activity(), fileProviderAuthority, fileToShare);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.d(TAG + " shareFile - cannot get URI for ", path1);
|
||||
return false;
|
||||
}
|
||||
Log.d(TAG + " shareFile - URI for file: ", uri.toString());
|
||||
|
||||
// because we allow up to two attachments, we use ACTION_SEND_MULTIPLE and so the attachments
|
||||
// need to be an ArrayList - even if we only add one attachment this still works
|
||||
ArrayList<Uri> attachments = new ArrayList<Uri>();
|
||||
attachments.add(uri);
|
||||
|
||||
// if there is a second file name (that's for support emails) add it and set this up as support email as well
|
||||
if (path2 != "") {
|
||||
fileToShare = new File(path2);
|
||||
try {
|
||||
uri = FileProvider.getUriForFile(QtNative.activity(), fileProviderAuthority, fileToShare);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.d(TAG + " shareFile - cannot get URI for ", path2);
|
||||
return false;
|
||||
}
|
||||
Log.d(TAG + " shareFile - URI for file: ", uri.toString());
|
||||
attachments.add(uri);
|
||||
// recipients are also always an array, even if there's only one
|
||||
shareFileIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { "in-app-support@subsurface-divelog.org" });
|
||||
shareFileIntent.putExtra(Intent.EXTRA_SUBJECT, "Subsurface-mobile support request");
|
||||
shareFileIntent.putExtra(Intent.EXTRA_TEXT, "Please describe your issue here and keep the attached logs.\n\n\n\n");
|
||||
}
|
||||
shareFileIntent.setType("text/plain");
|
||||
shareFileIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);
|
||||
shareFileIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
shareFileIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
Log.d(TAG + " sendFile ", " create activity for the Intent");
|
||||
// this actually allows sharing with any app that will take "text/plain" files, including Dropbox, etc
|
||||
// in order for the recipient / subject to work, the user needs to be clever enough to share with an email app
|
||||
QtNative.activity().startActivity(shareFileIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isIntentPending;
|
||||
public static boolean isInitialized;
|
||||
private static final String TAG = "subsurfacedivelog.mobile";
|
||||
|
||||
@ -48,7 +48,8 @@ bool subsurface_ignore_font(const char *font)
|
||||
static const char *system_default_path_append(const char *append)
|
||||
{
|
||||
// Qt appears to find a working path for us - let's just go with that
|
||||
QString path = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
|
||||
// AppDataLocation allows potential sharing of the files we put there
|
||||
QString path = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first();
|
||||
|
||||
if (append)
|
||||
path += QString("/%1").arg(append);
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "commands/command.h"
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
#include <QtAndroid>
|
||||
#include "core/serial_usb_android.h"
|
||||
std::vector<android_usb_serial_device_descriptor> androidSerialDevices;
|
||||
|
||||
@ -230,9 +231,11 @@ QMLManager::QMLManager() :
|
||||
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
|
||||
#if defined(Q_OS_ANDROID)
|
||||
// on Android we first try the GenericDataLocation (typically /storage/emulated/0) and if that fails
|
||||
// (as happened e.g. on a Sony Xperia phone) we try several other default locations, with the TempLocation as last resort
|
||||
// on Android we first try the AppDataLocation (which allows sharing of files), then the
|
||||
// GenericDataLocation (typically /storage/emulated/0), and if that fails (as happened e.g. on a
|
||||
// Sony Xperia phone) we try several other default locations, with the TempLocation as last resort
|
||||
QStringList fileLocations =
|
||||
QStandardPaths::standardLocations(QStandardPaths::AppDataLocation) +
|
||||
QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation) +
|
||||
QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation) +
|
||||
QStandardPaths::standardLocations(QStandardPaths::DownloadLocation) +
|
||||
@ -260,7 +263,8 @@ QMLManager::QMLManager() :
|
||||
appendTextToLog("Successfully opened logfile " + appLogFileName
|
||||
+ " at " + QDateTime::currentDateTime().toString());
|
||||
// if we were able to write the overall logfile, also write the libdivecomputer logfile
|
||||
QString libdcLogFileName = appLogFileName.replace("/subsurface.log", "/libdivecomputer.log");
|
||||
QString libdcLogFileName = appLogFileName;
|
||||
libdcLogFileName = libdcLogFileName.replace("/subsurface.log", "/libdivecomputer.log");
|
||||
// remove the existing libdivecomputer logfile so we don't copy an old one by mistake
|
||||
QFile libdcLog(libdcLogFileName);
|
||||
libdcLog.remove();
|
||||
@ -488,8 +492,25 @@ void QMLManager::copyAppLogToClipboard()
|
||||
|
||||
bool QMLManager::createSupportEmail()
|
||||
{
|
||||
QString messageBody = "Please describe your issue here and keep the logs below:\n\n\n\n";
|
||||
#if defined(Q_OS_ANDROID)
|
||||
// let's use our nifty Java shareFile function
|
||||
QAndroidJniObject activity = QtAndroid::androidActivity();
|
||||
if (activity.isValid()) {
|
||||
QAndroidJniObject applogfilepath = QAndroidJniObject::fromString(appLogFileName);
|
||||
QAndroidJniObject libdcfilepath = QAndroidJniObject::fromString(logfile_name);
|
||||
bool success = activity.callMethod<jboolean>("shareFiles",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)Z", // two string arguments, return bool
|
||||
applogfilepath.object<jstring>(), libdcfilepath.object<jstring>());
|
||||
qDebug() << __FUNCTION__ << "shareFiles" << (success ? "succeeded" : "failed");
|
||||
if (success)
|
||||
return true;
|
||||
}
|
||||
qDebug() << __FUNCTION__ << "failed to share the logFiles via intent, use the fall-back mail body method";
|
||||
#endif
|
||||
QString mailToLink = "mailto:in-app-support@subsurface-divelog.org?subject=Subsurface-mobile support request";
|
||||
mailToLink += "&body=Please describe your issue here and keep the logs below:\n\n\n\n";
|
||||
mailToLink += "&body=";
|
||||
mailToLink += messageBody;
|
||||
mailToLink += getCombinedLogs();
|
||||
if (QDesktopServices::openUrl(QUrl(mailToLink))) {
|
||||
appendTextToLog("OS accepted support email");
|
||||
@ -1826,8 +1847,6 @@ void QMLManager::writeToAppLogFile(QString logText)
|
||||
//HACK to color the system bar on Android, use qtandroidextras and call the appropriate Java methods
|
||||
//this code is based on code in the Kirigami example app for Android (under LGPL-2) Copyright 2017 Marco Martin
|
||||
|
||||
#include <QtAndroid>
|
||||
|
||||
// there doesn't appear to be an include that defines these in an easily accessible way
|
||||
// WindowManager.LayoutParams
|
||||
#define FLAG_TRANSLUCENT_STATUS 0x04000000
|
||||
|
||||
@ -51,7 +51,10 @@ void QMLProfile::paint(QPainter *painter)
|
||||
timer.start();
|
||||
|
||||
// let's look at the intended size of the content and scale our scene accordingly
|
||||
// for some odd reason the painter transformation is set up to scale by the dpr - which results
|
||||
// in applying that dpr scaling twice. So we hard-code it here to be the identity matrix
|
||||
QRect painterRect = painter->viewport();
|
||||
painter->resetTransform();
|
||||
if (m_diveId < 0)
|
||||
return;
|
||||
struct dive *d = get_dive_by_uniq_id(m_diveId);
|
||||
|
||||
@ -221,7 +221,8 @@ echo Building from "$SRC", installing in "$INSTALL_ROOT"
|
||||
# find qmake
|
||||
if [ -n "$CMAKE_PREFIX_PATH" ] ; then
|
||||
QMAKE=$CMAKE_PREFIX_PATH/../../bin/qmake
|
||||
else
|
||||
fi
|
||||
if [[ -z $QMAKE || ! -x $QMAKE ]] ; then
|
||||
hash qmake > /dev/null 2> /dev/null && QMAKE=qmake
|
||||
[ -z $QMAKE ] && hash qmake-qt5 > /dev/null 2> /dev/null && QMAKE=qmake-qt5
|
||||
[ -z $QMAKE ] && echo "cannot find qmake or qmake-qt5" && exit 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user