¿Cómo tomar una captura de pantalla mediante progtwigción?

¿Cómo puedo tomar una captura de pantalla de un área seleccionada de la pantalla del teléfono, no por ningún progtwig sino por código?

Aquí está el código que permitió que mi captura de pantalla se almacenara en una tarjeta SD y se usara más adelante para cualquiera que sea su necesidad:

En primer lugar, debe agregar un permiso adecuado para guardar el archivo:

 

Y este es el código (ejecutándose en una Actividad):

 private void takeScreenshot() { Date now = new Date(); android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now); try { // image naming and path to include sd card appending name you choose for file String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg"; // 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(mPath); FileOutputStream outputStream = new FileOutputStream(imageFile); int quality = 100; bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream); outputStream.flush(); outputStream.close(); openScreenshot(imageFile); } catch (Throwable e) { // Several error may come out with file handling or DOM e.printStackTrace(); } } 

Y así es como puedes abrir la imagen generada recientemente:

 private void openScreenshot(File imageFile) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); Uri uri = Uri.fromFile(imageFile); intent.setDataAndType(uri, "image/*"); startActivity(intent); } 

Si quieres usar esto en la vista de fragmentos, utiliza:

 View v1 = getActivity().getWindow().getDecorView().getRootView(); 

en lugar de

 View v1 = getWindow().getDecorView().getRootView(); 

en la función takeScreenshot ()

Nota :

Esta solución no funciona si su cuadro de diálogo contiene una vista de superficie. Para detalles, verifique la respuesta a la siguiente pregunta:

Android Captura de pantalla de la vista de superficie muestra la pantalla en negro

Llame a este método, pasando el grupo de visualización más externo que desea una captura de pantalla de:

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

Nota: funciona solo para teléfono rooteado

Programáticamente, puede ejecutar adb shell /system/bin/screencap -p /sdcard/img.png como se muestra a continuación

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

luego lea img.png como Bitmap y utilícelo como desee.

EDITAR: ten piedad de los votos bajos. Fue cierto en 2010 cuando respondí la pregunta.

Todos los progtwigs que permiten capturas de pantalla funcionan solo en teléfonos rooteados.

No se requiere permiso de root o no se necesita una gran encoding para este método.


En adb shell usando el comando debajo puedes tomar capturas de pantalla.

 input keyevent 120 

Este comando no requiere ningún permiso de root por lo que también puede realizar desde el código de java de la aplicación de Android.

 Process process; process = Runtime.getRuntime().exec("input keyevent 120"); 

Más sobre el código keyevent en android ver http://sofes.miximages.com/android/ream fos = null; try { final File sddir = new File(SCREENSHOTS_LOCATIONS); if (!sddir.exists()) { sddir.mkdirs(); } fos = new FileOutputStream(SCREENSHOTS_LOCATIONS System.currentTimeMillis() .jpg”); if (fos != null) { if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)) { Log.d(LOGTAG, “Compress/Write failed”); } fos.flush(); fos.close(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }

 private void captureScreen() { View v = getWindow().getDecorView().getRootView(); v.setDrawingCacheEnabled(true); Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache()); v.setDrawingCacheEnabled(false); try { FileOutputStream fos = new FileOutputStream(new File(Environment .getExternalStorageDirectory().toString(), "SCREEN" + System.currentTimeMillis() + ".png")); bmp.compress(CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } 

Agregue el permiso en el manifiesto

  

Para Supporting Marshmallow o versiones anteriores, agregue el siguiente código en la actividad onCreate method

 ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00); 

Como referencia, una forma de capturar la pantalla (y no solo la actividad de su aplicación) es capturar el framebuffer (device / dev / graphics / fb0). Para hacerlo, debe tener privilegios de administrador o su aplicación debe ser una aplicación con permisos de firma (“Un permiso que el sistema concede solo si la aplicación solicitante está firmada con el mismo certificado que la aplicación que declaró el permiso”), que es muy poco probable a menos que haya comstackdo su propia ROM.

Cada captura de framebuffer, de un par de dispositivos que he probado, contenía exactamente una captura de pantalla. La gente ha informado que contiene más, supongo que depende del tamaño del fotogtwig / visualización.

Traté de leer el framebuffer de forma continua, pero parece regresar por una cantidad fija de bytes leídos. En mi caso, eso es (3 410 432) bytes, que es suficiente para almacenar un marco de visualización de 854 * 480 RGBA (3 279 360 bytes). Sí, el fotogtwig, en binario, emitido desde fb0 es RGBA en mi dispositivo. Es muy probable que esto dependa de un dispositivo a otro. Esto será importante para decodificarlo =)

En mi dispositivo, los permisos / dev / graphics / fb0 son para que solo el usuario root y los usuarios de los gráficos grupales puedan leer el archivo fb0.

graphics es un grupo restringido, por lo que probablemente solo accedas a fb0 con un teléfono rooteado usando su comando.

Las aplicaciones de Android tienen la identificación del usuario (uid) = aplicación _ ## y la identificación del grupo (guid) = aplicación _ ## .

adb shell tiene uid = shell y guid = shell , que tiene muchos más permisos que una aplicación. Puede verificar esos permisos en /system/permissions/platform.xml

Esto significa que podrá leer fb0 en el shell adb sin root pero no lo leerá dentro de la aplicación sin root.

Además, otorgar permisos a READ_FRAME_BUFFER y / o ACCESS_SURFACE_FLINGER en AndroidManifest.xml no hará nada para una aplicación normal, ya que solo funcionarán para las aplicaciones de ‘ firma ‘.

También verifique este hilo cerrado para más detalles.

Mi solución es:

 public static Bitmap loadBitmapFromView(Context context, View v) { DisplayMetrics dm = context.getResources().getDisplayMetrics(); v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY)); v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(returnedBitmap); v.draw(c); return returnedBitmap; } 

y

 public void takeScreen() { Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg"; File imageFile = new File(mPath); OutputStream fout = null; try { fout = new FileOutputStream(imageFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout); fout.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { fout.close(); } } 

Las imágenes se guardan en la carpeta de almacenamiento externo.

Puede probar la siguiente biblioteca: http://code.google.com/p/android-screenshot-library/ Android Screenshot Library (ASL) permite capturar capturas de pantalla desde dispositivos Android sin necesidad de privilegios de acceso a la raíz. En cambio, ASL utiliza un servicio nativo que se ejecuta en segundo plano, iniciado a través del Android Debug Bridge (ADB) una vez por cada inicio del dispositivo.

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

AGREGAR PERMISO

  

Basado en la respuesta de @JustinMorris anterior y @NiravDangi aquí https://stackoverflow.com/a/8504958/2232148 debemos tomar los antecedentes y el primer plano de una vista y armarlos de esta manera:

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

El parámetro de calidad toma una constante de Bitmap.Config, normalmente Bitmap.Config.RGB_565 o Bitmap.Config.ARGB_8888 .

Puedes intentar hacer algo como esto,

Obtener un caché de bitmap desde un diseño o una vista haciendo algo como Primero tienes que establecer setDrawingCacheEnabled en un diseño (un diseño lineal o relativo, o una vista)

entonces

 Bitmap bm = layout.getDrawingCache() 

Luego haz lo que quieras con el bitmap. Ya sea convirtiéndolo en un archivo de imagen, o enviando el uri del bitmap a otro lugar.

Para aquellos que quieran capturar un GLSurfaceView, el método getDrawingCache o drawing to canvas no funcionará.

Debe leer el contenido del framebuffer de OpenGL después de que se haya procesado el fotogtwig. Hay una buena respuesta aquí

La manera corta es

 FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/ layDraw.buildDrawingCache(); Bitmap bmp = layDraw.getDrawingCache(); 

Creé una biblioteca simple que toma una captura de pantalla de una View y le da un objeto Bitmap o la guarda directamente en cualquier ruta que desee

https://github.com/abdallahalaraby/Blink

Simplemente extendiendo la respuesta de taraloca. Debe agregar las siguientes líneas para que funcione. He hecho que el nombre de la imagen sea estático. Por favor, asegúrese de utilizar la variable de indicación de fecha y hora de Taraloca en caso de que necesite un nombre de imagen dynamic.

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

Y en el archivo AndroidManifest.xml, las siguientes entradas son obligatorias:

   

Si quieres tomar una captura de pantalla de un fragment sigue esto:

  1. Anular 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. Lógica para tomar una captura de pantalla:

      button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { View view = mView.findViewById(R.id.scrollView1); shareScreenShotM(view, (NestedScrollView) view); } 
  3. método 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. método 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. método 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; } 

Para la actividad, simplemente puede usar View v1 = getWindow().getDecorView().getRootView(); en lugar de mView

Junto con la captura de pantalla, si queremos reproducir el tono también. Podemos usar el siguiente código

  MediaPlayer _shootMP = null; AudioManager manager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); manager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0); if (_shootMP == null) _shootMP = MediaPlayer .create(getActivity(), Uri.parse("file:///system/media/audio/ui/camera_click.ogg")); if (_shootMP != null) { try { _shootMP.start(); _shootMP.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer arg0) { // release the media _shootMP.stop(); _shootMP.reset(); _shootMP.release(); _shootMP = null; } }); } catch (IllegalStateException e) { Log.w(TAG, "Exception takeScreenShot" + e.getMessage()); } } 

¡Solo para aplicaciones del sistema!

 Process process; process = Runtime.getRuntime().exec("screencap -p " + outputPath); process.waitFor(); 

Nota: las aplicaciones del sistema no necesitan ejecutar “su” para ejecutar este comando.

La vista de parámetros es el objeto de disposición raíz.

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

La mayoría de las respuestas para esta pregunta usan el método de dibujo Canvas o el método de caché de dibujo. Sin embargo, el método View.setDrawingCache() está en desuso en API 28 . Actualmente, la API recomendada para realizar capturas de pantalla es la clase PixelCopy disponible desde la API 24 (pero los métodos que aceptan el parámetro Window están disponibles en API 26 == Android 8.0 Oreo). Aquí hay un ejemplo de código de Kotlin para recuperar un 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 } } } 

si desea capturar una vista o diseño como RelativeLayout o LinearLayout, solo use el código:

 LinearLayout llMain = (LinearLayout) findViewById(R.id.linearlayoutMain); Bitmap bm = loadBitmapFromView(llMain); 

ahora puede guardar este bitmap en el almacenamiento del dispositivo de la siguiente manera:

 FileOutputStream outStream = null; File f=new File(Environment.getExternalStorageDirectory()+"/Screen Shots/"); f.mkdir(); String extStorageDirectory = f.toString(); File file = new File(extStorageDirectory, "my new screen shot"); pathOfImage = file.getAbsolutePath(); try { outStream = new FileOutputStream(file); bm.compress(Bitmap.CompressFormat.PNG, 100, outStream); Toast.makeText(getApplicationContext(), "Saved at "+f.getAbsolutePath(), Toast.LENGTH_LONG).show(); addImageGallery(file); //mail.setEnabled(true); flag=true; } catch (FileNotFoundException e) {e.printStackTrace();} try { outStream.flush(); outStream.close(); } catch (IOException e) {e.printStackTrace();}