Taking Screenshot

2019-01-14 08:49发布

问题:

I'm developing an application for taking screenshots in the device. In this application, we can draw anything on the screen. For this I am using Canvas, Paint and Path to do this.

I'm using this code to take screenshots:

        public void saveScreenshot() 
    {
        if (ensureSDCardAccess()) 
        {
            Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            onDraw(canvas);
            File file = new File(mScreenshotPath + "/" + System.currentTimeMillis() + ".jpg");
            FileOutputStream fos;
            try {
                fos = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.e("Panel", "FileNotFoundException", e);
            } catch (IOException e) {
                Log.e("Panel", "IOEception", e);
            }
        }
    }

    /**
     * Helper method to ensure that the given path exists.
     * TODO: check external storage state
     */
    private boolean ensureSDCardAccess() {
        File file = new File(mScreenshotPath);
        if (file.exists()) {
            return true;
        } else if (file.mkdirs()) {
            return true;
        }
        return false;
    }

However, when the following line is run:

Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

my application closes with the following exception:

11-28 15:05:46.291: E/AndroidRuntime(8209): java.lang.IllegalArgumentException: width and height must be > 0

If I change the height and width, the screenshot is taken, but it's empty:

Why is that happening? What am I doing wrong?

回答1:

You can do it like this,

Give the id for your main Layout & after you display the content on the screen write the below code on some Listener say button click or menu item or any such Listener(make sure you call these line after your layout is display else it will give a blank screen).

        View content = findViewById(R.id.myLayout);
        content.setDrawingCacheEnabled(true);
        getScreen(content);

method getScreen(content)

private void getScreen(View content)
    {
        Bitmap bitmap = content.getDrawingCache();
        File file = new File("/sdcard/test.png");
        try 
        {
            file.createNewFile();
            FileOutputStream ostream = new FileOutputStream(file);
            bitmap.compress(CompressFormat.PNG, 100, ostream);
            ostream.close();
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }

Also don't for to add permission for writing file to SDCard.

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


回答2:

Exception is because the height and width of Bitmap you are creating is zero

try below code to get height and width

Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth();
int height = display.getHeight();

In case there is no access to getWindowManager

Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();


回答3:

getWidth(), getHeight() required to be called with context, if your are trying it outside Activity it will fail. Try getApplicationContext.getWidth().



回答4:

Could you show more of your code pls? It seems like you are calling width and height have not positive integer values. You could debug this by printing the values of width and height.



回答5:

I faced a similar issue and the solution was:

You get width and heigh before your view is drown so check first if width or heigh equal zero:

if (getWidth() == 0 || getHeight() == 0) {
            initRemote(remote);
            isViewInitialized=false;
        }

isViewInitialized is a member value.

Then put this code in OnSizeChanged

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);
        if(!isViewInitialized&&){
            // this is the right place to take snapshot :)
        }

    }


回答6:

I have wrapped the screenshot code into a very simple library. It allows you to take screenshots and store them to the disk if you want.

https://github.com/abdallahalaraby/Blink