Skip to content

Commit e48b97d

Browse files
AliothmoonMistEO
andauthored
feat: android native support (#1222)
Co-authored-by: MistEO <mistereo@hotmail.com>
1 parent ea893cd commit e48b97d

28 files changed

Lines changed: 1234 additions & 7 deletions

.github/workflows/build.yml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,9 @@ jobs:
389389
with:
390390
ndk-version: r27d
391391

392+
- name: Export ANDROID_NDK_ROOT
393+
run: echo "ANDROID_NDK_ROOT=${{ steps.setup-ndk.outputs.ndk-path }}" >> "$GITHUB_ENV"
394+
392395
- name: Setup ccache
393396
uses: Chocobo1/setup-ccache-action@v1
394397
with:
@@ -401,20 +404,29 @@ jobs:
401404
python3 tools/maadeps-download.py ${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-android
402405
403406
- name: Build MAA
407+
shell: bash
404408
run: |
405-
cmake --preset 'NinjaMulti' \
406-
-DCMAKE_TOOLCHAIN_FILE=${{ steps.setup-ndk.outputs.ndk-path}}/build/cmake/android.toolchain.cmake \
407-
-DANDROID_ABI=${{ matrix.arch == 'x86_64' && 'x86_64' || 'arm64-v8a' }} \
408-
-DANDROID_PLATFORM=android-23 \
409-
-DMAADEPS_TRIPLET='maa-${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-android' \
409+
if [[ "${{ matrix.arch }}" == "x86_64" ]]; then
410+
preset='NinjaMulti Android x64'
411+
else
412+
preset='NinjaMulti Android arm64'
413+
fi
414+
415+
cmake --preset "$preset" \
410416
-DMAA_HASH_VERSION='${{ needs.meta.outputs.tag }}'
411417
412-
cmake --build build --preset 'NinjaMulti - ${{ needs.meta.outputs.build-config }}' -j 16
418+
cmake --build --preset "$preset - ${{ needs.meta.outputs.build-config }}" -j 16
413419
414420
- name: Install
415421
shell: bash
416422
run: |
417-
cmake --install build --prefix install --config ${{ needs.meta.outputs.build-config }}
423+
if [[ "${{ matrix.arch }}" == "x86_64" ]]; then
424+
build_dir='build/android/x86_64'
425+
else
426+
build_dir='build/android/arm64-v8a'
427+
fi
428+
429+
cmake --install "$build_dir" --prefix install --config ${{ needs.meta.outputs.build-config }}
418430
419431
cp -r docs install
420432
cp README*.md install

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ include(source/MaaUtils/MaaUtils.cmake)
99
option(WITH_ADB_CONTROLLER "build with adb controller" ON)
1010
option(WITH_WIN32_CONTROLLER "build with win32 controller" ON)
1111
option(WITH_MACOS_CONTROLLER "build with macOS controller" ON)
12+
option(WITH_ANDROID_NATIVE_CONTROLLER "build with Android native controller" ON)
1213
option(WITH_CUSTOM_CONTROLLER "build with custom controller" ON)
1314
option(WITH_PLAYCOVER_CONTROLLER "build with PlayCover controller for macOS" ON)
1415
option(WITH_GAMEPAD_CONTROLLER "build with virtual gamepad controller for Windows" ON)
@@ -52,6 +53,11 @@ if(WITH_MACOS_CONTROLLER AND NOT APPLE)
5253
set(WITH_MACOS_CONTROLLER OFF)
5354
endif()
5455

56+
if(WITH_ANDROID_NATIVE_CONTROLLER AND NOT ANDROID)
57+
message(STATUS "Not on Android, disable WITH_ANDROID_NATIVE_CONTROLLER")
58+
set(WITH_ANDROID_NATIVE_CONTROLLER OFF)
59+
endif()
60+
5561
if(WITH_GAMEPAD_CONTROLLER AND NOT WIN32)
5662
message(STATUS "Not on Windows, disable WITH_GAMEPAD_CONTROLLER")
5763
set(WITH_GAMEPAD_CONTROLLER OFF)

CMakePresets.json

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,37 @@
5151
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/source/MaaUtils/MaaDeps/cmake/maa-arm64-linux-toolchain.cmake"
5252
}
5353
},
54+
{
55+
"name": "NinjaMulti Android",
56+
"hidden": true,
57+
"inherits": "NinjaMulti",
58+
"cacheVariables": {
59+
"CMAKE_TOOLCHAIN_FILE": "$env{ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake",
60+
"ANDROID_PLATFORM": "android-23"
61+
}
62+
},
63+
{
64+
"name": "NinjaMulti Android x64",
65+
"displayName": "Ninja MultiConfig Android x64",
66+
"description": "Ninja MultiConfig Android x64, requires ANDROID_NDK_ROOT",
67+
"inherits": "NinjaMulti Android",
68+
"binaryDir": "${sourceDir}/build/android/x86_64",
69+
"cacheVariables": {
70+
"ANDROID_ABI": "x86_64",
71+
"MAADEPS_TRIPLET": "maa-x64-android"
72+
}
73+
},
74+
{
75+
"name": "NinjaMulti Android arm64",
76+
"displayName": "Ninja MultiConfig Android arm64",
77+
"description": "Ninja MultiConfig Android arm64, requires ANDROID_NDK_ROOT",
78+
"inherits": "NinjaMulti Android",
79+
"binaryDir": "${sourceDir}/build/android/arm64-v8a",
80+
"cacheVariables": {
81+
"ANDROID_ABI": "arm64-v8a",
82+
"MAADEPS_TRIPLET": "maa-arm64-android"
83+
}
84+
},
5485
{
5586
"name": "MSVC 2022",
5687
"displayName": "MSVC 2022",
@@ -153,6 +184,54 @@
153184
"configuration": "Release",
154185
"jobs": 16
155186
},
187+
{
188+
"name": "NinjaMulti Android x64 - Debug",
189+
"displayName": "Ninja MultiConfig Android x64 Debug",
190+
"description": "Ninja MultiConfig Android x64 Debug",
191+
"configurePreset": "NinjaMulti Android x64",
192+
"configuration": "Debug",
193+
"jobs": 16
194+
},
195+
{
196+
"name": "NinjaMulti Android x64 - RelWithDebInfo",
197+
"displayName": "Ninja MultiConfig Android x64 RelWithDebInfo",
198+
"description": "Ninja MultiConfig Android x64 RelWithDebInfo",
199+
"configurePreset": "NinjaMulti Android x64",
200+
"configuration": "RelWithDebInfo",
201+
"jobs": 16
202+
},
203+
{
204+
"name": "NinjaMulti Android x64 - Release",
205+
"displayName": "Ninja MultiConfig Android x64 Release",
206+
"description": "Ninja MultiConfig Android x64 Release",
207+
"configurePreset": "NinjaMulti Android x64",
208+
"configuration": "Release",
209+
"jobs": 16
210+
},
211+
{
212+
"name": "NinjaMulti Android arm64 - Debug",
213+
"displayName": "Ninja MultiConfig Android arm64 Debug",
214+
"description": "Ninja MultiConfig Android arm64 Debug",
215+
"configurePreset": "NinjaMulti Android arm64",
216+
"configuration": "Debug",
217+
"jobs": 16
218+
},
219+
{
220+
"name": "NinjaMulti Android arm64 - RelWithDebInfo",
221+
"displayName": "Ninja MultiConfig Android arm64 RelWithDebInfo",
222+
"description": "Ninja MultiConfig Android arm64 RelWithDebInfo",
223+
"configurePreset": "NinjaMulti Android arm64",
224+
"configuration": "RelWithDebInfo",
225+
"jobs": 16
226+
},
227+
{
228+
"name": "NinjaMulti Android arm64 - Release",
229+
"displayName": "Ninja MultiConfig Android arm64 Release",
230+
"description": "Ninja MultiConfig Android arm64 Release",
231+
"configurePreset": "NinjaMulti Android arm64",
232+
"configuration": "Release",
233+
"jobs": 16
234+
},
156235
{
157236
"name": "MSVC 2022 - Debug",
158237
"displayName": "MSVC 2022 Debug",

docs/en_us/2.2-IntegratedInterfaceOverview.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,18 @@ Create Adb controller
254254

255255
Create Win32 controller
256256

257+
### MaaAndroidNativeControllerCreate
258+
259+
- `config_json`: Android native controller config JSON, required fields:
260+
- `library_path`: Android native control unit library path
261+
- `screen_resolution.width`: raw screenshot width, also used as the touch coordinate width
262+
- `screen_resolution.height`: raw screenshot height, also used as the touch coordinate height
263+
- optional fields: `display_id` (defaults to `0`), `force_stop` (defaults to `false`)
264+
265+
Create an Android native controller backed by `MaaAndroidNativeControlUnit` for native screenshot and input on Android.
266+
267+
> `screen_resolution` must match both the control unit's raw screenshot resolution and touch coordinate space, otherwise screencap fails immediately.
268+
257269
### MaaCustomControllerCreate
258270

259271
- `controller`: Custom control callback structure

docs/en_us/2.4-ControlMethods.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,29 @@ By default, all methods except `RawByNetcat`, `MinicapDirect`, and `MinicapStrea
4646
| MinicapStream | `32` | Very Fast | Low | Lossy | |
4747
| EmulatorExtras | `64` | Very Fast | Low | Lossless | Only supports emulators: MuMu 12, LDPlayer 9, and AVD |
4848

49+
## Android Native
50+
51+
The Android native controller uses `MaaAndroidNativeControlUnit` for direct screenshot and input on Android.
52+
53+
### Android Native Prerequisites
54+
55+
1. Android platform only
56+
57+
### Android Native Configuration
58+
59+
Pass a JSON config to `MaaAndroidNativeControllerCreate(config_json)`:
60+
61+
- `library_path`: Android native control unit library path
62+
- `screen_resolution.width` / `screen_resolution.height`: raw screenshot resolution, also used as the touch coordinate space
63+
- `display_id`: target display id, optional, defaults to `0`
64+
- `force_stop`: whether to force stop before `start_app`, optional, defaults to `false`
65+
66+
> [!NOTE]
67+
>
68+
> MaaFramework converts scaled recognition coordinates back to raw screenshot coordinates in `ControllerAgent`.
69+
> The Android native controller no longer performs any frame-to-touch remapping internally, and only clamps to `screen_resolution`.
70+
> If the control unit reports a raw frame resolution different from `screen_resolution`, screencap fails immediately.
71+
4972
## Win32
5073

5174
### Win32 Input

docs/zh_cn/2.2-集成接口一览.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,18 @@
254254

255255
创建 Win32 控制器
256256

257+
### MaaAndroidNativeControllerCreate
258+
259+
- `config_json`: Android Native 控制器配置 JSON,必填字段:
260+
- `library_path`: Android Native 控制单元库路径
261+
- `screen_resolution.width`: 原始截图宽度,同时也是 touch 坐标宽度
262+
- `screen_resolution.height`: 原始截图高度,同时也是 touch 坐标高度
263+
- 可选字段:`display_id`(默认 `0`)、`force_stop`(默认 `false`
264+
265+
创建 Android Native 控制器,用于在 Android 环境下通过 `MaaAndroidNativeControlUnit` 完成原生输入与截图。
266+
267+
> `screen_resolution` 必须与控制单元返回的原始截图分辨率和 touch 坐标系保持一致,否则截图会直接失败。
268+
257269
### MaaCustomControllerCreate
258270

259271
- `controller`: 自定义控制回调结构体

docs/zh_cn/2.4-控制方式说明.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,29 @@
4646
| MinicapStream | `32` | 极快 || 有损 | |
4747
| EmulatorExtras | `64` | 极快 || 无损 | 仅支持模拟器:MuMu 12、雷电 9、AVD |
4848

49+
## Android Native
50+
51+
Android Native 控制器用于在 Android 环境下通过 `MaaAndroidNativeControlUnit` 直接完成截图和输入。
52+
53+
### Android Native 前置要求
54+
55+
1. 仅支持 Android 平台
56+
57+
### Android Native 配置
58+
59+
通过 `MaaAndroidNativeControllerCreate(config_json)` 传入 JSON 配置:
60+
61+
- `library_path`:Android Native 控制单元库路径
62+
- `screen_resolution.width` / `screen_resolution.height`:原始截图分辨率,同时也是 touch 坐标系
63+
- `display_id`:目标显示 ID,可选,默认 `0`
64+
- `force_stop``start_app` 前是否强制停止应用,可选,默认 `false`
65+
66+
> [!NOTE]
67+
>
68+
> MaaFramework 会在 `ControllerAgent` 中统一把缩放后的识别坐标换算回原始截图坐标。
69+
> Android Native 控制器不会再额外做 frame-to-touch 映射,只会按 `screen_resolution` 做边界裁剪。
70+
> 如果控制单元返回的原始截图分辨率与 `screen_resolution` 不一致,截图会直接失败。
71+
4972
## Win32
5073

5174
### Win32 Input
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include "MaaControlUnit/ControlUnitAPI.h"
4+
#include "MaaFramework/MaaDef.h"
5+
6+
#ifdef __cplusplus
7+
extern "C"
8+
{
9+
#endif
10+
11+
MAA_CONTROL_UNIT_API const char* MaaAndroidNativeControlUnitGetVersion();
12+
13+
MAA_CONTROL_UNIT_API MaaAndroidNativeControlUnitHandle MaaAndroidNativeControlUnitCreate(const char* config_json);
14+
15+
MAA_CONTROL_UNIT_API void MaaAndroidNativeControlUnitDestroy(MaaAndroidNativeControlUnitHandle handle);
16+
17+
#ifdef __cplusplus
18+
}
19+
#endif

include/MaaControlUnit/ControlUnitAPI.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ class AdbControlUnitAPI
8686
virtual bool find_device(/*out*/ std::vector<std::string>& devices) = 0;
8787
};
8888

89+
class AndroidNativeControlUnitAPI : public ControlUnitAPI
90+
{
91+
public:
92+
~AndroidNativeControlUnitAPI() override = default;
93+
94+
virtual void* attach_thread() const = 0;
95+
virtual int detach_thread(void* env) const = 0;
96+
};
97+
8998
class Win32ControlUnitAPI
9099
: public ControlUnitAPI
91100
, public ScrollableUnit
@@ -141,3 +150,4 @@ using MaaCustomControlUnitHandle = MAA_CTRL_UNIT_NS::CustomControlUnitAPI*;
141150
using MaaReplayControlUnitHandle = MAA_CTRL_UNIT_NS::FullControlUnitAPI*;
142151
using MaaRecordControlUnitHandle = MAA_CTRL_UNIT_NS::FullControlUnitAPI*;
143152
using MaaDbgControlUnitHandle = MAA_CTRL_UNIT_NS::ControlUnitAPI*;
153+
using MaaAndroidNativeControlUnitHandle = MAA_CTRL_UNIT_NS::AndroidNativeControlUnitAPI*;

include/MaaControlUnit/MaaControlUnitAPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "RecordTypes.h"
77

88
#include "AdbControlUnitAPI.h"
9+
#include "AndroidNativeControlUnitAPI.h"
910
#include "CustomControlUnitAPI.h"
1011
#include "DbgControlUnitAPI.h"
1112
#include "GamepadControlUnitAPI.h"

0 commit comments

Comments
 (0)