草庐IT

Android 在 Root设备上截取屏幕截图

coder 2023-11-23 原文

更新 还有许多其他帖子询问如何在 android 中获取屏幕截图,但似乎没有一个完整的答案如何做到这一点。最初我将此作为问题发布是由于我在尝试打开帧缓冲区流时遇到的特定问题。现在我已经切换到将帧缓冲区转储到一个文件中,所以我更新了我的帖子以展示我是如何做到这一点的。作为引用(和确认),我找到了将 FrameBuffer 发送到来自 this post 的文件的命令(不幸的是,他没有提供他是如何做到这一点的)。我只是想念如何将从帧缓冲区中提取的原始数据转换为实际的图像文件。

我的目的是完全转储 Android 设备上的实际屏幕。在不使用 adb 桥的情况下,我能找到的唯一方法是直接访问系统的帧缓冲区。显然,这种方法需要设备和运行它的应用程序的 root 权限!幸运的是,出于我的目的,我可以控制设备的设置方式,并且可以使用向我的应用程序提供的 root 权限对设备进行 root 操作。我目前正在运行 2.2.3 的旧 Droid 上进行测试。

我从 https://stackoverflow.com/a/6970338/1446554 中找到了关于如何处理它的第一个提示。 .经过更多研究后,我发现了另一篇描述如何正确使用 run shell commands as root 的文章。 .他们用它来执行重启,我用它来将当前帧缓冲区发送到实际文件。我当前的测试仅通过 ADB 和基本 Activity (每个都提供根)进行。我将通过后台运行的服务进行进一步测试,更新即将到来!这是我可以将当​​前屏幕导出到文件的整个测试 Activity :

public class ScreenshotterActivity extends Activity {
    public static final String TAG = "ScreenShotter";

    private Button _SSButton;
    private PullScreenAsyncTask _Puller;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        _SSButton = (Button)findViewById(R.id.main_screenshotButton);
        _SSButton.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                if (_Puller != null)
                    return;
                //TODO: Verify that external storage is available! Could always use internal instead...

                _Puller = new PullScreenAsyncTask();
                _Puller.execute((Void[])null);
            }
        });
    }

    private void runSuShellCommand(String cmd) {
        Runtime runtime = Runtime.getRuntime();
        Process proc = null;
        OutputStreamWriter osw = null;
        StringBuilder sbstdOut = new StringBuilder();
        StringBuilder sbstdErr = new StringBuilder();

        try { // Run Script
            proc = runtime.exec("su");
            osw = new OutputStreamWriter(proc.getOutputStream());
            osw.write(cmd);
            osw.flush();
            osw.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (osw != null) {
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();                    
                }
            }
        }

        try {
            if (proc != null)
                proc.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        sbstdOut.append(readBufferedReader(new InputStreamReader(proc.getInputStream())));
        sbstdErr.append(readBufferedReader(new InputStreamReader(proc.getErrorStream())));
    }

    private String readBufferedReader(InputStreamReader input) {

        BufferedReader reader = new BufferedReader(input);
        StringBuilder found = new StringBuilder();
        String currLine = null;
        String sep = System.getProperty("line.separator");
        try {
            // Read it all in, line by line.
            while ((currLine = reader.readLine()) != null) {
                found.append(currLine);
                found.append(sep);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    class PullScreenAsyncTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {

            File ssDir = new File(Environment.getExternalStorageDirectory(), "/screenshots");
            if (ssDir.exists() == false) {
                Log.i(TAG, "Screenshot directory doesn't already exist, creating...");
                if (ssDir.mkdirs() == false) {
                    //TODO: We're kinda screwed... what can be done?
                    Log.w(TAG, "Failed to create directory structure necessary to work with screenshots!");
                    return null;
                }
            }
            File ss = new File(ssDir, "ss.raw");            
            if (ss.exists() == true) {
                ss.delete();
                Log.i(TAG, "Deleted old Screenshot file.");
            }
            String cmd = "/system/bin/cat /dev/graphics/fb0 > "+ ss.getAbsolutePath();
            runSuShellCommand(cmd);
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            _Puller = null;
        }
    }
}

这还需要向 list 添加 android.permission.WRITE_EXTERNAL_STORAGE 权限。正如 this post 中的建议.否则它会运行,不会报错,不会创建目录或文件。

最初我无法从帧缓冲区获取可用数据,因为我不了解如何正确运行 shell 命令。现在我已经切换到使用流来执行命令,我可以使用“>”将帧缓冲区的当前数据发送到实际文件...

最佳答案

您可以通过编程方式运行“adb shell/system/bin/screencap -p/sdcard/img.png”,如下所示:

Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream  os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();

关于Android 在 Root设备上截取屏幕截图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10965409/

有关Android 在 Root设备上截取屏幕截图的更多相关文章

  1. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  2. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. ruby-on-rails - 禁用设备的 :confirmable on-the-fly to batch-generate users - 2

    Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation

  5. ruby - 在没有 root 的情况下安装 Jekyll - 2

    我想在共享服务器上建立一个jekyll博客。当我尝试安装Jekyll时,我得到“您没有写权限”。我该如何在没有root或sudo的情况下解决这个问题?更多细节:我在共享服务器上有空间,但没有根访问权限。我无法安装Ruby,尽管托管公司应我的要求安装了它。当我尝试安装Jekyll时我使用user@hosting.org[~]#geminstalljekyll这是我得到的回应:ERROR:Whileexecutinggem...(Gem::FilePermissionError)Youdon'thavewritepermissionsintothe/usr/lib/ruby/gems/1.

  6. ruby-on-rails - Rails 3,在RAILS_ROOT上方显示来自本地文件系统的jpg图片 - 2

    我正在尝试找出一种方法来显示来自不在RAILS_ROOT下(在RedHat或Ubuntu环境中)的已安装文件系统的图像。我不想使用符号链接(symboliclink),因为这个应用程序实际上是通过Tomcat部署的,而当我关闭Tomcat时,Tomcat会尝试跟随符号链接(symboliclink)并删除挂载中的所有图像。由于这些文件的数量和大小,将图像放在public/images下也不是一种选择。我查看了send_file,但它只会显示一张图片。我需要在一个格式良好的页面中显示6个请求的图像。由于膨胀,我宁愿不使用Base64编码,但我不知道如何将图像数据与呈现的页面一起传递下去。

  7. 电脑怎么截图?进来看(8种常用截图方法) - 2

    电脑上可以截取图片吗?如果可以,该如何操作呢?相信很多小伙伴都只知道一两种截图的方式,知道的并不全面。其实,电脑上有多种方式截图的,而且非常方便。电脑怎么截图?今天我们就来教大家如何使用电脑截取图片的8种常用方式!操作环境:演示机型:Delloptiplex7050系统版本:Windows10方法一:系统自带截图具体操作:同时按下电脑的自带截图键【Windows+shift+S】,可以选择其中一种方式来截取图片:截屏有矩形截屏、任意形状截屏、窗口截屏和全屏截图。 方法二:QQ截图具体操作:在电脑登录QQ,然后同时按下【Ctrl+Alt+A】,可以任意截图你需要的界面,可以把截图的页面直接下载,

  8. ruby - 以非 root 用户身份从 ruby​​ 在 Xvfb 中运行 Selenium::WebDriver::Firefox - 2

    我正在尝试使用ruby​​脚本进行一些headless测试。本质上,我在显示器:1上执行Xvfb,然后使用watir-webdriver启动Watir::Browser.new(:firefox)。如果您以root身份运行脚本,效果会很好-我可以运行x11vnc并观察脚本执行浏览器并与之交互。问题是,我需要能够从Rails应用程序调用这个ruby​​脚本,而不是以root身份运行它...如果我尝试以普通用户身份从命令行运行脚本,Xvfb会启动on:1像往常一样,但Watir不会启动浏览器......它最终会在60秒后超时。通过VNC连接会显示带有鼠标光标的黑屏。我可以从命令行完成所有操

  9. ruby - 带有 sinatra 的 Heroku 没有 RAILS_ROOT 或 Rail.root - 2

    我正在尝试将文件上传到amazons3,显然我必须先写入一个临时文件,然后再上传该文件。但是我无法弄清楚如何使用Sinatra和heroku做到这一点,因为它找不到“#{RAILS_ROOT}”或#{Rail.root}如何使用heroku将临时文件上传到sinatra。谢谢 最佳答案 我假设您已经阅读了Heroku的UploadingtoS3文档.Heroku上的临时目录路径是./tmp。如果您运行的是Sinatra,Heroku可能不会创建与Rails相关的环境变量(尽管我不确定是否可能)。Here是关于Heroku文件系统的更

  10. ruby-on-rails - 在服务器端检测屏幕尺寸和像素密度? - 2

    我一直在做一些研究,我想我已经知道答案了,但我想知道是否有任何方法可以在不使用javascript或依赖CSS3媒体的情况下获得设备的屏幕尺寸和像素密度查询。本质上,我正在研究如何获取屏幕分辨率和像素密度,以便服务器可以决定在URI请求中为服务器提供哪个图像。到目前为止,我还没有发现任何证据表明这是可能的,但我想嘿,为什么不问问呢? 最佳答案 我不完全同意上面的正确答案。实际上,这个答案在很多情况下都是正确的……但理论上并非如此。通常向Web服务器发出的请求包含一个User-Agent字段,从理论上讲,该字段可用于识别有关设备屏幕分

随机推荐