web-dev-qa-db-fra.com

Comment prendre une capture d'écran et la partager par programme

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;
}
26
user1025050

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();
    }
}
37
ρяσѕρєя K

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.

15
CommonsWare

1. Créer le bouton de partage

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.

2. Ajoutez le menu de partage à votre activité (ou fragment)

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);

3. Configurer l'action du bouton/callback/onclick

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;
}

Important

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/*".

4
Chase Roberts

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

0
Van Toan Vu

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"/>
0
Hamed Jaliliani