Снимок экрана

Я разрабатываю приложение для снятия скриншотов в устройстве. В этом приложении мы можем рисовать что угодно на экране. Для этого я использую Canvas, Paint и Path.

Я использую этот код для создания скриншотов:

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

Однако, когда выполняется следующая строка:

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

мое приложение закрывается со следующим исключением:

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

Если я изменю высоту и ширину, снимок экрана будет сделан, но он будет пуст:

Пустой

Почему это происходит? Что я делаю неправильно?


person Praveenkumar    schedule 28.11.2011    source источник
comment
Куда вы звоните saveScreenshot?   -  person Krishnabhadra    schedule 28.11.2011
comment
@Krishnabhadra Это название моего метода. Есть ли проблема с этим именем метода?   -  person Praveenkumar    schedule 28.11.2011
comment
Я спросил, где вы вызвали функцию SaveScreenshot? Это в onCreate(), onResume()?   -  person Krishnabhadra    schedule 28.11.2011
comment
Нет, я создал пункт меню. И я звоню туда.   -  person Praveenkumar    schedule 28.11.2011
comment
Я думаю, что вы просто не получаете нужную ширину и высоту макета, вы можете получить его в методе onLayout.   -  person dreamtale    schedule 08.12.2011


Ответы (6)


Вы можете сделать это так,

Дайте идентификатор для вашего основного макета, и после того, как вы отобразите содержимое на экране, напишите приведенный ниже код на каком-либо прослушивателе, скажем, при нажатии кнопки или элементе меню или любом таком прослушивателе (убедитесь, что вы вызываете эту строку после отображения вашего макета, иначе он даст Пустой экран).

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

метод getScreen(содержимое)

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

Также не добавляйте разрешение на запись файла на SDCard.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
                                                               </uses-permission>
person Lalit Poptani    schedule 03.12.2011
comment
+1, теперь можно сделать снимок экрана любого отдельного вида/макета моего экрана... передав его как вид. - person MKJParekh; 29.11.2012

Исключением является то, что высота и ширина создаваемого вами Bitmap равны нулю.

попробуйте ниже код, чтобы получить высоту и ширину

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

В случае, если нет доступа к getWindowManager

Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
person ingsaurabh    schedule 28.11.2011
comment
да, ваш второй метод работает. Это пустой скриншот, но я написал текст Android на экране. - person Praveenkumar; 28.11.2011
comment
Это не относится к этому вопросу, есть проблема с вашим методом рисования. - person ingsaurabh; 28.11.2011
comment
Для этого поста отдельный вопрос публикует вам код onDraw и onTouch. - person ingsaurabh; 28.11.2011
comment
display.getWidth() и display.getHeight() использовать нельзя; они возвращают реальный размер всего дисплея, который не имеет обязательного отношения к фактическому размеру вашего пользовательского интерфейса на дисплее. - person hackbod; 07.12.2011

getWidth(), getHeight() необходимо вызывать с контекстом, если вы пытаетесь это сделать вне Activity, это не удастся. Попробуйте getApplicationContext.getWidth().

person ANUP    schedule 28.11.2011

Не могли бы вы показать больше вашего кода, пожалуйста? Кажется, что вы называете ширину и высоту не положительными целыми значениями. Вы можете отладить это, распечатав значения ширины и высоты.

person JustCurious    schedule 06.12.2011
comment
в порядке. Можете ли вы распечатать значения ширины и высоты, чтобы увидеть, что они содержат после инициализации? - person JustCurious; 10.12.2011

Я столкнулся с аналогичной проблемой, и решение было таким:

Вы получаете ширину и высоту до того, как ваш вид утонет, поэтому сначала проверьте, равна ли ширина или высота нулю:

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

isViewInitialized — это значение члена.

Затем поместите этот код в 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 :)
        }

    }
person Hisham Bakr    schedule 05.11.2013

Я завернул код скриншота в очень простую библиотеку. Это позволяет вам делать скриншоты и сохранять их на диск, если хотите.

https://github.com/abdallahalaraby/Blink

person Abdallah Alaraby    schedule 25.08.2016