来自后台应用程序

时间:2016-10-18 05:07:28

标签: c# ios xamarin bitmap

对于 jailbroken iOS-Device 上的私有应用(=不在任何appstore上发布),我需要将整个屏幕的屏幕截图发送到背景。

已发布类似问题

以下是我的代码的帖子。我正在寻求有关private System.Drawing.Bitmap ShootScreen()

实施的帮助
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;

namespace StackOverflowSnippets
{
    public sealed class ScreenshooterThread
    {
        private Thread _t = null;                   // Thread-Object: Execution-Helper
        private Boolean _terminate = false;         // Stop current execution?
        private Int32 _intervalMS = 0;              // Take Screenshots every ? MS
        private Queue<Bitmap> _q;                   // Queue to store the Screenshots

        #region Interface
        /// <summary>
        /// Creates a Screenshooter
        /// </summary>
        /// <param name="intervalMS">Defines every how many MS a screenshot should be taken</param>
        public ScreenshooterThread(Int32 intervalMS = 200)
        {
            _intervalMS = intervalMS;
        }

        /// <summary>
        /// Starts taking Screenshots
        /// </summary>
        public void Run()
        {
            if(this.IsRunning || this.IsTerminating)
            {
                throw new InvalidOperationException("ScreenshooterThread is currently running or terminating");
            }

            lock (this)
            {
                _terminate = false;
                _t = new Thread(this.DoWork);
                _t.Start();
            }
        }

        /// <summary>
        /// Stops taking Screenshots
        /// </summary>
        public void Stop()
        {
            if (!this.IsRunning) return; if (this.IsTerminating) return;

            lock(this)
            {
                _terminate = true;
            }
        }

        /// <summary>
        /// Determines whether the Thread is currently running
        /// </summary>
        public Boolean IsRunning
        {
            get
            {
                if (_t == null) return false;

                return _t.IsAlive;
            }
        }
        /// <summary>
        /// Determines whether Thread-Termination has been invoked
        /// </summary>
        public Boolean IsTerminating
        {
            get
            {
                return _terminate;
            }
        }

        /// <summary>
        /// Get a Screenshot from the Queue. Returns null if none available
        /// </summary>
        public Bitmap Deqeue()
        {
            lock(_q)
            {
                if (_q.Count < 1) return null;
                return _q.Dequeue();
            }
        }

        #endregion

        #region Implementation Details
        /// <summary>
        /// Add a Screenshot to the Queue
        /// </summary>
        private void Enqueue(Bitmap b)
        {
            lock(_q)
            {
                _q.Enqueue(b);
            }
        }

        /// <summary>
        /// Task-Implementation while running
        /// </summary>
        private void DoWork()
        {
            while(!_terminate)
            {
                if (_intervalMS > 0) Thread.Sleep(_intervalMS);

                this.Enqueue(this.ShootScreen());
            }

            this.CleanUp();
        }

        /// <summary>
        /// Takes a Screenshot of the device even if the app is in the Background
        /// </summary>
        private System.Drawing.Bitmap ShootScreen()
        {
            // System.Drawing.Bitmap supported by Xamarin
            // https://developer.xamarin.com/api/type/System.Drawing.Bitmap/

            // Method in ObjC: https://stackoverflow.com/questions/33369014/how-to-take-screenshot-of-entire-screen-on-a-jailbroken-ios-device

            throw new NotImplementedException();
        }
        /// <summary>
        /// Preparing for next launch
        /// </summary>
        private void CleanUp()
        {
            lock(this)
            {
                _terminate = false;
                _t = null;
            }
        }
        #endregion
    }
}

PS:屏幕截图必须是System.Drawing.Bitmap,因为我之后需要对它执行Pixelwise操作

编辑1

经过进一步调查,我在http://sharpmobilecode.com/introduction-to-xamarin-what-it-is-what-it-isnt/上找到了以下段落

  

例如,假设您使用的是现有的C#代码   System.Drawing.Bitmap。这是一个你写的多个常见的库   桌面应用参考。一种可能的方法如下所示:

using System.Drawing; 

public Bitmap GetBitmapFromCache(string fileName) 
{ 
   return (Bitmap) Image.FromFile(fileName); 
}    
     

如果您要在Xamarin.iOS或Xamarin.Android应用程序中编译此方法,则会出现编译错误。咦?上   进一步调查,你会看到System.Drawing.Bitmap和。{   System.Drawing.Image未定义。什么!?!?这是有效的C#   句法!经过进一步调查,你只能看到几个班级   实际定义了System.Drawing(RectangleF,PointF等)。哪里   哎呀是Bitmap和Image?嗯,这是有充分理由的   类在Mono Framework中没有实现。这是因为他们   不是跨平台兼容的。

     

这究竟是什么意思?我们来看看System.Drawing   MSDN上的文档。它声明,“System.Drawing命名空间   提供对GDI +基本图形功能的访问。“什么是GDI +?   GDI +(图形设备接口)是一个图形库(Win32)   特定于Windows操作系统。所以在一个引擎盖下面   System.Drawing.Bitmap是一个绑定到的Win32实现   Windows桌面/服务器操作系统。这意味着   System.Drawing.Bitmap和System.Drawing.Image是平台相关的,   并且只适用于Windows桌面/服务器应用程序。你将无法做到   在iOS应用,Android应用甚至Windows Phone上使用这些类   应用。那么如何在iOS或Android中使用当前的C#代码呢?   应用程序吗?稍作修改:

public byte[] GetBitmapFromCache(string fileName) 
{ 
    return File.ReadAllBytes(fileName); 
} 
     

iOS和Android没有GDI +位图的概念   (System.Drawing.Bitmap),但是,每个平台都知道如何转换   将一个字节数组放入自己的位图实现中。运用   iOS,你可以从一个字节数组和Android中创建一个UIImage   你可以从同一个数组创建一个Android.Graphics.Bitmap。

1 个答案:

答案 0 :(得分:0)

http://sharpmobilecode.com/introduction-to-xamarin-what-it-is-what-it-isnt/所述,无法创建System.Drawing.Bitmap,因为System.Drawing命名空间可以访问特定于Windows操作系统的GDI +基础图形功能,因此根本无法使用在iOS上。

然而,可以将屏幕截图创建为UIImage,如下所示

  1. How to take screenshot of entire screen on a Jailbroken iOS Device?显示,存在一个返回所需屏幕截图的私有函数_UICreateScreenUIImage(void)。要访问此函数,必须声明它

    using System.Runtime.InteropServices;
    using ObjCRuntime;
    
    [DLLImport(/*ObjCRuntime.*/Constants.UIKitLibrary)]
    extern static IntPtr _UICreateScreenUIImage();
    
  2. 调用时,返回的IntPtr指向本机UIImage,需要将其包装到托管对象中,由Runtime.GetNSObject(IntPtr)

    完成
    IntPtr ptr = _UICreateScreenUIImage();
    UIImage uiimg = Runtime.GetNSObject(ptr) as UIImage;
    

    生成的uiimg包含屏幕截图

  3. 附图包含有关如何创建屏幕截图并将其另存为.jpeg

    的简约示例

    Minimalistic example on how to create and save a screenshot

    当应用在后台时,屏幕截图可能会是什么样子

    Picture of what a screenshot looks like