You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# MAUI Android:借助无障碍服务实现全局截图遇阻

解决.NET MAUI Android无障碍服务全屏截图问题

核心问题说明

Screenshot.Default.CaptureAsync()仅能截取当前应用界面,要实现全屏截图需通过无障碍服务的TakeScreenshot方法,关键是正确实现ITakeScreenshotCallback接口,避免类型转换异常。

实现步骤

1. 实现ITakeScreenshotCallback接口

在C#中创建类实现该接口,需严格匹配Android原生接口的方法签名:

public class ScreenshotCallback : Java.Lang.Object, ITakeScreenshotCallback
{
    private readonly Action<Bitmap> _onSuccess;
    private readonly Action<int> _onFailure;

    public ScreenshotCallback(Action<Bitmap> onSuccess, Action<int> onFailure)
    {
        _onSuccess = onSuccess;
        _onFailure = onFailure;
    }

    public void OnSuccess(ScreenshotResult screenshotResult)
    {
        // 将硬件缓冲区转换为Bitmap
        using var hardwareBuffer = screenshotResult.HardwareBuffer;
        using var colorSpace = screenshotResult.ColorSpace;
        var fullScreenBitmap = Bitmap.WrapHardwareBuffer(hardwareBuffer, colorSpace);

        // 裁剪截图(示例参数,按需调整)
        var croppedBitmap = Bitmap.CreateBitmap(fullScreenBitmap, 39, 498, 1002, 1002);

        _onSuccess?.Invoke(croppedBitmap);

        // 弹出成功提示
        Toast.MakeText(Android.App.Application.Context, "截图成功", ToastLength.Long).Show();
    }

    public void OnFailure(int errorCode)
    {
        _onFailure?.Invoke(errorCode);

        // 弹出失败提示
        Toast.MakeText(Android.App.Application.Context, $"截图失败,错误码:{errorCode}", ToastLength.Long).Show();
    }
}

2. 在无障碍服务中调用TakeScreenshot

重写无障碍服务的事件处理方法,在合适时机触发截图:

public class MyAccessibilityService : AccessibilityService
{
    public override void OnAccessibilityEvent(AccessibilityEvent e)
    {
        // 示例:监听窗口状态变化事件触发截图
        if (e.EventType == EventTypeWindowStateChanged)
        {
            TakeScreenshot(
                Display.DefaultDisplay,
                Android.App.Application.Context.MainExecutor,
                new ScreenshotCallback(OnScreenshotSuccess, OnScreenshotFailure)
            );
        }
    }

    private void OnScreenshotSuccess(Bitmap bitmap)
    {
        // 处理截图,例如保存到本地
        SaveBitmapToFile(bitmap);
        bitmap.Recycle(); // 及时释放Bitmap资源
    }

    private void OnScreenshotFailure(int errorCode)
    {
        // 记录失败日志
        Android.Util.Log.Debug("SCREENSHOT", $"截图失败,错误码:{errorCode}");
    }

    private void SaveBitmapToFile(Bitmap bitmap)
    {
        var savePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "full_screenshot.jpg");
        using var stream = new FileStream(savePath, FileMode.Create);
        bitmap.Compress(Bitmap.CompressFormat.Jpeg, 90, stream);
    }

    public override void OnInterrupt()
    {
        // 服务中断时的处理逻辑
    }
}

3. 关键配置与注意事项

  • API版本要求:TakeScreenshot是Android 12(API 31)及以上版本的API,需确保项目目标SDK版本≥31。
  • 无障碍服务启用:用户必须在系统设置中手动启用你的应用的无障碍服务,否则无法调用截图方法。
  • 权限配置:在AndroidManifest.xml中声明无障碍服务权限:
<service android:name=".MyAccessibilityService"
         android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data android:name="android.accessibilityservice"
               android:resource="@xml/accessibility_service_config" />
</service>

同时在Resources/xml/accessibility_service_config.xml中开启截图权限:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canTakeScreenshot="true"
    android:description="@string/accessibility_service_description" />

内容的提问来源于stack exchange,提问作者Nathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:04:55