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
19 changes: 19 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,21 @@ jobs:
sudo apt-get update -y
sudo apt-get install -y ninja-build cmake ccache

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

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
gradle-version: '8.5'

- name: Build Kotlin Library
working-directory: source/MaaAndroidControlUnit/java
run: gradle assembleRelease

- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
Expand Down Expand Up @@ -412,6 +427,10 @@ jobs:

cp -r LICENSE.md install

# Copy Kotlin AAR
mkdir -p install/android
cp source/MaaAndroidControlUnit/java/build/outputs/aar/*.aar install/android/ || true

- name: Download Plugin
uses: robinraju/release-downloader@v1
with:
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include(source/MaaUtils/MaaUtils.cmake)

option(WITH_ADB_CONTROLLER "build with adb controller" ON)
option(WITH_WIN32_CONTROLLER "build with win32 controller" ON)
option(WITH_ANDROID_CONTROLLER "build with android controller" ON)
option(WITH_DBG_CONTROLLER "build with debugging controller" OFF)
option(WITH_CUSTOM_CONTROLLER "build with custom controller" ON)
option(WITH_NODEJS_BINDING "build with nodejs binding" OFF)
Expand Down Expand Up @@ -38,6 +39,11 @@ if(WITH_WIN32_CONTROLLER AND NOT WIN32)
set(WITH_WIN32_CONTROLLER OFF)
endif()

if(WITH_ANDROID_CONTROLLER AND NOT ANDROID)
message(STATUS "Not on Android, disable WITH_ANDROID_CONTROLLER")
set(WITH_ANDROID_CONTROLLER OFF)
endif()

if(WITH_MAA_AGENT)
find_package(cppzmq REQUIRED)
endif()
Expand Down
8 changes: 8 additions & 0 deletions docs/en_us/2.2-IntegratedInterfaceOverview.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ Create Adb controller

> Screenshot and input methods will be speed tested at startup, selecting the fastest option.

### MaaAndroidControllerCreate

- `screencap_methods`: bitmask of `MaaAndroidScreencapMethod` (AccessibilityScreenshot or MediaProjection)
- `input_methods`: use `MaaAndroidInputMethod_Accessibility` (control via accessibility service)
- `config`: extra config (reserved, can be empty)
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation mentions a config parameter that doesn't exist in the actual API signature. The MaaAndroidControllerCreate function only takes screencap_methods and input_methods parameters, not a config parameter.

Suggested change
- `config`: extra config (reserved, can be empty)

Copilot uses AI. Check for mistakes.

Create native Android controller (requires accessibility; MediaProjection screenshot needs user consent)

### MaaWin32ControllerCreate

- `hWnd`: window handle
Expand Down
21 changes: 21 additions & 0 deletions docs/en_us/2.4-ControlMethods.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,27 @@ By default, all methods except `RawByNetcat`, `MinicapDirect`, and `MinicapStrea
| MinicapStream | `32` | Takes streaming screenshots and encodes to jpg via minicap tool, transfers via adb process pipe. |
| EmulatorExtras | `64` | Uses emulator-specific tools for screenshots. Currently supported emulators: MuMu 12, LDPlayer 9 |

## Android

### Android Input

> Reference: `MaaAndroidInputMethod`.

| Name | Value | Description |
| --- | --- | --- |
| Accessibility | `1` | Uses accessibility service for control, including `dispatchGesture` for tap/swipe/scroll, global actions for key events (back/home/recents), and `ACTION_SET_TEXT` on current focused input node. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): 将 "current focused" 改为 "currently focused" 以符合正确的语法

将 "on current focused input node" 修改为 "on the currently focused input node",以保证语法正确且表达更清晰。

Suggested change
| Accessibility | `1` | Uses accessibility service for control, including `dispatchGesture` for tap/swipe/scroll, global actions for key events (back/home/recents), and `ACTION_SET_TEXT` on current focused input node. |
| Accessibility | `1` | Uses accessibility service for control, including `dispatchGesture` for tap/swipe/scroll, global actions for key events (back/home/recents), and `ACTION_SET_TEXT` on the currently focused input node. |
Original comment in English

issue (typo): Use "currently focused" instead of "current focused" for correct grammar.

Change "on current focused input node" to "on the currently focused input node" for correct grammar and clarity.

Suggested change
| Accessibility | `1` | Uses accessibility service for control, including `dispatchGesture` for tap/swipe/scroll, global actions for key events (back/home/recents), and `ACTION_SET_TEXT` on current focused input node. |
| Accessibility | `1` | Uses accessibility service for control, including `dispatchGesture` for tap/swipe/scroll, global actions for key events (back/home/recents), and `ACTION_SET_TEXT` on the currently focused input node. |


### Android Screencap

> Reference: `MaaAndroidScreencapMethod`.

Combine the selected methods below using **bitwise OR**. Framework will choose available ones, preferring MediaProjection (faster and more stable), then AccessibilityScreenshot.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (typo): 建议在 "Framework will choose available ones" 中补充冠词,使语句更顺畅

可以改成这样以使表达更自然且语法完整:"The framework will choose the available ones, preferring MediaProjection …"。

Suggested change
Combine the selected methods below using **bitwise OR**. Framework will choose available ones, preferring MediaProjection (faster and more stable), then AccessibilityScreenshot.
Combine the selected methods below using **bitwise OR**. The framework will choose the available ones, preferring MediaProjection (faster and more stable), then AccessibilityScreenshot.
Original comment in English

suggestion (typo): Consider adding an article to "Framework will choose available ones" for smoother phrasing.

You could rephrase to: "The framework will choose the available ones, preferring MediaProjection …" for more natural, grammatically complete wording.

Suggested change
Combine the selected methods below using **bitwise OR**. Framework will choose available ones, preferring MediaProjection (faster and more stable), then AccessibilityScreenshot.
Combine the selected methods below using **bitwise OR**. The framework will choose the available ones, preferring MediaProjection (faster and more stable), then AccessibilityScreenshot.


| Name | Value | Description |
| --- | --- | --- |
| AccessibilityScreenshot | `1` | API 33+ accessibility `takeScreenshot`. No extra permission required, but needs Android 13 or above. |
| MediaProjection | `2` | MediaProjection virtual display screenshot, requires user consent. Faster and better compatibility. |

## Win32

### Win32 Input
Expand Down
8 changes: 8 additions & 0 deletions docs/zh_cn/2.2-集成接口一览.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@

> 截图方式和输入方式会在启动时进行测速,选择最快的方案

### MaaAndroidControllerCreate

- `screencap_methods`: 安卓原生截图方式集合,位或自 `MaaAndroidScreencapMethod`(AccessibilityScreenshot 或 MediaProjection)
- `input_methods`: 安卓原生输入方式,使用 `MaaAndroidInputMethod_Accessibility`(通过辅助功能进行控制)
- `config`: 额外配置(预留,可为空字符串)

创建安卓原生控制器(依赖辅助功能;MediaProjection 截图需用户授权录屏)

### MaaWin32ControllerCreate

- `hWnd`: 窗口句柄
Expand Down
21 changes: 21 additions & 0 deletions docs/zh_cn/2.4-控制方式说明.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,27 @@
| MinicapStream | `32` | 通过 minicap 工具流式截图和编码为 jpg,通过 adb 进程管道传输。 |
| EmulatorExtras | `64` | 使用模拟器专用工具进行截图。目前支持的模拟器:MuMu 12、雷电 9 |

## Android

### Android Input

> 参考 `MaaAndroidInputMethod` 定义。

| 名称 | 值 | 说明 |
| --- | --- | --- |
| Accessibility | `1` | 通过辅助功能进行控制,包括 `dispatchGesture` 点击/滑动/滚动、全局按键(返回/主页/多任务)、以及对焦点输入框执行 `ACTION_SET_TEXT`。 |

### Android Screencap

> 参考 `MaaAndroidScreencapMethod` 定义。

将下面选择的方式 **按位或** 合并为一个值提供。框架会按可用性选择,优先使用 MediaProjection(更快更稳定),其次使用 AccessibilityScreenshot。

| 名称 | 值 | 说明 |
| --- | --- | --- |
| AccessibilityScreenshot | `1` | API 33+ 辅助功能 `takeScreenshot`。无需额外权限,但需要 Android 13 及以上。 |
| MediaProjection | `2` | MediaProjection 虚拟显示截图,需要用户授权录屏。速度更快,兼容性更好。 |

## Win32

### Win32 Input
Expand Down
3 changes: 3 additions & 0 deletions include/MaaFramework/Instance/MaaController.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ extern "C"
const char* config,
const char* agent_path);

MAA_FRAMEWORK_API MaaController*
MaaAndroidControllerCreate(MaaAndroidScreencapMethod screencap_methods, MaaAndroidInputMethod input_methods);

MAA_FRAMEWORK_API MaaController* MaaWin32ControllerCreate(
void* hWnd,
MaaWin32ScreencapMethod screencap_method,
Expand Down
21 changes: 21 additions & 0 deletions include/MaaFramework/MaaDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,27 @@ typedef uint64_t MaaAdbInputMethod;
#define MaaAdbInputMethod_All (~MaaAdbInputMethod_None)
#define MaaAdbInputMethod_Default (MaaAdbInputMethod_All & (~MaaAdbInputMethod_EmulatorExtras))

// MaaAndroidScreencapMethod:
/**
* Use bitwise OR to set the method you need, MaaFramework will test their availability.
*/
typedef uint64_t MaaAndroidScreencapMethod;
#define MaaAndroidScreencapMethod_None 0ULL
/// API 33+ AccessibilityService.takeScreenshot
#define MaaAndroidScreencapMethod_AccessibilityScreenshot 1ULL
/// MediaProjection VirtualDisplay capture (requires user consent)
#define MaaAndroidScreencapMethod_MediaProjection (1ULL << 1)
#define MaaAndroidScreencapMethod_All (~MaaAndroidScreencapMethod_None)
#define MaaAndroidScreencapMethod_Default (MaaAndroidScreencapMethod_AccessibilityScreenshot | MaaAndroidScreencapMethod_MediaProjection)

// MaaAndroidInputMethod:
/**
* Use bitwise OR to set the method you need.
*/
typedef uint64_t MaaAndroidInputMethod;
#define MaaAndroidInputMethod_None 0ULL
#define MaaAndroidInputMethod_Accessibility 1ULL
Comment on lines +269 to +271
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 定义 MaaAndroidInputMethod_All 和 MaaAndroidInputMethod_Default 以与模块导出和用法保持一致

MaaFramework.cppm 导出了 _MaaAndroidInputMethod_All / _MaaAndroidInputMethod_Default,并引用了 MaaAndroidInputMethod_All / MaaAndroidInputMethod_Default,但这些宏在此处没有定义。这会导致编译或链接错误。请在这里定义它们(例如:

#define MaaAndroidInputMethod_All (~MaaAndroidInputMethod_None)
#define MaaAndroidInputMethod_Default MaaAndroidInputMethod_Accessibility

或者使用你偏好的语义),以保证 C API 与模块导出保持一致。

Original comment in English

issue (bug_risk): Define MaaAndroidInputMethod_All and MaaAndroidInputMethod_Default to match module exports and usage

MaaFramework.cppm exports _MaaAndroidInputMethod_All / _MaaAndroidInputMethod_Default and refers to MaaAndroidInputMethod_All / MaaAndroidInputMethod_Default, but these macros are not defined here. That will cause compile or link errors. Please define them (e.g.

#define MaaAndroidInputMethod_All (~MaaAndroidInputMethod_None)
#define MaaAndroidInputMethod_Default MaaAndroidInputMethod_Accessibility

or whatever semantics you prefer) so the C API and module exports remain consistent.

Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing MaaAndroidInputMethod_All and MaaAndroidInputMethod_Default macros. For consistency with other input method definitions (like MaaAdbInputMethod), these should be defined. Suggested additions:

#define MaaAndroidInputMethod_All (~MaaAndroidInputMethod_None)
#define MaaAndroidInputMethod_Default MaaAndroidInputMethod_Accessibility
Suggested change
#define MaaAndroidInputMethod_Accessibility 1ULL
#define MaaAndroidInputMethod_Accessibility 1ULL
#define MaaAndroidInputMethod_All (~MaaAndroidInputMethod_None)
#define MaaAndroidInputMethod_Default MaaAndroidInputMethod_Accessibility

Copilot uses AI. Check for mistakes.

// MaaWin32ScreencapMethod:
/**
* No bitwise OR, just set it
Expand Down
4 changes: 4 additions & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ if(WITH_ADB_CONTROLLER)
add_subdirectory(MaaAdbControlUnit)
endif()

if(WITH_ANDROID_CONTROLLER)
add_subdirectory(MaaAndroidControlUnit)
endif()

if(WITH_WIN32_CONTROLLER)
add_subdirectory(MaaWin32ControlUnit)
endif()
Expand Down
4 changes: 4 additions & 0 deletions source/LibraryHolder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ if(WITH_ADB_CONTROLLER)
add_dependencies(LibraryHolder MaaAdbControlUnit)
endif()

if(WITH_ANDROID_CONTROLLER)
add_dependencies(LibraryHolder MaaAndroidControlUnit)
endif()

if(WITH_WIN32_CONTROLLER)
add_dependencies(LibraryHolder MaaWin32ControlUnit)
endif()
Expand Down
34 changes: 34 additions & 0 deletions source/LibraryHolder/ControlUnit/ControlUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <filesystem>

#include "ControlUnit/AdbControlUnitAPI.h"
#include "ControlUnit/AndroidControlUnitAPI.h"
#include "ControlUnit/CustomControlUnitAPI.h"
#include "ControlUnit/DbgControlUnitAPI.h"
#include "ControlUnit/Win32ControlUnitAPI.h"
Expand Down Expand Up @@ -65,6 +66,39 @@ std::shared_ptr<MAA_CTRL_UNIT_NS::AdbControlUnitAPI> AdbControlUnitLibraryHolder
return std::shared_ptr<MAA_CTRL_UNIT_NS::AdbControlUnitAPI>(control_unit_handle, destroy_control_unit_func);
}

std::shared_ptr<MAA_CTRL_UNIT_NS::AndroidControlUnitAPI> AndroidControlUnitLibraryHolder::create_control_unit(
MaaAndroidScreencapMethod screencap_methods,
MaaAndroidInputMethod input_methods)
{
if (!load_library(library_dir() / libname_)) {
LogError << "Failed to load library" << VAR(library_dir()) << VAR(libname_);
return nullptr;
}

check_version<AndroidControlUnitLibraryHolder, decltype(MaaAndroidControlUnitGetVersion)>(version_func_name_);

auto create_control_unit_func = get_function<decltype(MaaAndroidControlUnitCreate)>(create_func_name_);
if (!create_control_unit_func) {
LogError << "Failed to get function create_control_unit";
return nullptr;
}

auto destroy_control_unit_func = get_function<decltype(MaaAndroidControlUnitDestroy)>(destroy_func_name_);
if (!destroy_control_unit_func) {
LogError << "Failed to get function destroy_control_unit";
return nullptr;
}

auto control_unit_handle = create_control_unit_func(screencap_methods, input_methods);

if (!control_unit_handle) {
LogError << "Failed to create control unit";
return nullptr;
}

return std::shared_ptr<MAA_CTRL_UNIT_NS::AndroidControlUnitAPI>(control_unit_handle, destroy_control_unit_func);
}

std::shared_ptr<MAA_CTRL_UNIT_NS::Win32ControlUnitAPI> Win32ControlUnitLibraryHolder::create_control_unit(
void* hWnd,
MaaWin32ScreencapMethod screencap_method,
Expand Down
35 changes: 35 additions & 0 deletions source/MaaAndroidControlUnit/API/AndroidControlUnitAPI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "ControlUnit/AndroidControlUnitAPI.h"

#include <meojson/json.hpp>

#include "MaaUtils/Logger.h"
#include "Manager/AndroidControlUnitMgr.h"

const char* MaaAndroidControlUnitGetVersion()
{
#pragma message("MaaAndroidControlUnit MAA_VERSION: " MAA_VERSION)

return MAA_VERSION;
}

MaaAndroidControlUnitHandle MaaAndroidControlUnitCreate(
MaaAndroidScreencapMethod screencap_methods,
MaaAndroidInputMethod input_methods)
{
using namespace MAA_CTRL_UNIT_NS;

LogFunc << VAR(screencap_methods) << VAR(input_methods);

auto unit_mgr = std::make_unique<AndroidControlUnitMgr>(screencap_methods, input_methods);

return unit_mgr.release();
}

void MaaAndroidControlUnitDestroy(MaaAndroidControlUnitHandle handle)
{
LogFunc << VAR_VOIDP(handle);

if (handle) {
delete handle;
}
}
28 changes: 28 additions & 0 deletions source/MaaAndroidControlUnit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
if(NOT ANDROID)
message(STATUS "MaaAndroidControlUnit skipped: not on Android")
return()
endif()

file(GLOB_RECURSE maa_android_control_unit_src *.h *.hpp *.cpp)
file(GLOB_RECURSE maa_android_control_unit_header ${MAA_PRIVATE_INC}/ControlUnit/AndroidControlUnitAPI.h ${MAA_PRIVATE_INC}/ControlUnit/ControlUnitAPI.h)

add_library(MaaAndroidControlUnit SHARED ${maa_android_control_unit_src} ${maa_android_control_unit_header})

target_include_directories(MaaAndroidControlUnit
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${MAA_PRIVATE_INC} ${MAA_PUBLIC_INC})

target_compile_definitions(MaaAndroidControlUnit PRIVATE MAA_CONTROL_UNIT_EXPORTS)

target_link_libraries(MaaAndroidControlUnit
PRIVATE MaaUtils HeaderOnlyLibraries ${OpenCV_LIBS} log jnigraphics android)

add_dependencies(MaaAndroidControlUnit MaaUtils)

install(
TARGETS MaaAndroidControlUnit
RUNTIME DESTINATION bin
LIBRARY DESTINATION bin
# ARCHIVE DESTINATION lib
)

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${maa_android_control_unit_src})
Loading
Loading