根设备上的Android截屏(Android take screenshot on rooted d

2019-06-25 09:11发布

UPDATE有一些其他的帖子,询问如何获取截图中的Android,但没有似乎对如何做一个完整的答案的。 本来我张贴这是一个问题,因为我也陷入了试图打开一个流的帧缓冲区中的具体问题。 现在我换过来,所以我已经更新了我的职务,以显示我是如何到达那里倾销帧缓冲到一个文件中。 仅供参考(和确认),我发现命令帧缓冲区从发送到文件这个职位 (遗憾的是他没有提供他是怎么到这一点)。 我只是缺少如何将我从帧缓冲器拉着原始数据转化为实际的图像文件。

我的目的是采取实际屏幕完全转储上的Android设备。 我能找到不使用亚行桥这样做的唯一方法是直接访问系统的帧缓冲。 显然,这种做法将需要运行在设备上和应用程序root权限! 幸运的是我的目的,我有过的设备是如何设置的,并具有与扎根提供给我的应用程序root权限的设备是可行的控制。 我的测试,目前正在对旧的Droid运行2.2.3完成。

我发现我如何从接近它首先提示https://stackoverflow.com/a/6970338/1446554 。 更多的研究后,我发现另一篇文章,描述了如何正确地运行shell命令为根 。 他们用它来执行重新启动,我用它来将当前帧缓冲器发送到一个实际的文件。 我的当前测试已经仅就得到经由ADB这样做的,在碱性活性(各设置根目录)。 我会做在后台运行的服务进行进一步的测试,更新的到来吧! 这是我可以在当前屏幕导出到文件整个测试活动:

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;
        }
    }
}

这也需要添加android.permission.WRITE_EXTERNAL_STORAGE权限的清单。 作为建议在这个职位 。 否则,它运行时,不抱怨,不创建目录,也没有文件。

本来我无法从帧缓冲器由于不了解如何正确运行shell命令得到有用的数据。 现在,我已经换用流执行的命令,我可以用“>”来缓冲当前发送数据帧到实际文件...

Answer 1:

这将是不同的手机不同。 这取决于你的设备的底层图形格式。 你可以查询一下图形格式是使用系统调用。 如果你只打算在你知道你的图形格式,可以写一个转换器,把它变成一个已知的格式的设备上运行此。

你可以看看以下项目: http://code.google.com/p/android-fb2png/

如果你看一下fb2png.c的源代码,你可以看到,他们轮询FBIOGET_VSCREENINFO其中包含有关设备的内存中如何存储的屏幕图像信息。 一旦你知道,你应该能够将其转换成可以使用的格式。

我希望这有帮助。



Answer 2:

编程可以参考以下运行“亚行外壳/系统/斌/撷取画面-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();


Answer 3:

对于ICS设备的简单的解决方案是使用下面的命令行

adb shell /system/bin/screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png screenshot.png

这将节省的screenshot.png文件在当前目录中。

经测试在三星Galaxy SII运行4.0.3。



文章来源: Android take screenshot on rooted device