web-dev-qa-db-fra.com

Android - Comment prendre une capture d'écran par programme

J'ai besoin de captures d'écran du périphérique ou de l'émulateur Android par programme lorsque mon application est installée et s'exécute en arrière-plan toutes les 200 millisecondes et d'enregistrer les images sur mon ordinateur. J'ai implémenté cette procédure en utilisant le code ci-dessous et ne fonctionne que lorsque mon application est au premier plan. Je veux prendre des captures d'écran lorsque mon application est également en arrière-plan. Ci-dessous mon code:

public static Bitmap takeScreenshot(Activity activity, int ResourceID) { 
    Random r = new Random();
    int iterator=r.nextInt();   
     String mPath = Environment.getExternalStorageDirectory().toString() + "/screenshots/";
    View v1 = activity.getWindow().getDecorView().findViewById(ResourceID);
    v1.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    v1.layout(0, 0, v1.getMeasuredWidth(), v1.getMeasuredHeight()); 
    v1.setDrawingCacheEnabled(true);
    final Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
    Bitmap resultBitmap = Bitmap.createScaledBitmap(bitmap, 640, 480, false);
    v1.setDrawingCacheEnabled(false);
    File imageFile = new File(mPath);
    imageFile.mkdirs();
    imageFile = new File(imageFile+"/"+iterator+"_screenshot.png");
    try {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        resultBitmap.compress(CompressFormat.PNG, 100, bos);
        byte[] bitmapdata = bos.toByteArray();

        //write the bytes in file
        FileOutputStream fos = new FileOutputStream(imageFile);
        fos.write(bitmapdata);
        fos.flush();
        fos.close();    
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bitmap;
    }  

Comment puis-je implémenter les fonctionnalités des boutons Actualiser et Enregistrer de Screencapture dans Devices -> DDMS par programme? Puis-je y arriver?

15
Avadhani Y

Si votre téléphone est enraciné, essayez ceci 

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 en bitmap et convertissez-le en jpg comme suit 

Bitmap screen = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+         
File.separator +"img.png");

//my code for saving
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    screen.compress(Bitmap.CompressFormat.JPEG, 15, bytes);

//you can create a new file name "test.jpg" in sdcard folder.

File f = new File(Environment.getExternalStorageDirectory()+ File.separator + "test.jpg");
            f.createNewFile();
//write the bytes in file
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
// remember close de FileOutput

    fo.close();

vous n'avez pas accès à l'écran si votre application est en arrière-plan sauf si vous êtes enraciné, le code ci-dessus peut prendre la capture d'écran le plus efficacement possible, même si vous êtes en arrière-plan.

METTRE À JOUR

Google a une bibliothèque avec laquelle vous pouvez prendre une capture d'écran sans l'enracinement, c'est ce que j'ai essayé, mais je suis sûr qu'il va vider la mémoire au plus vite.

Essayez http://code.google.com/p/Android-screenshot-library/

17

Voici le moyen de le faire.

Prenant Android captures d'écran par le code

Résultat:

enter image description here

enter image description here

public class CaptureScreenShots extends Activity {
    LinearLayout L1;
    ImageView image;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.screen_shots);
         L1 = (LinearLayout) findViewById(R.id.LinearLayout01);
            Button but = (Button) findViewById(R.id.munchscreen);
            but.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    View v1 = L1.getRootView();
                    v1.setDrawingCacheEnabled(true);
                    Bitmap bm = v1.getDrawingCache();
                    BitmapDrawable bitmapDrawable = new BitmapDrawable(bm);
                    image = (ImageView) findViewById(R.id.screenshots);
                    image.setBackgroundDrawable(bitmapDrawable);
                }
            });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.screen_shots, menu);
        return true;
    }

}
13
swiftBoy

Prendre une capture d’écran en arrière-plan (comme ADB) nécessite groups = 1003 (graphisme). Sinon, vous ne pouvez obtenir que la capture d'écran de votre propre processus. Vous ne pouvez donc le faire que sur un périphérique enraciné ou en exécutant le programme natif ADB.

Vous trouverez un exemple de code cpp natif à l’adresse https://Android.googlesource.com/platform/frameworks/base/+/Android-4.3_r2.3/cmds/screencap/

Et si vous voulez le faire en code Java, vous devez accéder à l'API masquée de la classe Surface:

/**
 * Like {@link #screenshot(int, int, int, int)} but includes all
 * Surfaces in the screenshot.
 *
 * @hide
 */
public static native Bitmap screenshot(int width, int height);

Ces deux éléments devraient être corrects depuis la version ICS, vous pouvez consulter le code cpp natif.

Cependant, sur certains appareils Android, la mise en œuvre du système multimédia, de la zone de dessin, etc. n'est pas très bonne. Vous ne pouvez donc capturer aucune lecture de vidéo ni aucun contenu de vue de surface dans ce cas.

4
Robin

vous pouvez envisager de mélanger MediaProjection et AccessibilityService . Le premier prend la capture d'écran avec facilité, le second tourne tout le temps "au-dessus" de toutes les applications

Tutoriel comment exécuter AccessibilityService dans CODELABS

Source complète des exemples ci-dessus ICI

Dans THIS answer, vous pouvez trouver un morceau de code très utile pour Activity. N'oubliez pas de définir correctement Theme entièrement transparent:

<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.NoActionBar">
    <item name="Android:background">#00000000</item>
    <item name="Android:windowNoTitle">true</item>
    <item name="Android:windowBackground">@Android:color/transparent</item>
    <item name="Android:colorBackgroundCacheHint">@null</item>
    <item name="Android:windowIsTranslucent">true</item>
    <item name="Android:windowAnimationStyle">@null</item>
</style>

Puis bouclez startActivity dans votre AccessibilityService aussi souvent que vous le souhaitez, ou mieux - utilisez LocalBroadcastManager pour informer Service que Activity a pris une capture d'écran et est terminé (donc Service peut recommencer cette Activity)

J'ai fait quelque chose de similaire (pour usage interne uniquement) + les captures d'écran ont été analysées avec OCR pour en extraire le texte. C'est un peu l'analyse, quand pas-votre-application se défend en quelque sorte contre les fonctionnalités AccesibilityService (ce type de Service est destiné à aider les personnes handicapées, par exemple en lecture de texte, à avoir généralement accès à TextViews)

0
snachmsm