Android Taking Screenshot of Offscreen Page

android taking screenshot of offscreen page

Well I have achieved what I want. These are the steps I used.

  1. Start activity B with startActivityForResult() instead of
    startActivity().

    Intent bIntent = new Intent(A.this,B.class);
    startActivityForResult(bIntent,B_REQUEST_CODE);
  2. In onCreate of activity B take mainLayout of B and enable its
    drawing cache

    final LinearLayout layout = (LinearLayout)
    findViewById(R.id.app_parent_layout);
    layout.setDrawingCacheEnabled(true);
    layout.setDrawingCacheQuality(LinearLayout.DRAWING_CACHE_QUALITY_HIGH);
  3. In activity B wait till its layout is drawn completely(This is very
    important). For that in onCreate() of activity B, get mainLayout of
    B, use ViewTreeObserver to get a call back when its layout is drawn
    completely.

    ViewTreeObserver vto = layout.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
    layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    getDrawingBitmap();
    }
    });
  4. Now getDrawingBitmap() gets called when layout is drawn completely.
    There take your screenshot.

    public void getDrawingBitmap(){
    LinearLayout mainLayout = (LinearLayout)
    findViewById(R.id.app_parent_layout);
    Bitmap b = mainLayout.getDrawingCache();

    File file = saveBitmapAsFile(b);

    Intent resultIntent = new Intent();
    resultIntent.putExtra("FullFileName",file.getAbsolutePath());
    setResult(Activity.RESULT_OK,resultIntent);
    finish();
    }

    Here I am taking bitmap and saving it as a file and returning the
    filename as a result code. I am sure there are better method to send
    the bitmap to parent activity than saving as a file and sending
    filename. But I have a requirement anyway to save bitmap for
    sometime. So For me this is the easier method. After setting result
    finish activity.

  5. Now on Activity A onActivityResult() retrieve the filename.

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == B_REQUEST_CODE){
    if (resultCode == Activity.RESULT_OK) {
    String newText = data.getStringExtra("FullFileName");
    File dir = new File (newText);
    }
    }
    }

screenshot of all Views in ViewPager

If you don't set offScreenPageLimit(totalPages), ViewPager will initially only load 1 more page other than you see. That means other pages will not be even created until you swipe there. That also means you cannot take screenshot of a screen/layout that is not created/inflated yet. And yes, it is not a good practice memorywise to set offscreen page limit to a number that ViewPager loads all pages at start.

Answer: No, if you mind your memory consumption. Otherwise, yes.

Taking a screenshot of a specific layout in Android

Thanks to you guys, I've finally found out what was wrong.

View v = view.getRootView(); should not be used because it will call the root view which I do not want. I mistakenly thought this did not make a difference because I had entered the wrong resource ID.

MeasureSpec somehow did not give a good account of the width and height. So I ended up using another method:

...
ScrollView z = (ScrollView) findViewById(R.id.scroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
u.layout(0, 0, totalWidth, totalHeight);
...

As ScrollView's total height can be determined by the single child element that it has.

After making these changes, I am now able to take a screenshot of a nested ScrollView and all its contents, visible or not. For anyone interested, here is the block of code including the saving of the bitmap:

            View u = findViewById(R.id.scroll);
u.setDrawingCacheEnabled(true);
ScrollView z = (ScrollView) findViewById(R.id.scroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
u.layout(0, 0, totalWidth, totalHeight);
u.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
u.setDrawingCacheEnabled(false);

//Save bitmap
String extr = Environment.getExternalStorageDirectory().toString() + File.separator + "Folder";
String fileName = new SimpleDateFormat("yyyyMMddhhmm'_report.jpg'").format(new Date());
File myPath = new File(extr, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Take a screenshot of a whole View

Actually I found the answer:

public static Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth() , v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}

Capture screenshot of a HorizontalScrollView including offscreen elements

Found a SIMPLE way to do it.

XML

        <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:layout_gravity="center_vertical">

<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:id="@+id/def"
>

<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="capture"
android:onClick="click"/>

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/black"
android:id="@+id/img"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a"/>

</LinearLayout>

</HorizontalScrollView>

</LinearLayout>

Acivity Code:

public class CaptureBeyondActivity extends Activity {
/** Called when the activity is first created. */

LinearLayout def;
ImageView img;
HorizontalScrollView hsv;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

def = (LinearLayout)findViewById(R.id.def);
img = (ImageView)findViewById(R.id.img);

}

public void click(View v) {
Bitmap bitmap;
def.setDrawingCacheEnabled(true);
def.buildDrawingCache(true);

bitmap = Bitmap.createBitmap(def.getWidth(), def.getHeight(),
Config.ARGB_8888);
def.layout(0, 0, def.getLayoutParams().width,
def.getLayoutParams().height);
Canvas c = new Canvas(bitmap);
def.draw(c);

def.setDrawingCacheEnabled(false);

if(bitmap!=null){
img.setImageBitmap(bitmap);
img.invalidate();
}
}}

Here I have placed some elements in a HorizontalScrollView. OnClick of the button a screenshot is taken and the second image is replaced by the screenshot taken.
It takes screenshots of the offscreen elements also. You can further enhance the code and save the final bitmap image on SD card.



Related Topics



Leave a reply



Submit