Делаем скриншот программно в андроиде

Я делаю скриншот программно, используя следующий код:

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

Есть несколько проблем, таких как:

  1. Неправильный цвет фона стрелки назад, заголовка и общего меню. Это выглядит грязно.
  2. Цвет фона панели инструментов полностью изменен.
  3. Качество изображения слишком низкое, а скругленные элементы списка не имеют ровных углов.
  4. Фон макета не берется, который я установил в качестве фона моего родительского макета.

Я делаю скриншот из корневого режима.

Делаем скриншот программно в андроиде

Пожалуйста, отредактируйте свой вопрос и покажите, что вы делаете с этим Bitmap. Например, вы используете compress() для записи на диск?

CommonsWare 24.04.2019 14:15

Вы имеете в виду programmatically ?

Akram 24.04.2019 14:15

@Merka программно, я имею в виду использование кода. Теперь это ясно для всех, я думаю.

Smeet 24.04.2019 14:18

@CommonsWare На самом деле, чтобы уменьшить размер кода, я не упомянул его здесь. Я сохраняю его с помощью bitmap.compress во внешнем хранилище. Но вы можете ориентироваться на скриншот.

Smeet 24.04.2019 14:19

«Но почему вы проголосовали против?» -- Я не голосовал ни за, ни против вашего вопроса. «Я сохраняю его с помощью bitmap.compress во внешнее хранилище» - тогда, скорее всего, ваша проблема заключается в нем. Пожалуйста, отредактируйте свой вопрос и покажите код, где вы используете compress().

CommonsWare 24.04.2019 14:21

@CommonsWare, извините за это. позвольте мне также поставить этот код.

Smeet 24.04.2019 14:22

вы сжимаете JPG с качеством 0, измените его на 90 или 100. Даже если это не решит вашу проблему, это обязательно поможет. bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);

Ricardo A. 24.04.2019 14:41

@CommonsWare Проблема решена путем установки фона на макет вместо стиля. Большое спасибо за быстрый ответ и помощь.

Smeet 24.04.2019 14:47
3
8
4 977
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Этот код может сохранить вид как растровое изображение. Но после того, как вы обновите свой вопрос с помощью кода сохранения, я вижу, что вы установили 0 для качества, и чего вы ожидаете?

@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

просто используйте кнопку Ctrl + щелкните имя метода, чтобы прочитать документ о параметрах

ответ установлен вторым параметром 100 вместо 0!

Ответ принят как подходящий
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);

Во-первых, вы сохраняете это как JPEG. JPEG предназначен для фотографий, и ваш скриншот не является фотографией.

Во-вторых, вы сохраняете это с коэффициентом качества 0. JPEG использует алгоритм сжатия с потерями, а коэффициент качества 0 говорит: «Пожалуйста, не стесняйтесь делать это изображение очень плохим, но сожмите его настолько, насколько сможете».

Предлагаю перейти на:

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

PNG — лучший формат изображения для снимка экрана с содержимым, показанным в вашем вопросе. Я не думаю, что PNG использует значение коэффициента качества; Я поставил 100 только для того, чтобы указать, что вы хотите получить максимально возможное качество.

Вы правы, проблема была с сохранением файла. использование 100% качества решило мои 1, 2 и 3-й пункты. Неподвижное фоновое изображение не появляется. Он принимает простой простой черный цвет. И качество изображения в формате JPG лучше, чем в png, я также удивлен, почему это так.

Smeet 24.04.2019 14:33

@Smeet: я не уверен, что означает «родительский макет» в вашем вопросе. Если этот фон не реализован напрямую в View, который вы передаете своему takeScreenshot() методу (или в дочерних элементах этого View), у него нет шансов оказаться на вашем изображении. Обратите внимание, что полагаться на кеш чертежей — не лучший план; Я рекомендую создать Bitmap-поддерживаемый Canvas и рассказать об этом своим Viewdraw()Canvas.

CommonsWare 24.04.2019 14:35

Я устанавливаю его, используя стиль <item name = "android:windowBackground">@drawable/main_bg</item>.

Smeet 24.04.2019 14:37

Обратите внимание, что полагаться на кеш чертежей — не лучший план; Я рекомендую создать холст с поддержкой растрового изображения и указать вашему представлению рисовать () на этом холсте. Не могли бы вы предложить код или ссылку для того же самого?

Smeet 24.04.2019 14:38

см. мой ответ ниже, как использовать Canvas вместо кеша

gordinmitya 24.04.2019 14:38

фон окна не относится к какому-либо виду в действии, он связан с самим действием. поместите свой фон в иерархию просмотра, например <FrameLayout><ImageView *you backgound here/><Other views/></FrameLayout>

gordinmitya 24.04.2019 14:41

попробуй это

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

использование 100% качества решило мои 1, 2 и 3-й пункты. Неподвижное фоновое изображение не появляется. Он принимает простой простой черный цвет.

Smeet 24.04.2019 14:31

Попробуйте использовать это:

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

а также

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

Изображения сохраняются во внешней папке хранения.

Другие вопросы по теме