Как программно сделать скриншот на Android? - PullRequest
470 голосов
/ 18 апреля 2010

Как сделать снимок экрана выбранной области экрана телефона не какой-либо программой, а кодом?

Ответы [ 24 ]

8 голосов
/ 21 мая 2015

Основываясь на ответе @JustinMorris выше и @NiravDangi здесь https://stackoverflow.com/a/8504958/2232148, мы должны взять фон и передний план вида и собрать их так:

public static Bitmap takeScreenshot(View view, Bitmap.Config quality) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), quality);
    Canvas canvas = new Canvas(bitmap);

    Drawable backgroundDrawable = view.getBackground();
    if (backgroundDrawable != null) {
        backgroundDrawable.draw(canvas);
    } else {
        canvas.drawColor(Color.WHITE);
    }
    view.draw(canvas);

    return bitmap;
}

Параметр качества принимаетконстанта Bitmap.Config, обычно либо Bitmap.Config.RGB_565, либо Bitmap.Config.ARGB_8888.

8 голосов
/ 21 августа 2014
public class ScreenShotActivity extends Activity{

private RelativeLayout relativeLayout;
private Bitmap myBitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    relativeLayout = (RelativeLayout)findViewById(R.id.relative1);
    relativeLayout.post(new Runnable() {
        public void run() {

            //take screenshot
            myBitmap = captureScreen(relativeLayout);

            Toast.makeText(getApplicationContext(), "Screenshot captured..!", Toast.LENGTH_LONG).show();

            try {
                if(myBitmap!=null){
                    //save image to SD card
                    saveImage(myBitmap);
                }
                Toast.makeText(getApplicationContext(), "Screenshot saved..!", Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    });

}

public static Bitmap captureScreen(View v) {

    Bitmap screenshot = null;
    try {

        if(v!=null) {

            screenshot = Bitmap.createBitmap(v.getMeasuredWidth(),v.getMeasuredHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(screenshot);
            v.draw(canvas);
        }

    }catch (Exception e){
        Log.d("ScreenShotActivity", "Failed to capture screenshot because:" + e.getMessage());
    }

    return screenshot;
}

public static void saveImage(Bitmap bitmap) throws IOException{

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 40, bytes);
    File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
    f.createNewFile();
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
    fo.close();
}

}

ДОБАВИТЬ РАЗРЕШЕНИЕ

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
6 голосов
/ 05 марта 2011

Вы можете попробовать сделать что-то вроде этого,

Получение кеша растрового изображения из макета или представления, выполняя что-то вроде Сначала вы должны setDrawingCacheEnabled на макет (линейное или относительное расположение или представление)

затем

Bitmap bm = layout.getDrawingCache()

Затем вы делаете все, что хотите с растровым изображением. Либо превратив его в файл изображения, либо отправьте URI растрового изображения куда-либо еще.

6 голосов
/ 10 апреля 2015

Для тех, кто хочет захватить GLSurfaceView, метод getDrawingCache или рисование на холст не будет работать.

Вы должны прочитать содержимое буфера кадров OpenGL после рендеринга кадра. Здесь хороший ответ здесь

6 голосов
/ 12 октября 2017

Короткий путь -

FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();
5 голосов
/ 27 октября 2014

Я создал простую библиотеку, которая делает снимок экрана с View и либо предоставляет вам растровый объект, либо сохраняет его непосредственно по любому желаемому пути

https://github.com/abdallahalaraby/Blink

4 голосов
/ 30 июля 2017

Просто расширяю ответ таралоки. Вы должны добавить следующие строки, чтобы это работало. Я сделал имя изображения статичным. Пожалуйста, убедитесь, что вы используете переменную метки времени taraloca, если вам нужно динамическое имя изображения. // Storage Permissions private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private void verifyStoragePermissions() { // Check if we have write permission int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); }else{ takeScreenshot(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestCode == REQUEST_EXTERNAL_STORAGE) { takeScreenshot(); } } } А в файле AndroidManifest.xml должны быть следующие записи:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
4 голосов
/ 30 апреля 2016

Если вы хотите сделать скриншот из fragment, выполните следующие действия:

  1. Переопределите onCreateView():

             @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) {
                // Inflate the layout for this fragment
                View view = inflater.inflate(R.layout.fragment_one, container, false);
                mView = view;
            }
    
  2. Логикадля снятия скриншота:

     button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         View view =  mView.findViewById(R.id.scrollView1);
          shareScreenShotM(view, (NestedScrollView) view); 
     }
    
  3. метод shareScreenShotM)():

    public void shareScreenShotM(View view, NestedScrollView scrollView){
    
         bm = takeScreenShot(view,scrollView);  //method to take screenshot
        File file = savePic(bm);  // method to save screenshot in phone.
        }
    
  4. метод takeScreenShot ():

             public Bitmap takeScreenShot(View u, NestedScrollView z){
    
                u.setDrawingCacheEnabled(true);
                int totalHeight = z.getChildAt(0).getHeight();
                int totalWidth = z.getChildAt(0).getWidth();
    
                Log.d("yoheight",""+ totalHeight);
                Log.d("yowidth",""+ totalWidth);
                u.layout(0, 0, totalWidth, totalHeight);
                u.buildDrawingCache();
                Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
                u.setDrawingCacheEnabled(false);
                u.destroyDrawingCache();
                 return b;
            }
    
  5. метод savePic ():

     public static File savePic(Bitmap bm){
    
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
             File sdCardDirectory =  new File(Environment.getExternalStorageDirectory() + "/Foldername");
    
           if (!sdCardDirectory.exists()) {
                sdCardDirectory.mkdirs();
          }
           //  File file = new File(dir, fileName);
          try {
             file = new File(sdCardDirectory, Calendar.getInstance()
                .getTimeInMillis() + ".jpg");
            file.createNewFile();
            new FileOutputStream(file).write(bytes.toByteArray());
            Log.d("Fabsolute", "File Saved::--->" + file.getAbsolutePath());
             Log.d("Sabsolute", "File Saved::--->" + sdCardDirectory.getAbsolutePath());
         } catch (IOException e) {
              e.printStackTrace();
          }
         return file;
       }
    

Для активности вы можете просто использовать View v1 = getWindow().getDecorView().getRootView(); вместо mView

2 голосов
/ 16 августа 2018

В большинстве ответов на этот вопрос используется метод рисования Canvas или метод кэширования чертежа. Однако метод View.setDrawingCache() устарел в API 28 . В настоящее время рекомендуемым API для создания снимков экрана является класс PixelCopy, доступный из API 24 (но методы, которые принимают параметр Window, доступны из API 26 == Android 8.0 Oreo). Вот пример кода Kotlin для получения Bitmap:

@RequiresApi(Build.VERSION_CODES.O)
fun saveScreenshot(view: View) {
    val window = (view.context as Activity).window
    if (window != null) {
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val locationOfViewInWindow = IntArray(2)
        view.getLocationInWindow(locationOfViewInWindow)
        try {
            PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
                if (copyResult == PixelCopy.SUCCESS) {
                    saveBitmap(bitmap)
                }
                // possible to handle other result codes ...
            }, Handler())
        } catch (e: IllegalArgumentException) {
            // PixelCopy may throw IllegalArgumentException, make sure to handle it
        }
    }
}
2 голосов
/ 29 июня 2018

Представление параметра является корневым объектом макета.

public static Bitmap screenShot(View view) {
                    Bitmap bitmap = null;
                    if (view.getWidth() > 0 && view.getHeight() > 0) {
                        bitmap = Bitmap.createBitmap(view.getWidth(),
                                view.getHeight(), Bitmap.Config.ARGB_8888);
                        Canvas canvas = new Canvas(bitmap);
                        view.draw(canvas);
                    }
                    return bitmap;
                }
...