Выполнение скриншота программно не захватывает содержимое поверхности

У меня есть приложение, которое я хочу, чтобы захватить снимок экрана. Фон макета – это surfaceView, который показывает видео с задней камеры. Следующий код способен сделать снимок экрана, но содержимое поверхностиView сохраняется как черный. Вот код:

btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { Random num = new Random(); int nu=num.nextInt(1000); Bitmap bmp; CamView.setDrawingCacheEnabled(true); CamView.buildDrawingCache(true); Bitmap bmp2 = Bitmap.createBitmap(CamView.getDrawingCache()); //Screenshot of the layout CamView.setDrawingCacheEnabled(false); SurView.setDrawingCacheEnabled(true); SurView.buildDrawingCache(true); Bitmap bmp1 = Bitmap.createBitmap(SurView.getDrawingCache()); //Screenshot of the surfaceView SurView.setDrawingCacheEnabled(false); Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(),bmp1.getConfig()); Canvas canvas = new Canvas(bmOverlay); //Overlaying the 2 bitmaps canvas.drawBitmap(bmp1, 0,0, null); canvas.drawBitmap(bmp2, 0,0, null); bmp=bmOverlay; //saving the file ByteArrayOutputStream bos = new ByteArrayOutputStream(); bmp.compress(CompressFormat.JPEG, 100, bos); byte[] bitmapdata = bos.toByteArray(); ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata); String picId=String.valueOf(nu); String myfile="Ghost"+picId+".jpeg"; File dir_image = new File(Environment.getExternalStorageDirectory()+ File.separator+"Ultimate Entity Detector"); dir_image.mkdirs(); try { File tmpFile = new File(dir_image,myfile); FileOutputStream fos = new FileOutputStream(tmpFile); byte[] buf = new byte[1024]; int len; while ((len = fis.read(buf)) > 0) { fos.write(buf, 0, len); } fis.close(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); 

Я обновил код. Теперь я создаю 2 растровых изображения, 1 для макета xml и 1 для surfaceView, а затем я накладываю их на одно растровое изображение. Но растровое изображение surfaceView по-прежнему черное

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

 public class Cam_View extends Activity implements SurfaceHolder.Callback { protected static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0; private SurfaceView SurView; private SurfaceHolder camHolder; private boolean previewRunning; final Context context = this; public static Camera camera = null; private RelativeLayout CamView; private Bitmap inputBMP = null, bmp, bmp1; private ImageView mImage; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camera); CamView = (RelativeLayout) findViewById(R.id.camview);//RELATIVELAYOUT OR //ANY LAYOUT OF YOUR XML SurView = (SurfaceView)findViewById(R.id.sview);//SURFACEVIEW FOR THE PREVIEW //OF THE CAMERA FEED camHolder = SurView.getHolder(); //NEEDED FOR THE PREVIEW camHolder.addCallback(this); //NEEDED FOR THE PREVIEW camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//NEEDED FOR THE PREVIEW camera_image = (ImageView) findViewById(R.id.camera_image);//NEEDED FOR THE PREVIEW Button btn = (Button) findViewById(R.id.button1); //THE BUTTON FOR TAKING PICTURE btn.setOnClickListener(new OnClickListener() { //THE BUTTON CODE public void onClick(View v) { camera.takePicture(null, null, mPicture);//TAKING THE PICTURE //THE mPicture IS CALLED //WHICH IS THE LAST METHOD(SEE BELOW) } }); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,//NEEDED FOR THE PREVIEW int height) { if(previewRunning) { camera.stopPreview(); } Camera.Parameters camParams = camera.getParameters(); Camera.Size size = camParams.getSupportedPreviewSizes().get(0); camParams.setPreviewSize(size.width, size.height); camera.setParameters(camParams); try { camera.setPreviewDisplay(holder); camera.startPreview(); previewRunning=true; } catch(IOException e) { e.printStackTrace(); } } public void surfaceCreated(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW try { camera=Camera.open(); } catch(Exception e) { e.printStackTrace(); Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show(); finish(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW camera.stopPreview(); camera.release(); camera=null; } public void TakeScreenshot(){ //THIS METHOD TAKES A SCREENSHOT AND SAVES IT AS .jpg Random num = new Random(); int nu=num.nextInt(1000); //PRODUCING A RANDOM NUMBER FOR FILE NAME CamView.setDrawingCacheEnabled(true); //CamView OR THE NAME OF YOUR LAYOUR CamView.buildDrawingCache(true); Bitmap bmp = Bitmap.createBitmap(CamView.getDrawingCache()); CamView.setDrawingCacheEnabled(false); // clear drawing cache ByteArrayOutputStream bos = new ByteArrayOutputStream(); bmp.compress(CompressFormat.JPEG, 100, bos); byte[] bitmapdata = bos.toByteArray(); ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata); String picId=String.valueOf(nu); String myfile="Ghost"+picId+".jpeg"; File dir_image = new File(Environment.getExternalStorageDirectory()+//<--- File.separator+"Ultimate Entity Detector"); //<--- dir_image.mkdirs(); //<--- //^IN THESE 3 LINES YOU SET THE FOLDER PATH/NAME . HERE I CHOOSE TO SAVE //THE FILE IN THE SD CARD IN THE FOLDER "Ultimate Entity Detector" try { File tmpFile = new File(dir_image,myfile); FileOutputStream fos = new FileOutputStream(tmpFile); byte[] buf = new byte[1024]; int len; while ((len = fis.read(buf)) > 0) { fos.write(buf, 0, len); } fis.close(); fos.close(); Toast.makeText(getApplicationContext(), "The file is saved at :SD/Ultimate Entity Detector",Toast.LENGTH_LONG).show(); bmp1 = null; camera_image.setImageBitmap(bmp1); //RESETING THE PREVIEW camera.startPreview(); //RESETING THE PREVIEW } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private PictureCallback mPicture = new PictureCallback() { //THIS METHOD AND THE METHOD BELOW //CONVERT THE CAPTURED IMAGE IN A JPG FILE AND SAVE IT @Override public void onPictureTaken(byte[] data, Camera camera) { File dir_image2 = new File(Environment.getExternalStorageDirectory()+ File.separator+"Ultimate Entity Detector"); dir_image2.mkdirs(); //AGAIN CHOOSING FOLDER FOR THE PICTURE(WHICH IS LIKE A SURFACEVIEW //SCREENSHOT) File tmpFile = new File(dir_image2,"TempGhost.jpg"); //MAKING A FILE IN THE PATH //dir_image2(SEE RIGHT ABOVE) AND NAMING IT "TempGhost.jpg" OR ANYTHING ELSE try { //SAVING FileOutputStream fos = new FileOutputStream(tmpFile); fos.write(data); fos.close(); //grabImage(); } catch (FileNotFoundException e) { Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show(); } catch (IOException e) { Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show(); } String path = (Environment.getExternalStorageDirectory()+ File.separator+"Ultimate EntityDetector"+ File.separator+"TempGhost.jpg");//<--- BitmapFactory.Options options = new BitmapFactory.Options();//<--- options.inPreferredConfig = Bitmap.Config.ARGB_8888;//<--- bmp1 = BitmapFactory.decodeFile(path, options);//<--- *********(SEE BELOW) //THE LINES ABOVE READ THE FILE WE SAVED BEFORE AND CONVERT IT INTO A BitMap camera_image.setImageBitmap(bmp1); //SETTING THE BitMap AS IMAGE IN AN IMAGEVIEW(SOMETHING //LIKE A BACKGROUNG FOR THE LAYOUT) tmpFile.delete(); TakeScreenshot();//CALLING THIS METHOD TO TAKE A SCREENSHOT //********* THAT LINE MIGHT CAUSE A CRASH ON SOME PHONES (LIKE XPERIA T)<----(SEE HERE) //IF THAT HAPPENDS USE THE LINE "bmp1 =decodeFile(tmpFile);" WITH THE METHOD BELOW } }; public Bitmap decodeFile(File f) { //FUNCTION BY Arshad Parwez Bitmap b = null; try { // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; FileInputStream fis = new FileInputStream(f); BitmapFactory.decodeStream(fis, null, o); fis.close(); int IMAGE_MAX_SIZE = 1000; int scale = 1; if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { scale = (int) Math.pow( 2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5))); } // Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; fis = new FileInputStream(f); b = BitmapFactory.decodeStream(fis, null, o2); fis.close(); } catch (IOException e) { e.printStackTrace(); } return b; } } 

Если вы хотите сделать простой скриншот (нет необходимости в канале камеры), вы можете использовать метод TakeScreenshot самостоятельно.

Если вы хотите сделать снимок экрана с помощью поверхностного экрана, с помощью функции mPicture невозможно сделать снимок экрана, установите изображение, которое вы снимаете в качестве backgroung, а затем вызовите TakeScreenshot, чтобы сделать снимок экрана (как видно выше)

Если вы хотите сделать снимок с помощью камеры без вызова другого приложения камеры с намерением использовать takePicture с mPicture и материалом surfaceView из приведенного выше кода.

Что делает предыдущий код, если используется «как есть», это сделать снимок экрана с содержимым макета (кнопки, изображения и т. Д.) И установить в качестве заднего изображения изображение с камеры.

Ниже я также предоставил базовый макет xml для предыдущего кода:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/camview"> <SurfaceView android:id="@+id/sview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" /> <ImageView android:id="@+id/camera_image" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@string/app_name" /> <Button android:id="@+id/button1" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" /> </RelativeLayout> 

Не забывайте импортировать то, что нужно импортировать

Согласно комментарию ( https://groups.google.com/forum/#!topic/android-developers/jYvm7ItpXQ ) инженером Android Framework, SurfaceView не обрабатывается как обычный вид:

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

Так как это «BEHIND» окно приложения, следовательно, чертеж для представления окна не будет содержать его. Я полагаю, что единственный способ предоставить метод в классе SurfaceView для рисования собственного контента на предоставленный Canvas / Bitmap.