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?
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/
Voici le moyen de le faire.
Prenant Android captures d'écran par le code
Résultat:
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;
}
}
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.
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 à TextView
s)