Question Comment prendre une capture d'écran par programmation?


Comment puis-je prendre une capture d'écran d'une zone sélectionnée de l'écran d'un téléphone, non par un programme quelconque, mais à partir d'un code?


419
2018-04-18 07:58


origine


Réponses:


Voici le code qui a permis de stocker ma capture d'écran sur une carte SD et de l'utiliser plus tard, 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 (en cours d'exécution 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, utilisez:

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

au lieu de

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

sur takeScreenshot () fonction

Remarque:

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

Android Capture d'écran de Surface View montre Black Screen


383
2018-04-13 14:53



Appelez cette méthode, en passant dans le ViewGroup le plus externe 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;
}

105
2018-04-19 17:08



Remarque: fonctionne uniquement pour les téléphones enracinés

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 lire img.png comme Bitmap et utiliser comme votre souhait.


39
2018-03-04 18:36



EDIT: ayez 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.


30
2018-04-18 08:41



Aucune autorisation root ou pas de gros codage est requis pour cette méthode.


Sur shell adb en utilisant la commande ci-dessous, vous pouvez prendre une capture d'écran.

input keyevent 120

Cette commande ne nécessite pas d'autorisation root donc vous pouvez également effectuer à 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 http://developer.android.com/reference/android/view/KeyEvent.html

Ici nous avons utilisé. KEYCODE_SYSRQ sa valeur est 120 et utilisée pour la touche System Request / Print Screen.


Comme l'a déclaré CJBS, l'image de sortie sera enregistrée dans / sdcard / Pictures / Captures d'écran


18
2018-01-13 09:42



Mualig réponse est très bonne, mais j'ai eu le même problème Ewoks décrit, je ne reçois pas l'arrière-plan. 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 rejette l'utilisation du cache de dessin en appelant directement la méthode draw. Avant cela, je vais essayer de rendre l'arrière-plan tirable de l'activité en cours pour le dessiner en premier.

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

17
2018-06-25 11:37



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 l'autorisation dans le manifeste

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

Pour soutenir Guimauve ou ci-dessus, ajoutez le code ci-dessous dans la méthode onCreate

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

14
2017-08-27 10:31



À titre de référence, une façon de capturer l'écran (et pas seulement l'activité de votre application) consiste à capturer framebuffer (périphérique / dev / graphics / fb0). Pour ce faire, vous devez disposer des privilèges root ou votre application doit être une application avec autorisations de signature ("Une autorisation que le système n'accorde que si l'application demandeuse est signée avec le même certificat que l'application qui a déclaré l'autorisation") - ce qui est très peu probable si vous n'avez pas 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 ont rapporté qu'il en contienne 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 binaire, sorti de fb0 est RGBA dans mon appareil. Cela dépendra probablement d'un périphérique à l'autre. Cela sera important pour vous de le décoder =)

Dans mon appareil / dev / graphics / fb0 les autorisations sont telles que seuls les utilisateurs root et les utilisateurs graphiques du groupe peuvent lire le fichier fb0.

graphique est un groupe restreint, donc vous n'aurez probablement accès à fb0 qu'avec un téléphone root utilisant la commande su.

Les applications Android ont le ID utilisateur (uid) = app _ ## et ID du groupe (guid) = app _ ## .

shell adb a uid = coquille et guid = shell, qui a beaucoup plus d'autorisations qu'une application. Vous pouvez réellement vérifier ces autorisations 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.

En outre, le fait de donner des autorisations READ_FRAME_BUFFER et / ou ACCESS_SURFACE_FLINGER sur AndroidManifest.xml ne fera rien pour une application standard, car cela ne fonctionnera que pour 'Signature' applications.

Vérifiez également ceci Discussion fermée pour plus de détails.


13
2017-12-12 10:40



Vous pouvez essayer la bibliothèque suivante: http://code.google.com/p/android-screenshot-library/ La bibliothèque de captures d'écran Android (ASL) permet de capturer par programme des captures d'écran à partir d'appareils Android sans avoir besoin de privilèges d'accès 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.


11
2017-09-07 13:53



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 enregistrées dans le dossier de stockage externe.


11
2017-09-25 15:07



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

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

6
2017-08-21 12:01