mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-23 22:37:55 +02:00
[android][launcher] copy existing oh3 files using Java
This commit is contained in:
@@ -157,4 +157,5 @@ def LoadSigningConfig(final signingConfigKey) {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: '../libs', include: ['*.jar', '*.aar'])
|
implementation fileTree(dir: '../libs', include: ['*.jar', '*.aar'])
|
||||||
implementation 'androidx.annotation:annotation:1.7.1'
|
implementation 'androidx.annotation:annotation:1.7.1'
|
||||||
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
package eu.vcmi.vcmi;
|
package eu.vcmi.vcmi;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.DocumentsContract;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import eu.vcmi.vcmi.VcmiSDLActivity;
|
import eu.vcmi.vcmi.VcmiSDLActivity;
|
||||||
|
import eu.vcmi.vcmi.util.FileUtil;
|
||||||
|
|
||||||
import org.libsdl.app.SDL;
|
import org.libsdl.app.SDL;
|
||||||
|
|
||||||
@@ -13,6 +21,8 @@ import org.libsdl.app.SDL;
|
|||||||
*/
|
*/
|
||||||
public class ActivityLauncher extends org.qtproject.qt5.android.bindings.QtActivity
|
public class ActivityLauncher extends org.qtproject.qt5.android.bindings.QtActivity
|
||||||
{
|
{
|
||||||
|
private static final int PICK_EXTERNAL_VCMI_DATA_TO_COPY = 1;
|
||||||
|
|
||||||
public boolean justLaunched = true;
|
public boolean justLaunched = true;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -23,6 +33,28 @@ public class ActivityLauncher extends org.qtproject.qt5.android.bindings.QtActiv
|
|||||||
SDL.setContext(this);
|
SDL.setContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent resultData)
|
||||||
|
{
|
||||||
|
if (requestCode == PICK_EXTERNAL_VCMI_DATA_TO_COPY && resultCode == Activity.RESULT_OK)
|
||||||
|
{
|
||||||
|
if (resultData != null && FileUtil.copyData(resultData.getData(), this))
|
||||||
|
NativeMethods.heroesDataUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onActivityResult(requestCode, resultCode, resultData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyHeroesData()
|
||||||
|
{
|
||||||
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||||
|
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,
|
||||||
|
Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "vcmi-data"))
|
||||||
|
);
|
||||||
|
startActivityForResult(intent, PICK_EXTERNAL_VCMI_DATA_TO_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
public void onLaunchGameBtnPressed()
|
public void onLaunchGameBtnPressed()
|
||||||
{
|
{
|
||||||
startActivity(new Intent(ActivityLauncher.this, VcmiSDLActivity.class));
|
startActivity(new Intent(ActivityLauncher.this, VcmiSDLActivity.class));
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import android.os.Build;
|
|||||||
public class Const
|
public class Const
|
||||||
{
|
{
|
||||||
public static final String JNI_METHOD_SUPPRESS = "unused"; // jni methods are marked as unused, because IDE doesn't understand jni calls
|
public static final String JNI_METHOD_SUPPRESS = "unused"; // jni methods are marked as unused, because IDE doesn't understand jni calls
|
||||||
// used to disable lint errors about try-with-resources being unsupported on api <19 (it is supported, because retrolambda backports it)
|
|
||||||
public static final int SUPPRESS_TRY_WITH_RESOURCES_WARNING = Build.VERSION_CODES.KITKAT;
|
|
||||||
|
|
||||||
public static final String VCMI_DATA_ROOT_FOLDER_NAME = "vcmi-data";
|
public static final String VCMI_DATA_ROOT_FOLDER_NAME = "vcmi-data";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class NativeMethods
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static native void initClassloader();
|
public static native void initClassloader();
|
||||||
|
public static native void heroesDataUpdate();
|
||||||
public static native boolean tryToSaveTheGame();
|
public static native boolean tryToSaveTheGame();
|
||||||
|
|
||||||
public static void setupMsg(final Messenger msg)
|
public static void setupMsg(final Messenger msg)
|
||||||
|
|||||||
107
android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/FileUtil.java
Normal file
107
android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/FileUtil.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package eu.vcmi.vcmi.util;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.vcmi.vcmi.Storage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author F
|
||||||
|
*/
|
||||||
|
public class FileUtil
|
||||||
|
{
|
||||||
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
|
public static boolean copyData(Uri folderToCopy, Activity activity)
|
||||||
|
{
|
||||||
|
File targetDir = Storage.getVcmiDataDir(activity);
|
||||||
|
DocumentFile sourceDir = DocumentFile.fromTreeUri(activity, folderToCopy);
|
||||||
|
return copyDirectory(targetDir, sourceDir, List.of("Data", "Maps", "Mp3"), activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean copyDirectory(File targetDir, DocumentFile sourceDir, @Nullable List<String> allowed, Activity activity)
|
||||||
|
{
|
||||||
|
if (!targetDir.exists())
|
||||||
|
{
|
||||||
|
targetDir.mkdir();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DocumentFile child : sourceDir.listFiles())
|
||||||
|
{
|
||||||
|
if (allowed != null)
|
||||||
|
{
|
||||||
|
boolean fileAllowed = false;
|
||||||
|
|
||||||
|
for (String str : allowed)
|
||||||
|
{
|
||||||
|
if (str.equalsIgnoreCase(child.getName()))
|
||||||
|
{
|
||||||
|
fileAllowed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileAllowed)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
File exported = new File(targetDir, child.getName());
|
||||||
|
|
||||||
|
if (child.isFile())
|
||||||
|
{
|
||||||
|
if (!exported.exists())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
exported.createNewFile();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Log.e(activity, "createNewFile failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (
|
||||||
|
final OutputStream targetStream = new FileOutputStream(exported, false);
|
||||||
|
final InputStream sourceStream = activity.getContentResolver()
|
||||||
|
.openInputStream(child.getUri()))
|
||||||
|
{
|
||||||
|
copyStream(sourceStream, targetStream);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Log.e(activity, "copyStream failed: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.isDirectory() && !copyDirectory(exported, child, null, activity))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void copyStream(InputStream source, OutputStream target) throws IOException
|
||||||
|
{
|
||||||
|
final byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
|
int read;
|
||||||
|
while ((read = source.read(buffer)) != -1)
|
||||||
|
{
|
||||||
|
target.write(buffer, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,17 @@
|
|||||||
#include "cli/extract.hpp"
|
#include "cli/extract.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VCMI_ANDROID
|
||||||
|
#include <QAndroidJniObject>
|
||||||
|
#include <QtAndroid>
|
||||||
|
|
||||||
|
static FirstLaunchView * thiz;
|
||||||
|
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_heroesDataUpdate(JNIEnv * env, jclass cls)
|
||||||
|
{
|
||||||
|
thiz->heroesDataUpdate();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
FirstLaunchView::FirstLaunchView(QWidget * parent)
|
FirstLaunchView::FirstLaunchView(QWidget * parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, ui(new Ui::FirstLaunchView)
|
, ui(new Ui::FirstLaunchView)
|
||||||
@@ -97,7 +108,12 @@ void FirstLaunchView::on_pushButtonDataSearch_clicked()
|
|||||||
|
|
||||||
void FirstLaunchView::on_pushButtonDataCopy_clicked()
|
void FirstLaunchView::on_pushButtonDataCopy_clicked()
|
||||||
{
|
{
|
||||||
|
#ifdef VCMI_ANDROID
|
||||||
|
thiz = this;
|
||||||
|
QtAndroid::androidActivity().callMethod<void>("copyHeroesData");
|
||||||
|
#else
|
||||||
copyHeroesData();
|
copyHeroesData();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirstLaunchView::on_pushButtonGogInstall_clicked()
|
void FirstLaunchView::on_pushButtonGogInstall_clicked()
|
||||||
@@ -198,11 +214,22 @@ void FirstLaunchView::heroesDataMissing()
|
|||||||
ui->lineEditDataSystem->setPalette(newPalette);
|
ui->lineEditDataSystem->setPalette(newPalette);
|
||||||
ui->lineEditDataUser->setPalette(newPalette);
|
ui->lineEditDataUser->setPalette(newPalette);
|
||||||
|
|
||||||
ui->pushButtonDataSearch->setVisible(true);
|
|
||||||
ui->pushButtonDataCopy->setVisible(true);
|
|
||||||
|
|
||||||
ui->labelDataSearch->setVisible(true);
|
ui->labelDataSearch->setVisible(true);
|
||||||
ui->labelDataCopy->setVisible(true);
|
ui->pushButtonDataSearch->setVisible(true);
|
||||||
|
|
||||||
|
#ifdef VCMI_ANDROID
|
||||||
|
// selecting directory with ACTION_OPEN_DOCUMENT_TREE is available only since API level 21
|
||||||
|
if (QtAndroid::androidSdkVersion() < 21)
|
||||||
|
{
|
||||||
|
ui->labelDataCopy->hide();
|
||||||
|
ui->pushButtonDataCopy->hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ui->labelDataCopy->show();
|
||||||
|
ui->pushButtonDataCopy->show();
|
||||||
|
}
|
||||||
|
|
||||||
ui->labelDataFound->setVisible(false);
|
ui->labelDataFound->setVisible(false);
|
||||||
ui->pushButtonDataNext->setEnabled(false);
|
ui->pushButtonDataNext->setEnabled(false);
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ class FirstLaunchView : public QWidget
|
|||||||
void languageSelected(const QString & languageCode);
|
void languageSelected(const QString & languageCode);
|
||||||
|
|
||||||
// Tab Heroes III Data
|
// Tab Heroes III Data
|
||||||
bool heroesDataUpdate();
|
|
||||||
bool heroesDataDetect();
|
bool heroesDataDetect();
|
||||||
|
|
||||||
void heroesDataMissing();
|
void heroesDataMissing();
|
||||||
@@ -64,6 +63,9 @@ class FirstLaunchView : public QWidget
|
|||||||
public:
|
public:
|
||||||
explicit FirstLaunchView(QWidget * parent = nullptr);
|
explicit FirstLaunchView(QWidget * parent = nullptr);
|
||||||
|
|
||||||
|
// Tab Heroes III Data
|
||||||
|
bool heroesDataUpdate();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
Reference in New Issue
Block a user