Xamarin-Android 中的屏幕捕获问题

问题描述

我已经创建了一个程序来捕获我的设备的屏幕。 该程序包括 2 部分。主类和服务类。捕获操作在服务类中进行。 我必须通过 Dependency Service 将 Main Activity 上下文发送到服务类。 这是 MainActivity 类:

     protected override void OnCreate(Bundle savedInstanceState)
        {
            Xamarin.Forms.Forms.Init(this,savedInstanceState);
            Xamarin.Forms.DependencyService.Register<A_Service.ScreenshotService>();
            Xamarin.Forms.DependencyService.Get<A_Service.ScreenshotService>().SetActivity(this);
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this,savedInstanceState);
            SetContentView(Resource.Layout.activity_main);
            StartRecordButton = (Button)FindViewById(Resource.Id.btnStartRecord);
            StopRecordButton = (Button)FindViewById(Resource.Id.btnStopRecord);

            StartRecordButton.Click += (sender,e) => {
                StartService(intent);
            };
            StopRecordButton.Click += (sender,e) => {
                StopService(intent);
            };

            Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);

            intent = new Intent(this,typeof(A_Service));
        }

这里是服务类:

    namespace AndroidService
{
    [Service]
    public class A_Service : Android.App.Service
    {
        private interface IScreenshotService
        {
            byte[] Capture();
        }

        public class ScreenshotService : IScreenshotService,Idisposable
        {
            public Activity _currentActivity;

            public void SetActivity(Activity activity)
            {
                _currentActivity = activity;
            }
            public byte[] Capture()
            {
                Android.Views.View rootView;
                rootView= _currentActivity.Window.DecorView.RootView;
                using (var screenshot = Bitmap.CreateBitmap(rootView.Width,rootView.Height,Bitmap.Config.Argb8888))
                {
                    var canvas = new Canvas(screenshot);
                    rootView.Draw(canvas);
                    using(var stream=new MemoryStream())
                    {
                        screenshot.Compress(Bitmap.CompressFormat.Png,90,stream);
                        return stream.ToArray();
                    }
                }  
            }

            public void dispose()
            {
                this.dispose();
            }
        }

        public override void OnCreate()
        {
            Toast.MakeText(this,"Service is created ...",ToastLength.Long).Show();
        }

        [return: GeneratedEnum]
        public override StartCommandResult OnStartCommand(Intent intent,[GeneratedEnum] StartCommandFlags flags,int startId)
        {
            Toast.MakeText(this,"سرویس استارت شد",ToastLength.Short).Show();
           
            Task.Run(() =>
            {
                StartCapturing();
            });
            return StartCommandResult.Sticky;
        }

        protected void StartCapturing()
        {
            bool d = true;
            int StartSecond = DateTime.Now.Hour * 3600 + DateTime.Now.Minute * 60 + DateTime.Now.Second;
            int StopSecond;
            using(var snpshot=new ScreenshotService())
            {
                var sShot = snpshot.Capture();
                SavePhoto(sShot);
            }

            while (d)
            {
                StopSecond = DateTime.Now.Hour * 3600 + DateTime.Now.Minute * 60 + DateTime.Now.Second;
                int secDiff = System.Math.Abs(StopSecond - StartSecond);
                if (secDiff == 5) d = false;
            }
        }
        
        public bool SavePhoto(byte[] data)
        {
            string filePath = FullPath("Image");
            try
            {
                using (FileOutputStream bitmapFile = new FileOutputStream(filePath))
                {
                    var buffer = ByteBuffer.Allocate(data.Length);
                    //fos.Write(new byte[buffer.Remaining()]); 
                    byte[] bmpData = new byte[data.Length];
                    buffer.Position(0); //or buffer.Flip();
                    buffer.Get(bmpData,buffer.Remaining());
                    bitmapFile.Write(bmpData);
                    bitmapFile.Close();
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}

问题是在运行程序并启动服务后,在Capture方法的Service类的第二行,“_currentActivity”的值变为NULL。(“ScreenshotService”类)

解决方法

使用 DependencyService 时,接口应该在共享项目中创建,不要在类中创建接口。请为接口设置 <link rel="stylesheet" href="../css/bootstrap.min.css"> 关键字,以便它可以在本机平台上使用。

如何使用DependencyService,可以按照以下步骤:

1.在共享项目中创建接口

<script src="../js/someFile.js"></script>

2.在各个平台上实现接口注册平台实现。

public

2.然后消费共享项目中的函数。

namespace AndroidService
{
    public interface IScreenshotService
    {
        byte[] Capture();
    }
}

检查文档:
DependencyService IntroductionDependencyService Registration and Resolution