Je crée une application sous Android dans laquelle je dois prendre une capture d'écran de l'une de mes activités et l'envoyer en pièce jointe.
Je veux prendre une capture d'écran de la page actuelle, puis la partager par courrier électronique, Bluetooth, Twitter ou Facebook.
Mon code est le suivant:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menuselected1, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.ScreenShot:
try {
takeScreenShot(this);
}
catch (Exception e) {
System.out.println(e);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private static void savePic(Bitmap b, String strFileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strFileName);
if (null != fos) {
b.compress(Bitmap.CompressFormat.PNG, 90, fos);
System.out.println("b is:"+b);
fos.flush();
fos.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void shoot(Activity a,String b) {
//savePic(takeScreenShot(a), "sdcard/xx.png");
savePic(takeScreenShot(a), b);
}
private static Bitmap takeScreenShot(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay()
.getHeight();
// Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return b;
}
Essayez ceci pour prendre une capture d'écran de l'activité en cours:
Android 2.2:
private static Bitmap takeScreenShot(Activity activity)
{
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
view.destroyDrawingCache();
return b;
}
private static void savePic(Bitmap b, String strFileName)
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(strFileName);
if (null != fos)
{
b.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
Si par "capture d'écran de la page en cours" vous voulez dire "capture d'écran de l'une de mes activités", vous pouvez organiser rendre votre Views
en une Canvas
avec sauvegarde bitmap, puis enregistrez une image à partir du bitmap .
Si par "capture d'écran de la page en cours", vous entendez "capture d'écran de l'activité de quelqu'un d'autre", cela n'est pas pris en charge par le SDK Android pour des raisons évidentes de confidentialité et de sécurité. Il existe diverses techniques que les utilisateurs d'appareils enracinés peuvent utiliser pour prendre des captures d'écran.
Je voulais le mien dans la barre d'action et j'ai donc créé un fichier share_menu.xml:
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<item
Android:id="@+id/share_item"
app:showAsAction="always|withText"
Android:title="Share"
Android:icon="@drawable/share_icon"
Android:actionProviderClass=
"Android.widget.ShareActionProvider" />
</menu>
Cela ajoute un bouton dans la barre d’action avec mon share_icon et le texte.
J'ai fait cela dans un fragment, j'ai donc ajouté le code ci-dessous à mon fichier fragment. Si vous êtes dans une activité, vous remplacez plutôt public boolean onCreateOptionsMenu(Menu menu)
.
@Override
public void onCreateOptionsMenu(
Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.share_menu, menu);
}
si vous faites cela avec un fragment, alors dans onCreate()
, vous devez ajouter:
setHasOptionsMenu(true);
C'est ce qui va lancer le partage.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.share_item){
Bitmap bm = screenShot(this.getView());
File file = saveBitmap(bm, "Mantis_image.png");
Log.i("chase", "filepath: "+file.getAbsolutePath());
Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, "Check out my app.");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "share via"));
}
return super.onOptionsItemSelected(item);
}
Notez que cela appelle deux méthodes magiques:
capture d'écran():
private Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
private static File saveBitmap(Bitmap bm, String fileName){
final String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Screenshots";
File dir = new File(path);
if(!dir.exists())
dir.mkdirs();
File file = new File(dir, fileName);
try {
FileOutputStream fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 90, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
Pour votre AndroidManifest.xml
, vous devez ajouter:
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />
ou bien la capture d'écran ne sera pas sauvegardée et Gmail pensera que vous essayez de joindre un fichier vide.
De plus, beaucoup de réponses SO indiquent qu'il faut utiliser "*/*"
pour shareIntent.setType()
, mais cela crée un problème avec le partage sur Facebook. Il est donc préférable de le laisser en tant que "image/*"
.
Voici comment j'ai capturé l'écran et partagé. Jetez un oeil si vous êtes intéressé.
public Bitmap takeScreenshot() {
View rootView = findViewById(Android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
Et la méthode qui enregistre l'image bitmap sur un stockage externe:
public void saveBitmap(Bitmap bitmap) {
File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}}
voir plus dans: https://www.youtube.com/watch?v=LRCRNvzamwY&feature=youtu.be
Kotlin complete solution Code avec vérification d'autorisation:
1- Utilisez cette bibliothèque Nice pour prendre une capture d'écran avec la fonctionnalité Java/Kotlin/Rx, ajoutez une dépendance à la bibliothèque: Lien github InstaCapture
implementation "com.github.tarek360:instacapture:2.0.1"
2- Doit vérifier l'autorisation de compatibilité sur toutes les versions d'Android:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) { // Needs permission so request it
DeviceUtil.showAlertMsg(this, GeneralDicModel.shareMsgScreenShot!!)
requestPermissions(
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
) //callback result to onRequestPermissionsResult
} else { //Has got the permission before or doesn't need
screenShotAndShareIt()
}
3- Vérifier le résultat de la permission:
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
screenShotAndShareIt()
} else {
// toast("Permission must be granted in order to save scrrenshot file")
}
}
}
}
4- Func appel à prendre Capture & Partager par intention:
fun screenShotAndShareIt() {
Instacapture.capture(this, object : SimpleScreenCapturingListener() {
override fun onCaptureComplete(bitmap: Bitmap) {
val state = Environment.getExternalStorageState()
if (Environment.MEDIA_MOUNTED == state) {
val path: String = Environment.getExternalStorageDirectory().toString()
val picDir = File(path.plus("/myPic"))
if (!picDir.exists()) {
picDir.mkdir()
}
var bitmapScreenShot = bitmap
val fileName = "screenshot" + ".jpg"
val picFile = File(picDir.path.plus("/" + fileName))
try {
picFile.createNewFile()
val picOut = FileOutputStream(picFile)
bitmapScreenShot =
Bitmap.createBitmap(bitmapScreenShot, 0, 0, bitmapScreenShot.width, bitmapScreenShot.height)
val saved: Boolean = bitmapScreenShot.compress(Bitmap.CompressFormat.JPEG, 100, picOut)
if (saved) {
Log.i(
TAG,
"ScreenShotAndShareIt : Image saved to your device Pictures " + "directory! + ${picFile.absolutePath}"
)
} else {
Log.i(TAG, "ScreenShotAndShareIt Error on Save! + ${picFile.absolutePath}")
}
picOut.close()
// share via intent
val intent: Intent = Intent(Android.content.Intent.ACTION_SEND)
intent.type = "image/jpeg"
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(picFile.absolutePath))
startActivity(Intent.createChooser(intent, "Sharing"))
} catch (e: Exception) {
Log.i(TAG, "ScreenShotAndShareIt Error catch : " + e.printStackTrace())
}
} else {
//Error
Log.i(TAG, "ScreenShotAndShareIt Error Environment.MEDIA_MOUNTED == state : " )
}
}
})
5- Déclarez cette variable:
val PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 100
6- N'oubliez pas d'ajouter ces autorisations à AndroidManifest.xml:
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>