Программное создание снимка экрана с Surfaceview в Android

У меня есть проект, который использует SurfaceView для рисования некоторых вещей на экране. Пользователь должен иметь возможность сделать снимок экрана, нажав кнопку на этом экране. Проблема в том, что я всегда получаю пустой экран, когда снимается скриншот с SurfaceView. Я пробовал много разных ответов, но ни один из них не помог мне. Вот что я пробовал:

void takeScre() {
        File file = saveBitmap(getBitmap());
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(file), "image/*");
        startActivity(intent);
    }
    
    Bitmap getBitmap() {
        dots_screen_view.setDrawingCacheEnabled(true);
        return dots_screen_view.getDrawingCache();
    }

// ----------

 Bitmap getBitmap() {
        Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        dots_screen_view.draw(c);

        return b;
    }

// -----------

Bitmap getBitmap() {
        Bitmap b = Bitmap.createBitmap(dots_screen_view.getWidth() , dots_screen_view.getHeight(), Bitmap.Config.ARGB_8888);
        dots_screen_view.setDrawingCacheEnabled(false);
        dots_screen_view.layout(0, 0, dots_screen_view.getLayoutParams().width, dots_screen_view.getLayoutParams().height);
        dots_screen_view.draw(new Canvas(b));

        return b;
    }

Также я пробовал эти библиотеки:

https://android-arsenal.com/details/1/6985

https://android-arsenal.com/details/1/6163

https://android-arsenal.com/details/3/5293

Однако ни один из них у меня не работает. Есть другие идеи?

какое исключение вы получаете?

Jitesh Mohite 23.07.2018 09:44

Я не получаю никаких исключений, но вывод файла пустой (где вид поверхности) элементы

David 23.07.2018 09:49

Взгляните хоть раз stackoverflow.com/questions/27817577/…

Akash 23.07.2018 09:58
0
3
408
3

Ответы 3

Попробуйте Селфи ... Я без проблем использовал его для создания сообщений в социальных сетях. Его открытый исходный код, поэтому, если он работает, вы можете понять, почему он работает :)

Попробуйте код ниже:

/**
    * Check for permissions and create a snapshot
    *
    * @param activity Activity used by Selfie.
    * @return {@code true} if the screenshot was taken, false otherwise.
    */
   public boolean snap(Activity activity) {
      boolean hasPermission = (ContextCompat.checkSelfPermission(activity,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
      if (!hasPermission) {
         ActivityCompat.requestPermissions(activity,
               new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
               REQUEST_WRITE_STORAGE);
         return false;
      } else {
         return takeScreenShot(activity);
      }
   }

   /**
    * This method is responsible for taking the screenshot and creating a file
    *
    * @param activity Activity used by Selfie.
    * @return {@code true} if the screenshot was taken, false otherwise.
    */
   private boolean takeScreenShot(Activity activity) {
      Date now = new Date();
      android.text.format.DateFormat.format(fileFormat, now);

      // create bitmap screen capture
      View v1 = activity.getWindow().getDecorView().getRootView();
      v1.setDrawingCacheEnabled(true);
      Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
      v1.setDrawingCacheEnabled(false);

      // image naming and path to include sd card appending name you choose for file
      String path = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";

      File imageFile = new File(path);

      try {
         FileOutputStream outputStream = new FileOutputStream(imageFile);
         bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
         outputStream.flush();
         outputStream.close();
      } catch (IOException ex) {
         return false;
      }

      return true;
   }

Пожалуйста, добавьте разрешение на запись внутри манифеста:

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

Нет, у меня это не сработало. По-прежнему отображается пустой экран с элементом Surfaceview :(

David 23.07.2018 09:57

вы проверили внутри sdcard? какое изображение сохраняется

Jitesh Mohite 23.07.2018 10:00

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

Попробуйте следующий код

public String getBitmapFromView() {

    int dwidth,dheight;
    DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
    if (displayMetrics.widthPixels > displayMetrics.heightPixels)
    {
        //orientation is landscape
        dwidth=displayMetrics.heightPixels;
        dheight=displayMetrics.widthPixels;
    }
    else
    {
        dwidth = displayMetrics.widthPixels;
        dheight=displayMetrics.heightPixels;
    }

    setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    //If the view wasnt displayed before this , you will get 0,0 measured widths and heights
    //Thus measure the layout
    measure(MeasureSpec.makeMeasureSpec(dwidth, MeasureSpec.AT_MOST),MeasureSpec.makeMeasureSpec(dheight, MeasureSpec.AT_MOST));

    layout(0, 0, getMeasuredWidth(), getMeasuredHeight());

    //Create a bitmap backed Canvas to draw the into
    Bitmap bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        if (getMeasuredWidth() == 0 && getMeasuredHeight() == 0) {
          //You will get blank bitmap
            return "";
        } else {
            Canvas c = new Canvas(bitmap);

            //Now that the view is here and we have a canvas, ask the to draw itself into the canvas
            draw(c);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 60, stream);
            byte[] byteArray = stream.toByteArray();
            return Base64.encodeToString(byteArray, Base64.DEFAULT);
        }

}

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

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