Browse Source

Allow app data to save to sd card on android

QGC4.4
Don Gagne 2 years ago committed by Don Gagne
parent
commit
fa9bf8a00f
  1. 9
      android.pri
  2. 21
      android/src/AndroidInterface.cc
  3. 21
      android/src/AndroidInterface.h
  4. 32
      android/src/org/mavlink/qgroundcontrol/QGCActivity.java
  5. 10
      src/Settings/App.SettingsGroup.json
  6. 27
      src/Settings/AppSettings.cc
  7. 1
      src/Settings/AppSettings.h
  8. 7
      src/api/QGCCorePlugin.cc
  9. 9
      src/ui/preferences/GeneralSettings.qml

9
android.pri

@ -53,3 +53,12 @@ DISTFILES += \ @@ -53,3 +53,12 @@ DISTFILES += \
$$PWD/android/build.gradle \
$$PWD/android/gradle/wrapper/gradle-wrapper.properties \
$$PWD/android/gradlew.bat
SOURCES += \
$$PWD/android/src/AndroidInterface.cc
HEADERS += \
$$PWD/android/src/AndroidInterface.h
INCLUDEPATH += \
$$PWD/android/src

21
android/src/AndroidInterface.cc

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
/****************************************************************************
*
* Copyright (C) 2018 Pinecone Inc. All rights reserved.
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include <QtAndroidExtras/QtAndroidExtras>
#include <QtAndroidExtras/QAndroidJniObject>
#include "QGCApplication.h"
#include "AndroidInterface.h"
#include <QAndroidJniObject>
QString AndroidInterface::getSDCardPath()
{
QAndroidJniObject value = QAndroidJniObject::callStaticObjectMethod("org/mavlink/qgroundcontrol/QGCActivity", "getSDCardPath",
"()Ljava/lang/String;");
return value.toString();
}

21
android/src/AndroidInterface.h

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
/****************************************************************************
*
* Copyright (C) 2018 Pinecone Inc. All rights reserved.
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include <QObject>
#include <jni.h>
#include <QtCore/private/qjni_p.h>
#include <QtCore/private/qjnihelpers_p.h>
class AndroidInterface
{
public:
static QString getSDCardPath();
};

32
android/src/org/mavlink/qgroundcontrol/QGCActivity.java

@ -38,6 +38,7 @@ import java.util.concurrent.Executors; @@ -38,6 +38,7 @@ import java.util.concurrent.Executors;
import java.util.Timer;
import java.util.TimerTask;
import java.io.IOException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.app.PendingIntent;
@ -58,6 +59,8 @@ import android.app.PendingIntent; @@ -58,6 +59,8 @@ import android.app.PendingIntent;
import android.view.WindowManager;
import android.os.Bundle;
import android.bluetooth.BluetoothDevice;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import com.hoho.android.usbserial.driver.*;
import org.qtproject.qt5.android.bindings.QtActivity;
@ -762,5 +765,34 @@ public class QGCActivity extends QtActivity @@ -762,5 +765,34 @@ public class QGCActivity extends QtActivity
}
}).start();
}
public static String getSDCardPath() {
StorageManager storageManager = (StorageManager)_instance.getSystemService(Activity.STORAGE_SERVICE);
List<StorageVolume> volumes = storageManager.getStorageVolumes();
Method mMethodGetPath;
String path = "";
for (StorageVolume vol : volumes) {
try {
mMethodGetPath = vol.getClass().getMethod("getPath");
} catch (NoSuchMethodException e) {
e.printStackTrace();
continue;
}
try {
path = (String) mMethodGetPath.invoke(vol);
} catch (Exception e) {
e.printStackTrace();
continue;
}
if (vol.isRemovable() == true) {
Log.i(TAG, "removable sd card mounted " + path);
return path;
} else {
Log.i(TAG, "storage mounted " + path);
}
}
return "";
}
}

10
src/Settings/App.SettingsGroup.json

@ -174,11 +174,19 @@ @@ -174,11 +174,19 @@
{
"name": "savePath",
"shortDesc": "Application save directory",
"longDesc": "Directory to which all data files are saved/loaded from",
"longDesc": "Directory to which all data files are saved/loaded from",
"type": "string",
"default": ""
},
{
"name": "androidSaveToSDCard",
"shortDesc": "Save to SD card",
"longDesc": "Application data is saved to the sd card",
"type": "bool",
"default": false,
"qgcRebootRequired": true
},
{
"name": "userBrandImageIndoor",
"shortDesc": "User-selected brand image",
"longDesc": "Location in file system of user-selected brand image (indoor)",

27
src/Settings/AppSettings.cc

@ -12,6 +12,10 @@ @@ -12,6 +12,10 @@
#include "QGCApplication.h"
#include "ParameterManager.h"
#ifdef __android__
#include "AndroidInterface.h"
#endif
#include <QQmlEngine>
#include <QtQml>
#include <QStandardPaths>
@ -95,10 +99,26 @@ DECLARE_SETTINGGROUP(App, "") @@ -95,10 +99,26 @@ DECLARE_SETTINGGROUP(App, "")
QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
savePathFact->setRawValue(rootDir.absolutePath());
#else
QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
savePathFact->setRawValue(rootDir.filePath(appName));
QString rootDirPath;
#ifdef __android__
if (androidSaveToSDCard()->rawValue().toBool()) {
rootDirPath = AndroidInterface::getSDCardPath();
qDebug() << "AndroidInterface::getSDCardPath();" << rootDirPath;
if (rootDirPath.isEmpty() || !QDir(rootDirPath).exists()) {
rootDirPath.clear();
qgcApp()->showAppMessage(tr("Save to SD card specified for application data. But no SD card present. Using internal storage."));
} else if (!QFileInfo(rootDirPath).isWritable()) {
rootDirPath.clear();
qgcApp()->showAppMessage(tr("Save to SD card specified for application data. But SD card is write protected. Using internal storage."));
}
}
#endif
if (rootDirPath.isEmpty()) {
rootDirPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
}
savePathFact->setRawValue(QDir(rootDirPath).filePath(appName));
#endif
savePathFact->setVisible(false);
savePathFact->setVisible(false);
#else
QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
savePathFact->setRawValue(rootDir.filePath(appName));
@ -128,6 +148,7 @@ DECLARE_SETTINGSFACT(AppSettings, virtualJoystickAutoCenterThrottle) @@ -128,6 +148,7 @@ DECLARE_SETTINGSFACT(AppSettings, virtualJoystickAutoCenterThrottle)
DECLARE_SETTINGSFACT(AppSettings, appFontPointSize)
DECLARE_SETTINGSFACT(AppSettings, showLargeCompass)
DECLARE_SETTINGSFACT(AppSettings, savePath)
DECLARE_SETTINGSFACT(AppSettings, androidSaveToSDCard)
DECLARE_SETTINGSFACT(AppSettings, useChecklist)
DECLARE_SETTINGSFACT(AppSettings, enforceChecklist)
DECLARE_SETTINGSFACT(AppSettings, mapboxToken)

1
src/Settings/AppSettings.h

@ -44,6 +44,7 @@ public: @@ -44,6 +44,7 @@ public:
DEFINE_SETTINGFACT(indoorPalette)
DEFINE_SETTINGFACT(showLargeCompass)
DEFINE_SETTINGFACT(savePath)
DEFINE_SETTINGFACT(androidSaveToSDCard)
DEFINE_SETTINGFACT(useChecklist)
DEFINE_SETTINGFACT(enforceChecklist)
DEFINE_SETTINGFACT(mapboxToken)

7
src/api/QGCCorePlugin.cc

@ -248,6 +248,13 @@ bool QGCCorePlugin::adjustSettingMetaData(const QString& settingsGroup, FactMeta @@ -248,6 +248,13 @@ bool QGCCorePlugin::adjustSettingMetaData(const QString& settingsGroup, FactMeta
return true;
}
#endif
#ifndef __android__
if (metaData.name() == AppSettings::androidSaveToSDCardName) {
// This only shows on android builds
return false;
}
#endif
}
return true; // Show setting in ui

9
src/ui/preferences/GeneralSettings.qml

@ -686,6 +686,13 @@ Rectangle { @@ -686,6 +686,13 @@ Rectangle {
}
FactCheckBox {
text: qsTr("Save application data to SD Card")
fact: _androidSaveToSDCard
visible: _androidSaveToSDCard.visible
property Fact _androidSaveToSDCard: QGroundControl.settingsManager.appSettings.androidSaveToSDCard
}
FactCheckBox {
text: qsTr("Check for Internet connection")
fact: _checkInternet
visible: _checkInternet && _checkInternet.visible
@ -727,8 +734,6 @@ Rectangle { @@ -727,8 +734,6 @@ Rectangle {
}
}
//-----------------------------------------------------------------
//-- Save path
RowLayout {
id: pathRow
anchors.margins: _margins

Loading…
Cancel
Save