1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-21 17:17:06 +02:00

[android][launcher] copy existing oh3 files using Java

This commit is contained in:
Andrey Filipenkov 2024-05-26 17:38:50 +03:00
parent ed6ab19818
commit d7bf6b7dbe
7 changed files with 175 additions and 8 deletions

View File

@ -157,4 +157,5 @@ def LoadSigningConfig(final signingConfigKey) {
dependencies {
implementation fileTree(dir: '../libs', include: ['*.jar', '*.aar'])
implementation 'androidx.annotation:annotation:1.7.1'
implementation 'androidx.documentfile:documentfile:1.0.1'
}

View File

@ -1,10 +1,18 @@
package eu.vcmi.vcmi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import androidx.annotation.Nullable;
import java.io.File;
import eu.vcmi.vcmi.VcmiSDLActivity;
import eu.vcmi.vcmi.util.FileUtil;
import org.libsdl.app.SDL;
@ -13,6 +21,8 @@ import org.libsdl.app.SDL;
*/
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;
@Override
@ -23,6 +33,28 @@ public class ActivityLauncher extends org.qtproject.qt5.android.bindings.QtActiv
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()
{
startActivity(new Intent(ActivityLauncher.this, VcmiSDLActivity.class));

View File

@ -8,8 +8,6 @@ import android.os.Build;
public class Const
{
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";
}

View File

@ -26,7 +26,7 @@ public class NativeMethods
}
public static native void initClassloader();
public static native void heroesDataUpdate();
public static native boolean tryToSaveTheGame();
public static void setupMsg(final Messenger msg)

View 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);
}
}
}

View File

@ -26,6 +26,17 @@
#include "cli/extract.hpp"
#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)
: QWidget(parent)
, ui(new Ui::FirstLaunchView)
@ -97,7 +108,12 @@ void FirstLaunchView::on_pushButtonDataSearch_clicked()
void FirstLaunchView::on_pushButtonDataCopy_clicked()
{
#ifdef VCMI_ANDROID
thiz = this;
QtAndroid::androidActivity().callMethod<void>("copyHeroesData");
#else
copyHeroesData();
#endif
}
void FirstLaunchView::on_pushButtonGogInstall_clicked()
@ -198,11 +214,22 @@ void FirstLaunchView::heroesDataMissing()
ui->lineEditDataSystem->setPalette(newPalette);
ui->lineEditDataUser->setPalette(newPalette);
ui->pushButtonDataSearch->setVisible(true);
ui->pushButtonDataCopy->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->pushButtonDataNext->setEnabled(false);

View File

@ -35,7 +35,6 @@ class FirstLaunchView : public QWidget
void languageSelected(const QString & languageCode);
// Tab Heroes III Data
bool heroesDataUpdate();
bool heroesDataDetect();
void heroesDataMissing();
@ -64,6 +63,9 @@ class FirstLaunchView : public QWidget
public:
explicit FirstLaunchView(QWidget * parent = nullptr);
// Tab Heroes III Data
bool heroesDataUpdate();
public slots:
private slots: