Wenn Sie den Screenshot programmgesteuert aufnehmen, wird der Inhalt von surfaceVIew nicht erfasst

Ich habe eine App, die ich in der Lage sein werde, einen Screenshot zu erfassen. Der Hintergrund des Layouts ist ein surfaceView, das Video von der hinteren Kamera zeigt. Der folgende Code kann einen Screenshot machen, aber der Inhalt der surfaceView wird als schwarz gespeichert. Hier ist der Code:

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

Ich habe den Code aktualisiert. Jetzt schaffe ich 2 Bitmaps, 1 für das Layout xml und 1 für die surfaceView und dann übergebe ich sie in eine einzelne Bitmap. Aber die surfaceView-Bitmap ist immer noch schwarz

  • Gibt es eine maximale Größe zu Android internen Speicher für eine App zugeteilt?
  • Android: Statische Felder und Speicherlecks
  • Den für die Anwendung zugeteilten Speicherplatz erhöhen
  • Android: Wo ist das Memory Monitor Tool?
  • `/ Storage / emulated / legacy /` vs `/ storage / emuliert / 0 /` vs `data / data / myApp '
  • Android: Konstante Speicherverbrauch / dumpGfxInfo ()
  • Laden Sie den Sound aus dem Speicher in Android
  • Android NDK mmap Anruf gebrochen auf 32-Bit-Geräte nach dem Upgrade auf Lollipop
  • 2 Solutions collect form web for “Wenn Sie den Screenshot programmgesteuert aufnehmen, wird der Inhalt von surfaceVIew nicht erfasst”

    Das habe ich endlich gelöst. Im Folgenden gebe ich einen Code für alle, die wissen wollen, wie man Screenshots von einem Layout, Bilder von der Kamera ohne Absicht, Screenshots (Art von) des Inhalts einer Oberfläche zu nehmen und speichern Sie den Bildschirm in einem Ordner:

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

    Wenn du einen einfachen Screenshot machen möchtest (kein Kamera-Feed benötigt) kannst du die TakeScreenshot-Methode alleine nutzen.

    Wenn du einen Screenshot von einem surfaceView mit machen willst, ist es nicht möglich, von der surfaceview direkt zu benutzen, die das mPicture benutzen, das Bild, das du als backgroung erfassst, und dann TakeScreenshot anrufen, um deinen Screenshot zu machen (wie oben gesehen)

    Wenn du ein Foto mit der Kamera machen willst, ohne eine andere Kamera-App mit einer Absicht aufzurufen, benutze das takePicture mit dem mPicture und dem surfaceView Zeug aus dem obigen Code.

    Was der vorherige Code tut, wenn es "as is" verwendet wird, ist ein Screenshot des Layoutinhalts (Buttons, Bildansichten etc.) zu machen und als Backgroung ein Bild von der Kamera zu setzen.

    Im Folgenden habe ich auch ein Grundlayout xml für den vorherigen Code:

     <?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> 

    Vergessen Sie nicht zu importieren, was importiert werden muss

    Nach dem Kommentar ( https://groups.google.com/forum/#!topic/android-developers/jYjvm7ItpXQ ) von einem Android Framework-Ingenieur wird SurfaceView nicht wie eine normale Ansicht behandelt:

    Die oberflächliche Ansicht ist eigentlich HINTER dein Fenster, und ein Loch, das in das Fenster geschlagen wurde, um dich zu sehen. Du kannst also die Dinge in deinem Fenster auf sie legen, aber nichts in deinem Fenster kann dahinter erscheinen.

    Da es "BEHIND" das App-Fenster ist, würde folglich die Zeichnung für die Fensteransicht nicht enthalten. Ich denke, der einzige Weg ist dann, eine Methode in deiner SurfaceView-Klasse zur Verfügung zu stellen, um seinen eigenen Inhalt auf die bereitgestellte Leinwand / Bitmap zu zeichnen.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.