Android根植设备上截屏

更新还有一些其他post要求如何在android中获得截图,但似乎没有一个完整的答案如何做到这一点。 最初,由于在尝试打开帧缓冲区stream时遇到的特定问题,我将其作为问题发布。 现在我已经交换了帧caching到一个文件,所以我已经更新了我的post,以显示我如何到达那里。 为了引用(和确认),我发现了从这个post发送FrameBuffer到一个文件的命令(不幸的是,他没有提供如何到达这一点)。 我只是想知道如何将我从帧缓冲区中提取的原始数据转换成实际的图像文件。

我的意图是在Android设备上完整转换实际屏幕。 我不能使用adb网桥的唯一方法是直接访问系统的帧缓冲区。 显然,这种方法将需要设备上的root权限和运行它的应用程序! 幸运的是,为了我的目的,我已经控制了设备的设置方式,并且使用为我的应用程序提供的权限设备是可行的。 我的testing目前正在运行2.2.3的旧Droid上完成。

我从https://stackoverflow.com/a/6970338/1446554find了我的第一个提示。 在进行了更多的研究之后,我发现了另一篇文章,介绍了如何以root身份正确运行shell命令 。 他们正在使用它来执行重新启动,我用它来发送当前帧缓冲区到一个实际的文件。 我目前的testing只能通过ADB和基本的Activity(每个都是根用户)来完成。 我会做一个在后台运行的服务进一步testing,更新来! 这是我的整个testing活动,可以导出当前屏幕到一个文件:

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

这也需要在Manifest中添加android.permission.WRITE_EXTERNAL_STORAGE权限。 正如在这篇文章中build议的 。 否则它运行,不抱怨,不创build目录和文件。

本来我不能从帧缓冲区获取可用数据,因为不了解如何正确运行shell命令。 现在,我已经交换到使用stream执行命令我可以使用'>'发送帧缓冲区的当前数据到一个实际的文件…

Solutions Collecting From Web of "Android根植设备上截屏"

这对于不同的手机会有所不同。 这取决于设备的底层graphics格式。 您可以使用系统调用来查询graphics格式。 如果你只打算在设备上运行这个程序,那么你就知道你的graphics格式可以编写一个转换器,将它转换成已知的格式。

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

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

我希望这有帮助。

以编程方式,你可以运行“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(); 

ICS设备的简单解决scheme是从命令行使用以下命令

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

这会将screenshot.png文件保存在当前目录中。

在运行4.0.3的Samsung Galaxy SII上testing。