How to take a screenshot and share it programmatically

后端 未结 5 844
半阙折子戏
半阙折子戏 2020-12-02 05:40

I am making an application in Android in which I have to take screenshot of one of my activities and mail it as attachment.

I want to take screenshot of the current

相关标签:
5条回答
  • 2020-12-02 06:01

    1. Create the share button

    I wanted mine in the action bar so I created a share_menu.xml file:

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

    This adds a button in the action bar with my share_icon and the text.

    2. Add the sharing menu to your activity (or fragment)

    I did this inside a fragment so I added the code below to my fragment file. If you are inside an activity then you override public boolean onCreateOptionsMenu(Menu menu) instead.

    @Override
    public void onCreateOptionsMenu(
            Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.share_menu, menu);
    }
    

    if you are doing this with a fragment then in onCreate() you have to add:

    setHasOptionsMenu(true);
    

    3. Set up button action/callback/onclick

    This is what is going to kick off the sharing.

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

    Notice this calls two magic methods:

    screenShot():

    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

    To your AndroidManifest.xml, you have to add:

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

    or the screenshot won't be saved, and gmail will think you are trying to attach an empty file.

    Also, a lot of SO answers say to use "*/*" for shareIntent.setType() but this creates an issue with facebook sharing, so it's best to leave it as "image/*".

    0 讨论(0)
  • 2020-12-02 06:10

    Try this for taking screenshot of current Activity:

    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;
    
        DisplayMetrics displaymetrics = new DisplayMetrics(); 
        mContext.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    
        int width = displaymetrics.widthPixels;
        int height = displaymetrics.heightPixels;
    
        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();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 06:10

    If by "screenshot of current page" you mean "screenshot of one of my activities", you can arrange to render your Views to a bitmap-backed Canvas, then save an image from the bitmap.

    If by "screenshot of current page" you mean "screenshot of somebody else's activity", that is not supported by the Android SDK, for obvious privacy and security reasons. There are various techniques that rooted device users can use to take screenshots.

    0 讨论(0)
  • 2020-12-02 06:15

    This is how I captured the screen and shared it. Take a look if you are interested.

    public Bitmap takeScreenshot() {
      View rootView = findViewById(android.R.id.content).getRootView();
      rootView.setDrawingCacheEnabled(true);
    return rootView.getDrawingCache();
     }
    

    And the method that saves the bitmap image to external storage:

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

    see more in : https://www.youtube.com/watch?v=LRCRNvzamwY&feature=youtu.be

    0 讨论(0)
  • 2020-12-02 06:22

    Kotlin complete solution Code with permission check :

    1- Use this nice library to take screen shot with java / Kotlin / Rx functionality, add library dependency : InstaCapture github link

     implementation "com.github.tarek360:instacapture:2.0.1"
    

    2- Must check permission for compatibility on all android versions:

         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- Check permission result :

     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 call for take Screenshot & Share it by intent :

     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- Declare this variable :

    val PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 100
    

    6- Do not forget to Add this permissions to AndroidManifest.xml:

        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    0 讨论(0)
提交回复
热议问题