Skip to content
Closed
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
150 changes: 150 additions & 0 deletions .github/workflows/build-custom-maa-core.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
name: Build APK with Custom MAA Core

# Cloud pipeline for testing custom MAA Core (e.g. facility_preset PR):
# Job 1: build Android arm64 MAA Core from a fork/ref
# Job 2: deploy Core into MAA-Meow and assemble APK

on:
workflow_dispatch:
inputs:
maa_repo:
description: 'MAA fork (owner/repo) containing your Core changes'
required: true
default: 'xjbsteven/MaaAssistantArknights'
maa_ref:
description: 'MAA git ref to build (branch/tag/commit)'
required: true
default: 'dev-v2'
build_type:
description: 'APK build type'
required: true
default: 'debug'
type: choice
options:
- debug
- release

jobs:
build-maa-core:
name: Build MAA Android Core
runs-on: macos-latest
outputs:
core_version: ${{ steps.meta.outputs.core_version }}
steps:
- name: Checkout MAA
uses: actions/checkout@v4
with:
repository: ${{ inputs.maa_repo }}
ref: ${{ inputs.maa_ref }}

- name: Fetch MaaUtils submodule
run: git submodule update --init --depth 1 src/MaaUtils

- name: Resolve Core version label
id: meta
run: |
ver="$(git describe --tags --match 'v*' HEAD 2>/dev/null || echo "local-$(git rev-parse --short HEAD)")"
echo "core_version=${ver}" >> "$GITHUB_OUTPUT"
echo "Core version label: ${ver}"

- name: Bootstrap MaaDeps (arm64-android)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python3 tools/maadeps-download.py arm64-android

- name: Setup Android NDK
id: setup-ndk
uses: nttld/setup-ndk@v1
with:
ndk-version: r29

- name: Configure, build and install (arm64)
run: |
cmake -B build --preset android-publish-arm64 \
-DCMAKE_TOOLCHAIN_FILE=${{ steps.setup-ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \
-DMAA_HASH_VERSION='${{ steps.meta.outputs.core_version }}'
cmake --build build --parallel $(sysctl -n hw.logicalcpu)
cmake --install build --prefix install

- name: Download MaaFramework control unit
uses: robinraju/release-downloader@v1
with:
repository: MaaXYZ/MaaFramework
latest: true
fileName: "*android-aarch64*.zip"
extract: true
out-file-path: MaaFramework-temp

- name: Copy MaaAndroidNativeControlUnit
run: cp MaaFramework-temp/bin/libMaaAndroidNativeControlUnit.so install/

- name: Upload MAA Core install tree
uses: actions/upload-artifact@v4
with:
name: maa-android-arm64-install
path: install/
compression-level: 6

build-apk:
name: Build MAA-Meow APK
needs: build-maa-core
runs-on: macos-latest
steps:
- name: Checkout MAA-Meow
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Download custom MAA Core
uses: actions/download-artifact@v4
with:
name: maa-android-arm64-install
path: maa-install

- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'

- name: Setup Android SDK
uses: android-actions/setup-android@v3

- name: Install NDK and CMake
run: sdkmanager --install "ndk;29.0.13113456" "cmake;3.22.1"

- name: Deploy custom MAA Core into project
run: |
python scripts/deploy_local_maa_core.py \
--install-dir "$GITHUB_WORKSPACE/maa-install" \
--abi arm64-v8a \
--version "${{ needs.build-maa-core.outputs.core_version }}"

- name: Print MAA Resource version
run: cat app/src/main/assets/MaaSync/MaaResource/version.json

- name: Build Debug APK
if: inputs.build_type == 'debug'
run: |
chmod +x ./gradlew
./gradlew clean assembleDebug

- name: Build Release APK
if: inputs.build_type == 'release'
env:
KEYSTORE_PATH: ${{ github.workspace }}/release.jks
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.jks
chmod +x ./gradlew
./gradlew clean assembleRelease

- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: meow-apk-${{ needs.build-maa-core.outputs.core_version }}-${{ inputs.build_type }}
path: |
app/build/outputs/apk/debug/*.apk
app/build/outputs/apk/release/*.apk
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ android/.cxx
/app/release
/app/debug
/gradle/gradle-daemon-jvm.properties

# Local build toolchain (JDK/NDK downloads for offline builds)
.build-tools/
84 changes: 84 additions & 0 deletions scripts/deploy_local_maa_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Deploy a locally built MAA install/ tree into MAA-Meow assets and jniLibs."""

from __future__ import annotations

import argparse
import shutil
import sys
from pathlib import Path

ASSETS_RESOURCE_DIR = Path("app/src/main/assets/MaaSync/MaaResource")
JNILIBS_DIR = Path("app/src/main/jniLibs")
VERSION_FILE = Path(".maaversion")
EXCLUDE_SO = {"libc++_shared.so"}


def deploy(install_dir: Path, project_root: Path, abi: str, version: str) -> None:
if not install_dir.is_dir():
raise SystemExit(f"[ERROR] install dir not found: {install_dir}")

resource_src = install_dir / "resource"
if not resource_src.is_dir():
raise SystemExit(f"[ERROR] resource dir not found: {resource_src}")

assets_dir = project_root / ASSETS_RESOURCE_DIR
if assets_dir.exists():
print(f"[DELETE] {assets_dir}")
shutil.rmtree(assets_dir)
assets_dir.mkdir(parents=True, exist_ok=True)

copied_resource = 0
for src in resource_src.rglob("*"):
if not src.is_file():
continue
rel = src.relative_to(resource_src)
dest = assets_dir / rel
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dest)
copied_resource += 1

jnilib_dir = project_root / JNILIBS_DIR / abi
jnilib_dir.mkdir(parents=True, exist_ok=True)
for existing in jnilib_dir.glob("*.so"):
if existing.name != "libjnidispatch.so":
existing.unlink()

copied_so = 0
for so in install_dir.glob("*.so"):
if so.name in EXCLUDE_SO:
continue
shutil.copy2(so, jnilib_dir / so.name)
copied_so += 1

(project_root / VERSION_FILE).write_text(version + "\n", encoding="utf-8")
print(f"[VERSION] {VERSION_FILE}: {version}")
print(f"[DONE] resource={copied_resource} files, so={copied_so} files -> {abi}/")


def main() -> None:
parser = argparse.ArgumentParser(description="Deploy local MAA install/ into MAA-Meow")
parser.add_argument(
"--install-dir",
required=True,
help="Path to MAA cmake install/ directory (contains resource/ and *.so)",
)
parser.add_argument(
"--abi",
default="arm64-v8a",
choices=["arm64-v8a", "x86_64"],
help="Target Android ABI (default: arm64-v8a)",
)
parser.add_argument(
"--version",
default="local-facility-preset",
help="Version string written to .maaversion",
)
args = parser.parse_args()

project_root = Path(__file__).resolve().parent.parent
deploy(Path(args.install_dir).resolve(), project_root, args.abi, args.version)


if __name__ == "__main__":
main()
Loading