1

I am working on an app, which uses the frontcamera to simulate a mirror for the person using the app. I have implemented a "Head-up-Display" which is in front of the cameraview and displays some stuff. This works fine at the moment. Now I'd like to implement a method to take a screenshot every 5s.

But how to take a screenshot? I tried one possible solution, but this just takes a screenshot of the HuD without the mirror, because I have to pass a view (v1) to this method:

    // create bitmap screen capture
    Bitmap b1;

    View v1 = (RelativeLayout) findViewById(R.id.RelLayout);
    v1.setDrawingCacheEnabled(true);
    b1 = Bitmap.createBitmap(v1.getDrawingCache());
    v1.setDrawingCacheEnabled(false);

    //mPreviewLayout.setDrawingCacheEnabled(true);
    //mPreviewLayout.buildDrawingCache();
    //Bitmap b1 = mPreviewLayout.getDrawingCache();

    String path = Environment.getExternalStorageDirectory().toString();
    FileOutputStream out = null;
    try {
        File file = new File(path, "brushGuide" + instructionCounter + ".jpg");
        out = new FileOutputStream(file);
        b1.compress(Bitmap.CompressFormat.PNG, 90, out);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            out.close();
        } catch (Throwable ignore) {
        }
    }

My layout and the important code for this question is quite less:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    android:id="@+id/RelLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal" >

<FrameLayout
    android:id="@+id/camPreview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true" >
</FrameLayout>

 <ImageView android:id="@+id/imageView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginTop="80dp"
          android:layout_marginLeft="65dp"
          ></ImageView>

</RelativeLayout>

onCreate()

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

 // do we have a camera?
 if (!getPackageManager()
        .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
    Toast.makeText(this,
            "No camera feature on this device. App closing",
            Toast.LENGTH_LONG).show();
 }else{

    mCameraId = findFirstFrontFacingCamera();

    if (mCameraId >= 0) {
        // Kamera wurde gefunden
        mPreviewLayout = (FrameLayout) findViewById(R.id.camPreview);
        mPreviewLayout.removeAllViews();
        startCameraInLayout(mPreviewLayout, mCameraId);
    }
  }
}

Is even possible to just take a normal screenshot of the actual content of the devices display without rooting the device, and if yes: How?

Any help will be appreciated.

moobi
  • 7,849
  • 2
  • 18
  • 29

3 Answers3

3

I actually just did this the other day and it was a pain to get a screenshot of the entire Activity, while also making sure to remove the StatusBar from the image (as it will appear as a black rectangle in the drawing cache). This method will also allow you to overlay the returned image with some color (ie. fading)):

public static Bitmap getActivitySnapshot(Activity activity, boolean fade){
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    Bitmap bmap = view.getDrawingCache();

    Rect statusBar = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(statusBar);
    Bitmap snapshot = Bitmap.createBitmap(bmap, 0, statusBar.top, bmap.getWidth(), bmap.getHeight() - statusBar.top, null, true);

    if(fade && snapshot != null){
        Canvas canvas = new Canvas(snapshot);
        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#88121212"));
        canvas.drawRect(0, 0, snapshot.getWidth(), snapshot.getHeight(), paint);
    }

    view.setDrawingCacheEnabled(false);
    return snapshot;
}

If you don't want the fading part, the important parts would just be:

public static Bitmap getActivitySnapshot(Activity activity){
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    Bitmap bmap = view.getDrawingCache();

    Rect statusBar = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(statusBar);
    Bitmap snapshot = Bitmap.createBitmap(bmap, 0, statusBar.top, bmap.getWidth(), bmap.getHeight() - statusBar.top, null, true);

    view.setDrawingCacheEnabled(false);
    return snapshot;
}

You may also want to catch the OutOfMemoryError that may be thrown when working with large Bitmaps.

Cruceo
  • 6,763
  • 2
  • 31
  • 52
  • thanks for your reply. But there is one problem with all answers, yours including: The bitmap just contains the picture of the HUD, not of the hud AND the running camera in the background. – moobi May 28 '14 at 12:35
  • If you're trying to get the Camera Preview (most likely from the FrameLayout at the the root of your layout? Correct me if I'm wrong), then my method won't work, as the camera's preview is not a part of the drawing cache (if I remember correctly...), which means you will have to get both the Activity snapshot and overlay that on top of the image returned by getting the image from the camera. This should help you do that: http://stackoverflow.com/a/11838480/1426565 – Cruceo May 28 '14 at 15:50
  • 1
    I used your method to take a image of the hud and another one to take a picture with the camera and merged them later. Thanks for the help – moobi Aug 28 '14 at 10:09
  • very good snippet that solves catching the action bar, thanks a bunch!! – marko.petrovic Oct 08 '14 at 14:36
0

This code can help you.

    /**
 * @param v view to capture it may be any Layout
 * @return
 */
 public static Bitmap captureScreen(View v)
 {
 Bitmap bitmap = null;

 try {
 if(v!=null)
 {
 int width = v.getWidth();
 int height = v.getHeight();

 Bitmap screenshot = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
 v.draw(new Canvas(screenshot));
 }
 } catch (Exception e)
 {
 Log.d("captureScreen", "Failed");
 }

 return bitmap;
 }
Chefes
  • 1,892
  • 18
  • 17
0

By screenshot, would a copy of your Root view help?

If so, you can use this:

public static Bitmap loadBitmapFromView(View view) {
    Bitmap bitmap = Bitmap.createBitmap(view.getLayoutParams().width, view.getLayoutParams().height, Bitmap.Config.ARGB_8888);                
    Canvas canvas = new Canvas(bitmap);
    view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
    view.draw(canvas);
    return bitmap;
}

Just pass your root view into this function and you can save the bitmap.

David Xu
  • 5,555
  • 3
  • 28
  • 50
  • when I loke to run this code, eclipse jumps into the Bitmap.class file and sets its debugging cursor to "return b" in the createScaledBitmap()-method. What am I doing wrong? – moobi May 14 '14 at 17:32
  • Did you get a stack trace or anything? – David Xu May 14 '14 at 17:40