繁体   English   中英

Xamarin Android 截屏

[英]Xamarin Android take screenshot

我正在做一个绘图项目。

我不使用 axml,因为我在一个名为 fillpolygon 的类中进行绘图并在 MainActivity 中调用该函数。 我只想在我的项目中截取屏幕截图。 是否有任何基本功能,我可以在 onCreate 方法中调用? 所以,当程序运行时,它会自动截屏。 我找到了除 Xamarin 平台之外的答案。

由于 Android 28 DrawingCacheEnabled已被弃用,如果没有它,我们将强制我们的视图在我们的自定义画布上重绘,这可能会导致自定义控件和渲染器出现伪影,并且屏幕截图版本可能与我们在屏幕上看到的不同。

仍在处理简单情况的遗留代码是:

  public byte[] CaptureScreenshot()
    {
        var view=
            Xamarin.Essentials.Platform.CurrentActivity.Window.DecorView.RootView;

       if (view.Height < 1 || view.Width < 1)
            return null;

        byte[] buffer = null;

        view.DrawingCacheEnabled = true;

        using (var screenshot = Bitmap.CreateBitmap(
            view.Width,
            view.Height,
            Bitmap.Config.Argb8888))
        {
            var canvas = new Canvas(screenshot);


            view.Draw(canvas);

            using (var stream = new MemoryStream())
            {
                screenshot.Compress(Bitmap.CompressFormat.Png, 90, stream);
                buffer = stream.ToArray();
            }
        }

        view.DrawingCacheEnabled = false;

        return buffer;

    }

使用上面的遗留方法如下

  if ((int)Android.OS.Build.VERSION.SdkInt < 28)
    {
        //legacy
    }

DrawingCacheEnabled过时警告将我们重定向到使用PixelCopy 此方法与回调一起使用,因此要同步使用它已经做了一些帮助:

用法:

    public byte[] CaptureScreenshot()
    {
        using var helper = new ScreenshotHelper(
            Xamarin.Essentials.Platform.CurrentActivity.Window.DecorView.RootView,
            Xamarin.Essentials.Platform.CurrentActivity);

        byte[] buffer = null;
        bool wait = true;

        Task.Run(async () =>
        {
            helper.Capture((Bitmap bitmap) =>
            {
                try
                {

                    if (!helper.Error)
                    {
                        using (var stream = new MemoryStream())
                        {
                            bitmap.Compress(Bitmap.CompressFormat.Png, 90, stream);
                            buffer = stream.ToArray();
                        }
                    }

                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
                finally
                {
                    wait = false;
                }
            });

        }).ConfigureAwait(false);


        while (wait)
        {
            Task.Delay(10).Wait();
        }

        return buffer;
    }

帮手:

    public class ScreenshotHelper : Java.Lang.Object, PixelCopy.IOnPixelCopyFinishedListener
    {


        public void OnPixelCopyFinished(int copyResult)
        {
            var stop = true;
            if (copyResult == (int) PixelCopyResult.Success)
            {
                Error = false;
                //todo CallbackGotScreenshot();
                _callback(_bitmap);
            }
            else
            {
                Error = true;
            }

            _callback(_bitmap);

        }

        public bool Error { get; protected set; }

        public ScreenshotHelper(Android.Views.View view, Activity activity)
        {
            _view = view;
            _activity = activity;

            _bitmap = Bitmap.CreateBitmap(
                _view.Width,
                _view.Height,
                Bitmap.Config.Argb8888);
        }

        // Starts a background thread and its {@link Handler}.
        private void StartBackgroundThread()
        {
            _BackgroundThread = new HandlerThread("ScreeshotMakerBackground");
            _BackgroundThread.Start();
            _BackgroundHandler = new Handler(_BackgroundThread.Looper);
        }

        // Stops the background thread and its {@link Handler}.
        private void StopBackgroundThread()
        {
            try
            {
                _BackgroundThread.QuitSafely();
                _BackgroundThread.Join();
                _BackgroundThread = null;
                _BackgroundHandler = null;
            }
            catch (Exception e)
            {
                //e.PrintStackTrace();
            }
        }

        public void Capture(Action<Bitmap> callback)
        {
            //var locationOfViewInWindow = new int[2];
            //_view.GetLocationInWindow(locationOfViewInWindow);
            _callback = callback;

            try
            {
                StartBackgroundThread();
                //todo could create-use background handler
                PixelCopy.Request(_activity.Window, _bitmap, this,
                    _BackgroundHandler);


            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                Task.Run(StopBackgroundThread);
            }
        }

        private Android.Views.View _view;
        private Activity _activity;
        private Bitmap _bitmap;
        private HandlerThread _BackgroundThread;
        private Handler _BackgroundHandler;
        private Action<Bitmap> _callback;


        public new void Dispose()
        {
            _bitmap?.Dispose();
            _bitmap= null;
            _activity = null;
            _view = null;
            _callback = null;

            base.Dispose();
        }

    }

在您的视图中,您可以运行以下代码来截取屏幕截图。 我之前没有尝试在OnCreate()运行它,因此您可能需要对其进行测试以确保视图已完全呈现。

*编辑:根据这篇文章,您可能无法在OnCreate()运行此代码,因此您需要找到一个更好的地方。 我无法弄清楚用户在他发布的链接中指的是什么帖子。

*编辑#2:刚刚发现Compress()没有考虑质量参数(在下面列出为0 ),因为 PNG 是无损的,但是如果您将格式更改为 JPEG 例如,那么您可能想要提高质量参数,因为您的图像看起来像垃圾。

public byte[] SaveImage() {

    DrawingCacheEnabled = true;                  //Enable cache for the next method below
    Bitmap bitmap       = GetDrawingCache(true); //Gets the image from the cache

    byte[] bitmapData;
    using(MemoryStream stream = new MemoryStream()) {
        bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
        bitmapData = stream.ToArray();
    }

    return bitmapData;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM