3

I am taking screenshot programmatically using the following code:

public static Bitmap takeScreenshot(View view)
    {
        try
        {
            // create bitmap screen capture
            view.setDrawingCacheEnabled(true);
            Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
            view.setDrawingCacheEnabled(false);
            return bitmap;
        }
        catch (Throwable e)
        {
            CustomLogHandler.printError(e);
        }
        return null;
    }

private static void copyFile(Bitmap bitmap)
    {
        File dstFile = getShareResultFile();

        //Delete old file if exist.
        if(dstFile.exists()) {
            dstFile.delete();
        }

        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(dstFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);
            fos.flush();
        }
        catch (Exception e) {
            CustomLogHandler.printError(e);
        }
        finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException ioe) {
                    CustomLogHandler.printError(ioe);
                }
            }
        }
    }

There are several problem like:

  1. Back arrow, title and share menu background color is not correct. It looks messy.
  2. Background color of toolbar is totally changed.
  3. Image quality is too poor and list items rounded drawable has not smooth corners.
  4. Background of layout is not taken that I set as background of my parent layout.

I am taking the screenshot from the root view.

ma

Smeet
  • 4,036
  • 1
  • 36
  • 47
  • Please edit your question and show what you are doing with this `Bitmap`. For example, are you using `compress()` to write it to disk? – CommonsWare Apr 24 '19 at 12:15
  • 6
    Do you mean `programmatically` ? – Akram Apr 24 '19 at 12:15
  • @Merka programmatically I mean using code. Now Its clear to all I think. – Smeet Apr 24 '19 at 12:18
  • @CommonsWare Actually to keep the code smaller I didn't mention it here.I am saving it using bitmap.compress to external store. But you can focus on screenshot. – Smeet Apr 24 '19 at 12:19
  • 1
    "But why you down voted ?" -- I did not upvote or downvote your question. "I am saving it using bitmap.compress to external store" -- then your problem lies there, most likely. Please edit your question and show the code where you are using `compress()`. – CommonsWare Apr 24 '19 at 12:21
  • @CommonsWare oh sorry for that. let me put that code as well. – Smeet Apr 24 '19 at 12:22
  • 1
    you are compressing a JPG with 0 quality, change it to 90 or 100. Even if it does not resolve your problem, it will surely help. bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos); – Ricardo A. Apr 24 '19 at 12:41
  • @CommonsWare Problem resolved by setting background to layout instead of style. Many thanks for your quick reply and help. – Smeet Apr 24 '19 at 12:47

4 Answers4

5
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);

First, you are saving this as a JPEG. JPEG is designed for photos, and your screenshot is not a photo.

Second, you are saving this with a quality factor of 0. JPEG uses a lossy compression algorithm, and a quality factor of 0 says "please feel free to make this image be really poor, but compress it as far as you can".

I suggest switching to:

bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);

PNG is a better image format for a screenshot with the contents shown in your question. I don't think PNG uses the quality factor value; I put in 100 just to indicate that you want the best possible quality.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • You are right, the problem was with saving file. using 100% quality resolved my 1, 2, and 3rd points. Still background image is not appearing. It is taking simple plain black color. And JPG format's image quality is best than png, I am also surprise why this is. – Smeet Apr 24 '19 at 12:33
  • @Smeet: I am not certain what "the parent layout" means in your question. If this background is not *directly* implemented on the `View` that you pass to your `takeScreenshot()` method (or on children of that `View`), it has no chance of being in your image. Note that relying on the drawing cache is not a good plan; I recommend creating a `Bitmap`-backed `Canvas` and telling your `View` to `draw()` on that `Canvas`. – CommonsWare Apr 24 '19 at 12:35
  • I am setting it using @drawable/main_bg in style. – Smeet Apr 24 '19 at 12:37
  • Note that relying on the drawing cache is not a good plan; I recommend creating a Bitmap-backed Canvas and telling your View to draw() on that Canvas - Can you please suggest code or link for the same ? – Smeet Apr 24 '19 at 12:38
  • see my answer below how to use Canvas instead of cache – gordinmitya Apr 24 '19 at 12:38
  • 1
    window background doesn't relate to any view in activity, it's related to activity itself. put your background in view hierarchy like `` – gordinmitya Apr 24 '19 at 12:41
3
public static Bitmap takeScreenshot(View view)
{
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}

This code can save view as bitmap. But after you update your question with save code I see that you set 0 for quality, and what you expect?

@param quality  Hint to the compressor, 0-100. 0 meaning compress for
     *                 small size, 100 meaning compress for max quality. Some
     *                 formats, like PNG which is lossless, will ignore the
     *                 quality setting

just use your Ctrl button + click on method name to read doc about params

the answer is set second parameter 100 instead of 0!

gordinmitya
  • 967
  • 10
  • 10
2

Try using this:

  public static Bitmap loadBitmapFromView(Context context, View v) {
        DisplayMetrics dm = context.getResources().getDisplayMetrics(); 
        v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
        v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
                v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(returnedBitmap);
        v.draw(c);

        return returnedBitmap;
    }

and

public void takeScreen() {
    Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
    String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
    File imageFile = new File(mPath);
    OutputStream fout = null;
    try {
        fout = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
        fout.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        fout.close();
    }
}

Images are saved in the external storage folder.

Rishabh Saxena
  • 1,765
  • 15
  • 26
1

try this

private void captureScreen() {
     View v =  this.getWindow().getDecorView().findViewById(android.R.id.content);
    v.setDrawingCacheEnabled(true);
    Bitmap bitmap = v.getDrawingCache();
    String extr = Environment.getExternalStorageDirectory().toString();
    File file = new File(extr, getString(R.string.free_tiket) + ".jpg");
    FileOutputStream f = null;
    try {
        f = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, f);
        f.flush();
        f.close();
        MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Screen", "screen");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Sajith
  • 713
  • 6
  • 21
  • using 100% quality resolved my 1, 2, and 3rd points. Still background image is not appearing. It is taking simple plain black color. – Smeet Apr 24 '19 at 12:31