Android - Как сделать скриншот программным

Мне нужно скриншоты Android-устройства или эмулятора программно, когда мое приложение установлено и работает в фоновом режиме каждые 200 миллисекунд и сохраняет изображения на моем компьютере. Я выполнил эту процедуру, используя приведенный ниже код, и работает только тогда, когда мое приложение находится на переднем плане. Я хочу делать скриншоты, когда мое приложение также находится в фоновом режиме. Ниже мой код:

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

Как я могу реализовать функциональность кнопок Refresh и Save Screencapture в Devices -> DDMS программно? Могу ли я достичь этого?

Ответы

Ответ 1

Если ваш телефон укоренен, попробуйте это

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 как bitmap и преобразуйте его в 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();

у вас нет доступа к экрану, если ваше приложение находится в фоновом режиме, если вы не внедрены, приведенный выше код может сделать снимок экрана наиболее эффективно с любого экрана, даже если вы находитесь в фоновом режиме.

UPDATE

В Google есть библиотека, с помощью которой вы можете снимать скриншот без укоренения, я пробовал это, но я уверен, что он как можно скорее будет вынимать память.

Попробуйте http://code.google.com/p/android-screenshot-library/

Ответ 2

Вот как это сделать.

Android принимает снимки экрана через код

Результат:

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

}

Ответ 3

При съемке в фоновом режиме (например, ADB) требуется groups = 1003 (графика). В противном случае вы можете получить только скриншот собственного процесса. Таким образом, вы можете либо сделать это только на корневом устройстве, либо сделать это, запустив собственную программу ADB.

Пример кода исходного кода cpp можно найти в https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r2.3/cmds/screencap/

И если вы хотите сделать это в Java-коде, вам нужно получить доступ к скрытому API класса Surface:

/**
 * 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 реализация медиасистемы и холста и т.д. не очень хороша, поэтому вы не можете захватить воспроизведение видео или любое содержимое поверхностного изображения в этом случае.

Ответ 4

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 я предоставил путь к загрузке, вы можете изменить путь к папке. В файле манифеста добавить разрешение на запись

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />