Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: generate-builds
on:
push:
pull_request:
# push:
# pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down Expand Up @@ -380,3 +381,29 @@ jobs:
with:
name: 2ship-windows
path: 2ship-windows

build-android:
needs: generate-2ship-otr
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: sudo apt-get install -y ninja-build
- name: Download 2ship.o2r
uses: actions/download-artifact@v4
with:
name: 2ship.o2r
path: Android/app/src/main/assets
- name: Build 2Ship
run: |
cd Android/
./gradlew assembleDebug -P elfBuildType=RelWithDebInfo
mv app/build/outputs/apk/debug/app-debug.apk ../2ship.apk
- name: Create release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref }}
file: 2ship.apk
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ _packages/
/mm/src/boot/build.c
/mm/windows/properties.h
/clang-format.exe

# IntelliJ / Android Studio
.idea
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "libultraship"]
path = libultraship
url = https://github.com/Waterdish/libultraship.git
url = https://github.com/robertkirkman/libultraship.git
[submodule "OTRExporter"]
path = OTRExporter
url = https://github.com/Waterdish/OTRExporter.git
Expand Down
50 changes: 24 additions & 26 deletions Android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY');
def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY')
def buildAsApplication = !buildAsLibrary
if (buildAsApplication) {
apply plugin: 'com.android.application'
Expand All @@ -8,35 +8,39 @@ else {
}

android {
ndkPath "/home/waterdish/Android/Sdk/ndk/26.0.10792818" // Point to your own NDK
compileSdkVersion 31
ndkVersion '27.2.12479018'
compileSdkVersion 34
defaultConfig {
if (buildAsApplication) {
applicationId "com.dishii.mm"
}
minSdkVersion 24
targetSdkVersion 31
minSdkVersion 21
//noinspection OldTargetApi
targetSdkVersion 34
versionCode 4
versionName "1.1.1"
externalNativeBuild {
//ndkBuild {
// arguments "APP_PLATFORM=android-23"
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
//}
cmake {
arguments "-DSDL_SHARED=ON", "-DANDROID_STL=c++_static", "-DHAVE_LD_VERSION_SCRIPT=OFF",'-DUSE_OPENGLES=ON'
arguments "-DANDROID_APPNAME=${applicationId}", "-DANDROID_APP_PLATFORM=android-21", "-DANDROID_STL=c++_static", "-DHAVE_LD_VERSION_SCRIPT=OFF", "-DUSE_OPENGLES=ON", "-DCMAKE_BUILD_TYPE=$elfBuildType"
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
//abiFilters 'arm64-v8a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
applicationVariants.all { variant ->
buildFeatures {
buildConfig = true
}
namespace 'com.dishii.mm'
lint {
abortOnError false
}
applicationVariants.configureEach { variant ->
tasks["merge${variant.name.capitalize()}Assets"]
.dependsOn("externalNativeBuild${variant.name.capitalize()}")
}
Expand All @@ -45,26 +49,20 @@ android {
jniLibs.srcDir 'libs'
}
externalNativeBuild {
//ndkBuild {
// path 'jni/Android.mk'
//}
cmake {
path '../../CMakeLists.txt'
version "3.25.1"
version "3.31.5"
}
}

}
lintOptions {
abortOnError false
}


if (buildAsLibrary) {
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith(".aar")) {
def fileName = "org.libsdl.app.aar";
def fileName = "com.dishii.mm.aar"
output.outputFile = new File(outputFile.parent, fileName);
}
}
Expand All @@ -74,13 +72,13 @@ android {

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.core:core:1.7.0' // Use the latest version
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core:1.13.1'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
}

task wrapper(type: Wrapper) {
gradleVersion = '7.0.3'
tasks.register('wrapper', Wrapper) {
gradleVersion = '8.10.2'
}

task prepareKotlinBuildScriptModel {
tasks.register('prepareKotlinBuildScriptModel') {
}
Binary file removed Android/app/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 0 additions & 5 deletions Android/app/gradle/wrapper/gradle-wrapper.properties

This file was deleted.

7 changes: 3 additions & 4 deletions Android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
com.gamemaker.game
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dishii.mm"
android:versionCode="4"
android:versionName="1.1.1"
android:installLocation="auto">
Expand Down Expand Up @@ -54,8 +53,8 @@
<!-- Allow access to the vibrator -->
<uses-permission android:name="android.permission.VIBRATE" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<!-- if you want to capture audio, uncomment this. -->
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
Expand All @@ -73,7 +72,8 @@
android:allowBackup="true"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:hardwareAccelerated="true"
android:appCategory="game" >
android:appCategory="game"
android:requestLegacyExternalStorage="true">


<!-- Example of setting SDL hints from AndroidManifest.xml:
Expand All @@ -84,7 +84,6 @@


<activity android:name="MainActivity"
android:label="@string/app_name"
android:alwaysRetainTaskState="true"
android:launchMode="singleInstance"
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
Expand Down
1 change: 1 addition & 0 deletions Android/app/src/main/assets/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Extractor Assets Copied by CMake during buildtime
assets/
mods/
103 changes: 61 additions & 42 deletions Android/app/src/main/java/com/dishii/mm/AssetCopyUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,79 @@

import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class AssetCopyUtil {
// based on https://stackoverflow.com/a/8366081/11708026
// This is desirable because it bulk copies all assets indiscriminately, simplifying the code in MainActivity
// the side effect is that, some people will see strange, unidentifiable files appearing in their destination folder.
// those extra files do not come from the app itself. They originate from something inside the Android ROM
// of the device they are using, and can be observed to vary between different models of devices.
public static void copyAssetsToExternal(Context context, String externalFolderPath) {
externalFolderPath = externalFolderPath + "/";
copyFileOrDir(context, "", externalFolderPath); // copy all files in assets folder to the destination
}

public static void copyAssetsToExternal(Context context, String assetsFolderPath, String externalFolderPath) throws IOException {
private static void copyFileOrDir(Context context, String srcpath, String destpath) {
AssetManager assetManager = context.getAssets();
String[] assetFiles = assetManager.list(assetsFolderPath);

for (String assetFile : assetFiles) {
String assetPath = assetsFolderPath + File.separator + assetFile;
String externalPath = externalFolderPath + File.separator + assetFile;

if (assetManager.list(assetPath).length > 0) {
// It's a directory
// Check if the directory exists in the external storage
File externalDir = new File(externalPath);
if (!externalDir.exists()) {
externalDir.mkdirs(); // Create the directory if it doesn't exist
}

// Recursively copy contents of the directory
copyAssetsToExternal(context, assetPath, externalPath);
String assets[] = null;
String tag = "AssetCopyUtil";
try {
Log.i(tag, "copyFileOrDir() " + srcpath);
assets = assetManager.list(srcpath);
if (assets.length == 0) {
copyFile(context, srcpath, destpath);
} else {
// It's a file
File externalFile = new File(externalPath);
if (!externalFile.exists()) {
// Check if the file exists in the external storage
InputStream in = null;
OutputStream out = null;

try {
in = assetManager.open(assetPath);
out = new FileOutputStream(externalPath);

byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}

} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
String fullPath = destpath + srcpath;
Log.i(tag, "path=" + fullPath);
File dir = new File(fullPath);
if (!dir.exists())
if (!dir.mkdirs())
Log.i(tag, "could not create dir " + fullPath);
for (int i = 0; i < assets.length; ++i) {
String p;
if (srcpath.isEmpty())
p = "";
else
p = srcpath + "/";
copyFileOrDir(context,p + assets[i], destpath);
}
}
} catch (IOException ex) {
Log.e(tag, "I/O Exception", ex);
}
}

private static void copyFile(Context context, String filename, String destpath) {
AssetManager assetManager = context.getAssets();
InputStream in = null;
OutputStream out = null;
String newFileName = null;
String tag = "AssetCopyUtil";
try {
Log.i(tag, "copyFile() " + filename);
in = assetManager.open(filename);
newFileName = destpath + filename;
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e(tag, "Exception in copyFile() of " + newFileName);
Log.e(tag, "Exception in copyFile() " + e.toString());
}
}
}
Loading