Android - 如何以编程方式截取屏幕截图

时间:2013-11-22 02:52:35

标签: java android

当我的应用程序安装并在后台运行200毫秒时,我需要以编程方式截取Android设备或模拟器,并将图像保存在我的计算机中。我已使用下面的代码实现了此过程,仅在我的应用程序位于前台时才有效。当我的应用程序也在后台时,我想截取屏幕截图。以下是我的代码:

public static Bitmap takeScreenshot(Activity activity, int ResourceID) { 
    Random r = new Random();
    int iterator=r.nextInt();   
     String mPath = Environment.getExternalStorageDirectory().toString() + "/screenshots/";
    View v1 = activity.getWindow().getDecorView().findViewById(ResourceID);
    v1.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    v1.layout(0, 0, v1.getMeasuredWidth(), v1.getMeasuredHeight()); 
    v1.setDrawingCacheEnabled(true);
    final Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
    Bitmap resultBitmap = Bitmap.createScaledBitmap(bitmap, 640, 480, false);
    v1.setDrawingCacheEnabled(false);
    File imageFile = new File(mPath);
    imageFile.mkdirs();
    imageFile = new File(imageFile+"/"+iterator+"_screenshot.png");
    try {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        resultBitmap.compress(CompressFormat.PNG, 100, bos);
        byte[] bitmapdata = bos.toByteArray();

        //write the bytes in file
        FileOutputStream fos = new FileOutputStream(imageFile);
        fos.write(bitmapdata);
        fos.flush();
        fos.close();    
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bitmap;
    }  

如何以编程方式在Devices -> DDMS中实现Screencapture的“刷新”和“保存”按钮的功能?我可以实现吗?

5 个答案:

答案 0 :(得分:17)

如果您的手机已植根,请尝试使用

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();

然后将img.png作为位图读取并将其转换为jpg如下

Bitmap screen = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+         
File.separator +"img.png");

//my code for saving
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    screen.compress(Bitmap.CompressFormat.JPEG, 15, bytes);

//you can create a new file name "test.jpg" in sdcard folder.

File f = new File(Environment.getExternalStorageDirectory()+ File.separator + "test.jpg");
            f.createNewFile();
//write the bytes in file
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
// remember close de FileOutput

    fo.close();

如果您的应用程序处于后台,除非您扎根,否则您无权访问该屏幕,即使您在后台,上面的代码也可以最有效地截取屏幕截图。

<强>更新

谷歌有一个图书馆,你可以用它来截取而不需要生根,我试过了,但我确信它会尽快消耗内存。

尝试http://code.google.com/p/android-screenshot-library/

答案 1 :(得分:13)

这是做到这一点的方法。

Android taking Screen shots through code

结果输出:

enter image description here

enter image description here

public class CaptureScreenShots extends Activity {
    LinearLayout L1;
    ImageView image;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.screen_shots);
         L1 = (LinearLayout) findViewById(R.id.LinearLayout01);
            Button but = (Button) findViewById(R.id.munchscreen);
            but.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    View v1 = L1.getRootView();
                    v1.setDrawingCacheEnabled(true);
                    Bitmap bm = v1.getDrawingCache();
                    BitmapDrawable bitmapDrawable = new BitmapDrawable(bm);
                    image = (ImageView) findViewById(R.id.screenshots);
                    image.setBackgroundDrawable(bitmapDrawable);
                }
            });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.screen_shots, menu);
        return true;
    }

}

答案 2 :(得分:4)

在后台拍摄屏幕截图(如ADB)需要 groups = 1003(图形)。否则,您只能获得自己进程的屏幕截图。因此,您只能在root设备上执行此操作,或者通过运行ADB本机程序来执行此操作。

可以在https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r2.3/cmds/screencap/

找到原生cpp代码示例

如果你想在java代码中这样做,你需要访问Surface类的隐藏API:

/**
 * Like {@link #screenshot(int, int, int, int)} but includes all
 * Surfaces in the screenshot.
 *
 * @hide
 */
public static native Bitmap screenshot(int width, int height);

这两个应该都可以,因为ICS发布,对于早期版本,如GB,你可以查看本机cpp代码。

但是,在某些Android设备中,媒体系统和画布等的实现并不是很好,因此,在这种情况下,您无法捕获任何视频播放或任何表面视图内容。

答案 3 :(得分:0)

您可以考虑将MediaProjectionAccessibilityService混合使用。第一个轻松获取屏幕截图,第二个始终在所有应用“之上”运行

教程如何在CODELABS中运行k <- {tmp <- table(x); names(tmp)[order(tmp, decreasing = TRUE)]} k [1] "pen" "banana" "apple" "desk"

上述HERE的全部来源

THIS答案中,您可以找到AccessibilityService的非常有用的代码。记住要设置适当的完全透明的Activity

Theme

然后根据需要在您的<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.NoActionBar"> <item name="android:background">#00000000</item> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@null</item> </style> 中循环startActivity,甚至更好-使用AccessibilityService通知LocalBroadcastManager Service截屏并完成(因此Activity可以再次启动此Service

我做过类似的事情(仅供内部使用)+屏幕截图已通过OCR分析,以从中获取文本。 Kinda解析,当非您的应用以某种方式抵御Activity功能(这种AccesibilityService类型旨在帮助残疾人,例如在阅读文本时,通常可以访问Service))< / p>

答案 4 :(得分:-1)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="select1" id="select1">
    <option value="1">Fruit</option>
    <option value="2">Animal</option>
    <option value="3">Bird</option>
    <option value="4">Car</option>
</select>

<div id="selsear">
</div>

将此方法添加到按钮单击事件或选项菜单项选择事件中,屏幕截图将存储在“下载”文件夹中,因为在private void takeScreenshot() throws IOException { Date now = new Date(); android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now); String fileName = now + ".jpg"; try { File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + ""); folder.mkdirs(); //create directory // create bitmap screen capture View v1 = getWindow().getDecorView().getRootView(); v1.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache()); v1.setDrawingCacheEnabled(false); File imageFile = new File(folder, fileName); imageFile.createNewFile(); FileOutputStream outputStream = new FileOutputStream(imageFile); int quality = 100; bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream); outputStream.flush(); outputStream.close(); Toast.makeText(MainActivity.this, "ScreenShot Captured", Toast.LENGTH_SHORT).show(); MediaScannerConnection.scanFile(this, new String[]{imageFile.toString()}, null, new MediaScannerConnection.OnScanCompletedListener() { public void onScanCompleted(String path, Uri uri) { Log.i("ExternalStorage", "Scanned " + path + ":"); Log.i("ExternalStorage", "-> uri=" + uri); } }); } catch (Throwable e) { // Several error may come out with file handling or OOM e.printStackTrace(); } } 变量中我提供了下载路径,您可以更改文件夹路径。文件添加写入权限

folder