获取具有root权限的Android上当前前台应用的屏幕截图

时间:2014-12-30 19:13:22

标签: android android-activity android-service android-view android-screen-support

我正在开发一个安装在系统分区上的应用程序,我想知道是否可以从服务获取当前前台应用程序的屏幕截图。当然,该应用程序是任何第三方应用程序。

我对安全问题或与此事无关的任何事情都不感兴趣。我只想获得当前前景第三方应用的快照。

注意:我了解/system/bin/screencap解决方案,但我正在寻找一种更优雅的替代方案,以编程方式完成所有工作。

2 个答案:

答案 0 :(得分:2)

我将在下面介绍的方法将允许您以编程方式从后台进程中截取前景中任何应用的屏幕截图。

我假设你有一个root设备。 在这种情况下,您可以使用uiautomator framework来完成工作。

这个框架已经被创建用于自动化Android上的应用程序的黑盒测试,但它也将适用于此目的。 我们将使用方法

takeScreenshot(File storePath, float scale, int quality)

这是服务类:

File f = new File(context.getApplicationInfo().dataDir, "test.jar");

//this command will start uiautomator
String cmd = String.format("uiautomator runtest %s -c com.mypacket.Test", f.getAbsoluteFile());
Process p = doCmds(cmd);
if(null != p)
{
    p.waitFor();
}
else
{
    Log.e(TAG, "starting the test FAILED");
}

private Process doCmds(String cmds)
{
    try
    {
        Process su = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(su.getOutputStream());

        os.writeBytes(cmds + "\n");
        os.writeBytes("exit\n");
        os.flush();
        os.close();

        return su;
    }
    catch(Exception e)
    {
        e.printStackTrace();
        Log.e(TAG, "doCmds FAILED");

        return null;
    }
}

这是uiautomator的课程:

public class Test extends UiAutomatorTestCase
{
    public void testDemo()
    {
        UiDevice dev = UiDevice.getInstance();

        File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
        dev.takeScreenshot(f, 1.0, 100);
    }
}

如果您创建一个uiautomator将运行的后台线程,那将是最好的,这样它就不会运行到ui线程上。 (服务在ui线程上运行。)

uiatuomator不了解或拥有Android上下文。 一旦uiautomator获得控件,你就可以在其中调用不带上下文参数或属于上下文类的android方法。

如果您需要在uiautomator和服务(或其他Android组件)之间进行通信,您可以使用LocalSocket。 这将允许双向沟通。

答案 1 :(得分:1)

自从我提出这个问题以来已经过了几个月但是现在有时间添加此功能。这样做的方法只需调用screencap -p <file_name_absolute_path>然后抓取文件即可。接下来是我使用的代码:

private class WorkerTask extends AsyncTask<String, String, File> {
    @Override
    protected File doInBackground(String... params) {
        File screenshotFile = new File(Environment.getExternalStorageDirectory().getPath(), SCREENSHOT_FILE_NAME);
        try {
            Process screencap = Runtime.getRuntime().exec("screencap -p " + screenshotFile.getAbsolutePath());
            screencap.waitFor();
            return screenshotFile;
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(File screenshot_file) {
        // Do something with the file.
    }
}

请记住向清单添加<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />权限。否则screenshot.png将为空白。

这比Goran所说的要简单得多,也是我最终使用的。

注意:只有在系统分区上安装了应用程序时,它才对我有用。