Procédure de programmation pour prendre une capture d'écran?
Comment puis-je prendre une capture d'écran d'une zone sélectionnée de l'écran de téléphone pas par n'importe quel programme mais par code?
23 réponses
voici le code qui a permis à ma capture d'écran d'être stockée sur une carte SD et utilisée plus tard pour quels que soient vos besoins:
tout d'Abord, vous devez ajouter une autorisation appropriée pour enregistrer le fichier:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Et voici le code (courant 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
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();
}
}
Et voici comment vous pouvez ouvrir l'image générée récemment:
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 voulez utiliser ceci sur la vue de fragment alors use:
View v1 = getActivity().getWindow().getDecorView().getRootView();
au lieu de
View v1 = getWindow().getDecorView().getRootView();
sur takeScreenshot() fonction
Note :
cette solution ne fonctionne pas si votre dialogue contient une vue de surface. Pour plus de détails, veuillez consulter la réponse à la question suivante:
Android Prendre une Capture d'écran de la Surface d'Affichage Montre l'Écran Noir
appelez cette méthode, en passant dans le groupe de vue le plus externe que vous voulez une prise de vue de l'é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;
}
Note: ne fonctionne que pour les téléphones à racines
par programmation, 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 img.png
comme Bitmap
et utilisez comme vous le souhaitez.
EDIT: aie pitié avec les downvotes. C'était vrai en 2010 quand j'ai répondu à la question.
tous les programmes qui permettent des captures d'écran ne fonctionnent que sur les téléphones enracinés.
Pas de racine autorisation ou pas grand-codage est nécessaire pour cette méthode.
sur shell adb en utilisant la commande ci-dessous, vous pouvez prendre la prise de vue d'écran.
input keyevent 120
cette commande ne nécessite pas de permission de la part de root, donc vous pouvez effectuer la même chose à 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://developer.android.com/reference/android/view/KeyEvent.html
nous avons utilisé ici. KEYCODE_SYSRQ sa valeur est de 120 et est utilisée pour la touche D'écran requête / impression Système.
comme CJBS l'a dit, L'image de sortie sera sauvegardée dans / sdcard / Pictures /Screenshots
Mualig réponse est très bon, mais j'ai eu le même problème Ewoks décrit, Je ne comprends pas le contexte. Donc parfois c'est assez bien et parfois je reçois du texte noir sur fond noir (selon le thème).
cette solution est fortement basée sur le code Mualig et le code que J'ai trouvé dans Robotium. Je me débarrasse de l'utilisation du cache dessin en appelant directement à la méthode draw. Avant cela, je vais essayer d'obtenir le fond de dessin de l'activité courante pour dessiner d'abord.
// Some constants
final static String SCREENSHOTS_LOCATIONS = Environment.getExternalStorageDirectory().toString() + "/screenshots/";
// Get device dimmensions
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Get root view
View view = mCurrentUrlMask.getRootView();
// Create the bitmap to use to draw the screenshot
final Bitmap bitmap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ARGB_4444);
final Canvas canvas = new Canvas(bitmap);
// Get current theme to know which background to use
final Activity activity = getCurrentActivity();
final Theme theme = activity.getTheme();
final TypedArray ta = theme
.obtainStyledAttributes(new int[] { android.R.attr.windowBackground });
final int res = ta.getResourceId(0, 0);
final Drawable background = activity.getResources().getDrawable(res);
// Draw background
background.draw(canvas);
// Draw views
view.draw(canvas);
// Save the screenshot to the file system
FileOutputStream 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();
}
}
ajouter la permission dans le manifeste
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Pour le Soutien Guimauve ou des versions ci-dessus, veuillez ajouter le code ci-dessous dans l'activité de la méthode onCreate
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);
Comme une référence, un moyen de capturer l'écran (et pas seulement votre activité app) est de capturer le framebuffer (périphérique /dev/graphiques/fb0). Pour ce faire, vous devez avoir des privilèges root ou votre application doit être une application avec autorisations de signature ("une autorisation que le système accorde seulement si la demande est signée avec le même certificat que la demande qui a déclaré la permission") - ce qui est très peu probable à moins que vous avez compilé votre propre ROM.
chaque capture de framebuffer, à partir de quelques 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 cadre/d'affichage.
j'ai essayé de lire le framebuffer en continu mais il semble revenir pour une quantité fixe d'octets lus. Dans mon cas, il s'agit de (3 410 432) octets, ce qui est suffisant pour stocker un cadre d'affichage de 854*480 RGBA (3 279 360 octets). Oui, le cadre, en binaire, sorti de fb0 est RGBA dans mon appareil. Cela dépendra très probablement d'un appareil à l'autre. Ce sera important pour vous de décoder it =)
dans mon appareil /dev/graphics/fb0 les permissions sont de sorte que seuls le root et les utilisateurs de Group graphics peuvent lire le fb0.
graphics est un groupe restreint de sorte que vous ne pourrez probablement accéder à fb0 qu'avec un téléphone qui utilise la commande su.
applications Android ont la id utilisateur (uid) = app_## et id de groupe (guid) = app_## .
adb shell a uid = shell et guid = shell , qui a beaucoup plus d'autorisations que d'une application. Vous pouvez vérifier ces permissions dans /system/permissions/platform.xml
vous pourrez lire fb0 dans le shell adb sans root, mais vous ne le lirez pas dans l'application sans root.
permet également READ_FRAME_BUFFER et/ou ACCESS_SURFACE_FLINGER sur AndroidManifest.xml ne fera rien pour une application régulière car cela ne fonctionnera que pour les applications ' signature ".
vérifier fermé fil pour plus de détails.
ma solution est:
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;
}
et
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();
}
}
Les Images sont sauvegardé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 des screenshots depuis des appareils Android sans avoir besoin des privilèges d'accès root. Au lieu de cela, ASL utilise un service natif en arrière-plan, lancé via le Pont de débogage Android (ADB) une fois par boot 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 AUTORISATION
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
basé sur la réponse de @JustinMorris ci-dessus et @NiravDangi ici https://stackoverflow.com/a/8504958/2232148 nous devons prendre l'arrière-plan et l'avant-plan d'une vue et les assembler comme ceci:
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, typiquement Bitmap.Config.RGB_565
ou Bitmap.Config.ARGB_8888
.
Vous pouvez essayer de faire quelque chose comme ça,
obtenir une cache bitmap à partir d'une mise en page ou d'une vue en faisant quelque chose comme
Tout d'abord, vous devez setDrawingCacheEnabled
à un layout(une linearlayout ou relativelayout, ou une vue)
puis
Bitmap bm = layout.getDrawingCache()
, Puis vous faites ce que vous voulez avec le bitmap. Soit en le transformant en fichier image, soit en envoyant l'uri de bitmap ailleurs.
j'ai créé une bibliothèque simple qui prend une capture d'écran d'un View
et soit vous donne un objet Bitmap ou le sauve directement à n'importe quel chemin que vous voulez
Bref, c'est "la 151920920"
FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();
si vous voulez prendre la capture d'écran de fragment
que de suivre ce qui suit:
-
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; }
-
Logique de la prise de 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); }
-
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. }
-
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; }
-
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
j'étends juste la réponse de taraloca. Vous devez ajouter les lignes suivantes pour le faire fonctionner. j'ai rendu le nom de l'image statique. S'il vous plaît assurez-vous que vous utilisez taraloca's timestamp variable incase vous avez besoin du nom de l'image dynamique.
// 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();
}
}
}
et dans L'AndroidManifest.fichier xml les entrées suivantes sont obligatoires:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
ainsi que la capture d'écran,si nous voulons jouer le ton aussi.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 seulement!
Process process;
process = Runtime.getRuntime().exec("screencap -p " + outputPath);
process.waitFor();
Note: les applications système n'ont pas besoin d'exécuter "su" pour exécuter cette commande.
le paramètre view est l'objet root layout.
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. Toutefois, la méthode View.setDrawingCache()
est dépréciée 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 extraire 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 vous voulez capturer une vue ou un layout comme RelativeLayout ou LinearLayout etc. il suffit d'utiliser le code:
LinearLayout llMain = (LinearLayout) findViewById(R.id.linearlayoutMain);
Bitmap bm = loadBitmapFromView(llMain);
maintenant vous pouvez enregistrer cette image sur le stockage de périphérique par:
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();}