Comment prendre une capture d’écran par programmation?

Comment puis-je faire une capture d’écran d’une zone sélectionnée de l’écran de téléphone non par un programme, mais par le code?

Voici le code qui a permis que ma capture d’écran soit stockée sur une carte SD et utilisée plus tard, quels que soient vos besoins:

Tout d’abord, vous devez append une autorisation appropriée pour enregistrer le fichier:

 

Et voici le code (exécuté dans une activité):

 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 Ssortingng mPath = Environment.getExternalStorageDirectory().toSsortingng() + "/" + 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(); } } 

Et voici comment vous pouvez ouvrir l’image récemment générée:

 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 vous souhaitez utiliser cette vue fragment, utilisez:

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

au lieu de

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

sur la fonction takeScreenshot ()

Note :

Cette solution ne fonctionne pas si votre boîte de dialog contient une vue de surface. Pour plus de détails, veuillez vérifier la réponse à la question suivante:

Capture d’écran Android de Surface View Affiche l’écran noir

Appelez cette méthode en transmettant le plus proche ViewGroup que vous voulez une capture d’écran 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; } 

Remarque: ne fonctionne que pour un téléphone rooté

Par programme, vous pouvez exécuter adb shell /system/bin/screencap -p /sdcard/img.png comme ci-dessous

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

puis lisez img.png comme Bitmap et utilisez-le comme vous le souhaitez.

EDIT: avoir pitié des downvotes. C’était vrai en 2010 quand j’ai répondu à la question.

Tous les programmes qui autorisent les captures d’écran ne fonctionnent que sur les téléphones rootés.

Aucune autorisation root ou aucun gros codage n’est requirejs pour cette méthode.


Sur shell adb en utilisant la commande ci-dessous, vous pouvez prendre des captures d’écran.

 input keyevent 120 

Cette commande ne nécessite aucune autorisation root, de sorte que vous pouvez également exécuter à partir du code Java de l’application Android.

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

Plus d’informations sur le code keyevent dans android, voir http://soffr.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().toSsortingng(), "SCREEN" + System.currentTimeMillis() + ".png")); bmp.compress(CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } 

Ajouter l’autorisation dans le manifeste

  

Pour les versions de Marshmallow ou ci-dessus, veuillez append le code ci-dessous dans la méthode activity onCreate

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

À titre de référence, une façon de capturer l’écran (et pas uniquement l’activité de votre application) consiste à capturer le framebuffer (périphérique / dev / graphics / fb0). Pour ce faire, vous devez avoir les privilèges root ou votre application doit être une application avec des permissions de signature (“Une autorisation que le système accorde uniquement si l’application demandeuse est signée avec le même certificate que l’application ayant déclaré l’autorisation”) très peu probable, sauf si vous avez compilé votre propre ROM.

Chaque capture de framebuffer, à partir de deux appareils que j’ai testés, contenait exactement une capture d’écran. Les gens l’ont signalé pour contenir plus, je suppose que cela dépend de la taille de l’image / de l’écran.

J’ai essayé de lire le framebuffer en continu mais il semble revenir pour une quantité d’octets lue. Dans mon cas, il s’agit de (3 410 432) octets, ce qui est suffisant pour stocker une trame d’affichage de 854 * 480 RGBA (3 279 360 octets). Oui, le cadre, en binary, généré par fb0 est RGBA dans mon appareil. Cela dépendra probablement d’un périphérique à l’autre. Ce sera important pour vous de le décoder =)

Dans mon appareil, les permissions / dev / graphics / fb0 sont telles que seuls les utilisateurs root et les utilisateurs de groupes peuvent lire le fb0.

Les graphiques sont un groupe restreint, donc vous n’aurez probablement access à fb0 qu’avec un téléphone rooté en utilisant la commande su.

Les applications Android ont l’ ID utilisateur (uid) = app _ ## et l’ ID de groupe (guid) = app _ ## .

adb shell a uid = shell et guid = shell , qui a beaucoup plus d’permissions qu’une application. Vous pouvez réellement vérifier ces permissions sur /system/permissions/platform.xml

Cela signifie que vous pourrez lire fb0 dans le shell adb sans root, mais vous ne le lirez pas dans l’application sans root.

De même, donner des permissions READ_FRAME_BUFFER et / ou ACCESS_SURFACE_FLINGER sur AndroidManifest.xml ne fera rien pour une application normale, car celles-ci ne fonctionneront que pour les applications « signature ».

Vérifiez également ce fil fermé pour plus de détails.

Ma solution est la suivante:

 public static Bitmap loadBitmapFromView(Context context, View v) { DisplayMesortingcs dm = context.getResources().getDisplayMesortingcs(); 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; } 

et

 public void takeScreen() { Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view Ssortingng 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(); } } 

Les images sont enregistrées dans le dossier de stockage externe.

Vous pouvez essayer la bibliothèque suivante: http://code.google.com/p/android-screenshot-library/ Android Screenshot Library (ASL) permet de capturer par programme des captures d’écran à partir d’appareils Android sans avoir besoin de privilèges d’access root. Au lieu de cela, ASL utilise un service natif exécuté en arrière-plan, démarré via Android Debug Bridge (ADB) une fois par démarrage de périphérique.

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

AJOUTER UNE AUTORISATION

  

Sur la base de la réponse de @JustinMorris ci-dessus et de @NiravDangi ici https://stackoverflow.com/a/8504958/2232148, nous devons prendre l’arrière-plan et le premier plan d’une vue et les assembler comme suit:

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

Le paramètre de qualité prend une constante de Bitmap.Config, généralement soit Bitmap.Config.RGB_565 ou Bitmap.Config.ARGB_8888 .

Vous pouvez essayer de faire quelque chose comme ça,

Obtenir un cache bitmap à partir d’une mise en page ou d’une vue en faisant quelque chose comme First

puis

 Bitmap bm = layout.getDrawingCache() 

Ensuite, vous faites ce que vous voulez avec le bitmap. Soit le transformer en fichier image, soit envoyer l’URI du bitmap ailleurs.

Pour ceux qui souhaitent capturer une GLSurfaceView, la méthode getDrawingCache ou Drawing to canvas ne fonctionnera pas.

Vous devez lire le contenu du framebuffer OpenGL après le rendu de l’image. Il y a une bonne réponse ici

Court chemin est

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

J’ai créé une bibliothèque simple qui prend une capture d’écran à partir d’une View et vous donne un object bitmap ou l’enregistre directement dans n’importe quel chemin que vous voulez

https://github.com/abdallahalaraby/Blink

Juste en étendant la réponse de taraloca. Vous devez append les lignes suivantes pour que cela fonctionne. J’ai rendu le nom de l’image statique. Veuillez vous assurer que vous utilisez la variable d’horodatage de taraloca si vous avez besoin d’un nom d’image dynamic.

  // Storage Permissions private static final int REQUEST_EXTERNAL_STORAGE = 1; private static Ssortingng[] 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 Ssortingng[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestCode == REQUEST_EXTERNAL_STORAGE) { takeScreenshot(); } } } 

Et dans le fichier AndroidManifest.xml, les entrées suivantes doivent être:

   

Si vous voulez prendre une capture d’écran de fragment suivez ceci:

  1. Remplacer 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. Logique pour prendre une capture d’écran:

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

Pour l’activité, vous pouvez simplement utiliser View v1 = getWindow().getDecorView().getRootView(); au lieu de mView

Avec la capture d’écran, si nous voulons également jouer le son. Nous pouvons utiliser le code suivant

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

Pour les applications système uniquement!

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

Remarque: les applications système n’ont pas besoin d’exécuter “su” pour exécuter cette commande.

La vue de paramètre est l’object de présentation racine.

 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 plupart des réponses à cette question utilisent la méthode de dessin Canvas ou la méthode de cache de dessin. Cependant, la méthode View.setDrawingCache() est obsolète dans l’API 28 . Actuellement, l’API recommandée pour faire des captures d’écran est la classe PixelCopy disponible à partir de l’API 24 (mais les méthodes qui acceptent le paramètre Window sont disponibles à partir de l’API 26 == Android 8.0 Oreo). Voici un exemple de code Kotlin pour récupérer une image 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 vous voulez capturer une vue ou une mise en page comme RelativeLayout ou LinearLayout etc., utilisez simplement le code:

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

Vous pouvez maintenant enregistrer ce bitmap sur le stockage de l’appareil en:

 FileOutputStream outStream = null; File f=new File(Environment.getExternalStorageDirectory()+"/Screen Shots/"); f.mkdir(); Ssortingng extStorageDirectory = f.toSsortingng(); 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();}