By korovaisdead


2010-04-18 07:58:29 8 Comments

How can I take a screenshot of a selected area of phone-screen not by any program but from code?

24 comments

@Peter 2019-02-20 05:04:24

For Full Page Scrolling Screenshot

If you want to capture a full View screenshot (Which contains a scrollview or so) then have a check at this library

https://github.com/peter1492/LongScreenshot

All you have to do is import the Gradel, and create an object of BigScreenshot

BigScreenshot longScreenshot = new BigScreenshot(this, x, y);

A callback will be received with the bitmap of the Screenshots taken while automatically scrolling through the screen view group and at the end assembled together.

@Override public void getScreenshot(Bitmap bitmap) {}

Which can be saved to the gallery or whatsoever usage is necessary their after

@Mohit Singh 2018-12-06 08:15:42

Take screenshot of a view in android.

public static Bitmap getViewBitmap(View v) {
    v.clearFocus();
    v.setPressed(false);

    boolean willNotCache = v.willNotCacheDrawing();
    v.setWillNotCacheDrawing(false);

    int color = v.getDrawingCacheBackgroundColor();
    v.setDrawingCacheBackgroundColor(0);

    if (color != 0) {
        v.destroyDrawingCache();
    }
    v.buildDrawingCache();
    Bitmap cacheBitmap = v.getDrawingCache();
    if (cacheBitmap == null) {
        return null;
    }

    Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);

    v.destroyDrawingCache();
    v.setWillNotCacheDrawing(willNotCache);
    v.setDrawingCacheBackgroundColor(color);

    return bitmap;
}

@Miloš Černilovský 2018-08-16 11:23:51

Most of the answers for this question use the the Canvas drawing method or drawing cache method. However, the View.setDrawingCache() method is deprecated in API 28. Currently the recommended API for making screenshots is the PixelCopy class available from API 24 (but the methods which accept Window parameter are available from API 26 == Android 8.0 Oreo). Here is a sample Kotlin code for retrieving a Bitmap:

@RequiresApi(Build.VERSION_CODES.O)
fun saveScreenshot(view: View) {
    val window = (view.context as Activity).window
    if (window != null) {
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val locationOfViewInWindow = IntArray(2)
        view.getLocationInWindow(locationOfViewInWindow)
        try {
            PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
                if (copyResult == PixelCopy.SUCCESS) {
                    saveBitmap(bitmap)
                }
                // possible to handle other result codes ...
            }, Handler())
        } catch (e: IllegalArgumentException) {
            // PixelCopy may throw IllegalArgumentException, make sure to handle it
        }
    }
}

@Henning 2019-05-07 09:48:44

Problem with PixelCopy over the drawingCache solution is, that it seems to only capture visible pixel. the rest is black for me. So it is not possible to share stuff which is scrollable and is partly out of the frame. Do you have a solution for this?

@Miloš Černilovský 2019-05-07 11:30:53

You are right. Similarly it can cause a problem if another View is shown above the View I want to screenshot (e. g. when the drawer is opened). In these cases I just use the old Canvas method :(

@Amir Rezaei 2019-07-03 18:23:32

Is it possible to take screenshot on any running app using PixelCopy?

@Anil Singhania 2018-06-29 06:28:43

The parameter view is the root layout object.

public static Bitmap screenShot(View view) {
                    Bitmap bitmap = null;
                    if (view.getWidth() > 0 && view.getHeight() > 0) {
                        bitmap = Bitmap.createBitmap(view.getWidth(),
                                view.getHeight(), Bitmap.Config.ARGB_8888);
                        Canvas canvas = new Canvas(bitmap);
                        view.draw(canvas);
                    }
                    return bitmap;
                }

@taraloca 2011-04-13 14:53:28

Here is the code that allowed my screenshot to be stored on an SD card and used later for whatever your needs are:

First, you need to add a proper permission to save the file:

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

And this is the code (running in an Activity):

private void takeScreenshot() {
    Date now = new Date();
    android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

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

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

        File imageFile = new File(mPath);

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
        outputStream.flush();
        outputStream.close();

        openScreenshot(imageFile);
    } catch (Throwable e) {
        // Several error may come out with file handling or DOM
        e.printStackTrace();
    }
}

And this is how you can open the recently generated image:

private void openScreenshot(File imageFile) {
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    Uri uri = Uri.fromFile(imageFile);
    intent.setDataAndType(uri, "image/*");
    startActivity(intent);
}

If you want to use this on fragment view then use:

View v1 = getActivity().getWindow().getDecorView().getRootView();

instead of

View v1 = getWindow().getDecorView().getRootView();

on takeScreenshot() function

Note:

This solution doesn't work if your dialog contains a surface view. For details please check the answer to the following question:

Android Take Screenshot of Surface View Shows Black Screen

@Team Pannous 2012-01-19 15:01:27

this just takes a screenshot of your own program (right?)

@Ewoks 2012-03-06 10:32:00

What happened if background image of captured view is partly transparent..? In my case background color is captured too.. Do u have idea how not to capture other things below, let's say, half-transparent view? 10q

@Gaurav Chawla 2012-05-12 08:34:22

It worked but i am passing the root view of existing image view but the whole activity view is getting saved in sdcard.Please help i am very close.I want to save the snap shot of image not the whole view.

@xamar 2012-06-25 11:16:42

Ewoks: I had the same problem, it rendered black text over black background because this method won't draw the background (as you don't have access to those views. I found a solution to, at least, use the themed background (I'll post that as another answer)

@Kumar Vivek Mitra 2012-10-13 09:47:27

@xamar i am strucked at this... not able to take the screen shot of the specified view ( the ImageView)

@Princewill Obinna Iwuorie 2013-03-20 10:23:03

this worked for me but i have having problem with javaoutofmemory exception. because i do not clear the cache how do i go about clearing the cache

@Ravikumar11 2013-03-22 07:44:40

can above code is run on android unrooted devices?

@Mitesh Sardhara 2013-04-29 19:30:09

Hi, Can you describe what is mCurrentUrlMask? I have tried this code but it is always giving me NullPointerException at Bitmap.createBitmap(v1.getDrawingCache()), Can anybody tell what I am doing wrong.? Any help is appreciated. Thanks.

@gipi 2013-05-24 16:11:09

@MiteshSardhara mCurrentUrlMask must be a View since is the unique class in the Android API that has the getRootView() method. Probably is a view in the UI.

@Vaiden 2013-09-04 20:37:34

b.compress(Bitmap.CompressFormat.PNG, 90, new BufferedOutputStream( fout ));It's better to wrap the FileOutputStream with a BufferedStream:

@Ari 2013-10-24 05:08:35

I'm getting Nullpointerexception problem here View v1 = mCurrentUrlMask.getRootView(); i have declared mCurrentUrlMask as a view but how am i supposed to initialize that view, what is supposed to be in that view, please help

@Jayeshkumar Sojitra 2013-10-25 11:12:31

Can you please tell me what is, mCurrentUrlMask?

@noobProgrammer 2014-01-02 20:03:38

Try this : View v1= findViewById(R.id.LayoutID); v1.getRootView();

@MrCeeJ 2014-02-07 17:05:02

mCurrentUrlMask is a view that the original poster had declared elsewhere in his code. It does not serve any purpose here other than to have getRootView() called on it. The important part is that v1 is the view that will have its image taken so as long as that is the main view you should be ok. If your xml has a LinearLayout called mainLinearLayout then you could replace the code with v1 = (LinearLayout)findViewByID(R.id.mainLinearLayout); And as long as the mainLinearLayout is both visible and inside the screen it will have its image taken, otherwise you need to inflate/measure it yourself.

@enadun 2014-03-05 10:47:04

Insted of View v1 = mCurrentUrlMask.getRootView(); I have used View v1 = getWindow().getDecorView().getRootView(); and it works for me.

@Nirav Dangi 2014-09-12 13:55:41

for anybody else who is wondering same, here you can go..

@Farrakh Javed 2014-09-22 05:25:00

I am using the same code to take screen shot in a loop, this code is only generating 13-14 images per second whereas i need 24-25 images per second so after that i will be able to create a video.

@Anis Abboud 2014-10-08 06:40:24

If you get EACCES (Permission denied) error, add the following to your AndroidManifest.xml: <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

@Tushar Gogna 2014-11-19 08:45:26

What if my view is scrollview? will it also capture content that isn't visible? Is there a way to get whole data?

@Pascal 2015-01-22 10:25:39

Do not forget to recycle bitmap to avoid MEMORY LEAK! public static void recycleInBackground(final Bitmap bitmapToRecycle) { if(bitmapToRecycle==null || bitmapToRecycle.isRecycled()) { return; } new Thread(new Runnable() { @Override public void run() { bitmapToRecycle.recycle(); } }); }

@Paul Alexander 2015-03-26 09:25:02

does the phone need to be rooted to do this?

@dragos2 2015-08-02 10:53:34

This method does not work in all cases. For example it fails to capture a Google Maps (MapView v2) or a dialog. (It's probably because map uses glsurfaceview).

@Rain Man 2015-08-18 22:47:29

can you store the image in the gallery? this works fine but opening the image from other applications is very difficult since the image is not stored in the gallery section.

@AlikElzin-kilaka 2015-12-15 12:07:56

Does this work when the app is in the background as well?

@AlikElzin-kilaka 2015-12-16 03:48:59

This answer takes a screenshot of just the app - not the "phone screen" as asked in the question - or am I doing something wrong.

@nirav kalola 2016-01-01 13:21:27

Very nice tutorial. thanks for sharing

@Kaushal28 2016-09-05 16:37:05

This will not take snapshot of status bar. How can i Include it also?

@user25 2017-07-14 13:15:23

it's not good for real time when you want to record it in a video

@Ramani Hitesh 2018-01-01 08:50:00

i want current any screen capture screenshot like system screenshot during start mobile . so please let me know how is there –

@Miloš Černilovský 2018-08-16 11:27:38

The setDrawingCache() method is deprecated in API 28. Check my answer which shows how to use the new API for saving screenshots: stackoverflow.com/a/51875893/2380518

@Killer 2018-12-13 10:14:39

The elevation is skipped !!

@Rahul Kushwaha 2019-04-01 11:04:32

How can I take screenshots along with status bar? I only able to take screenshots of my app only .I want to take screenshots with tame anddate with battry status ,which is shown on the top of app in status bar.

@Crazy Coder 2014-08-27 10:31:18

private void captureScreen() {
    View v = getWindow().getDecorView().getRootView();
    v.setDrawingCacheEnabled(true);
    Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false);
    try {
        FileOutputStream fos = new FileOutputStream(new File(Environment
                .getExternalStorageDirectory().toString(), "SCREEN"
                + System.currentTimeMillis() + ".png"));
        bmp.compress(CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Add the permission in the manifest

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

For Supporting Marshmallow or above versions, please add the below code in the activity onCreate method

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);

@Naresh Sharma 2014-12-17 12:20:50

Worked fine for me.

@AndroidGuy 2015-05-11 06:19:02

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

@AlikElzin-kilaka 2015-12-16 03:56:39

This answer takes a screenshot of just the app - not the "phone screen" as asked in the question - or am I doing something wrong?

@Anshul Tyagi 2016-02-12 10:20:00

What about If I need screenshot of an item of listview?

@Deep Dave 2016-06-18 11:36:52

i want to capture in from adapter any idea how can i do it?

@GilCol 2018-01-04 15:13:35

For system applications only!

Process process;
process = Runtime.getRuntime().exec("screencap -p " + outputPath);
process.waitFor();

Note: System applications don't need to run "su" to execute this command.

@Chintan Khetiya 2017-10-12 07:42:24

Short way is

FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();

@TechBee 2017-07-30 15:39:23

Just extending taraloca's answer. You must add followings lines to make it work. I have made the image name static. Please ensure you use taraloca's timestamp variable incase you need dynamic image name.

    // Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

private void verifyStoragePermissions() {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
    }else{
        takeScreenshot();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        if (requestCode == REQUEST_EXTERNAL_STORAGE) {
            takeScreenshot();
        }
    }
}

And in the AndroidManifest.xml file following entries are must:

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

@Jeegar Patel 2015-01-13 09:42:40

No root permission or no big coding is required for this method.


On adb shell using below command you can take screen shot.

input keyevent 120

This command does not required any root permission so same you can perform from java code of android application also.

Process process;
process = Runtime.getRuntime().exec("input keyevent 120");

More about keyevent code in android see http://developer.android.com/reference/android/view/KeyEvent.html

Here we have used. KEYCODE_SYSRQ its value is 120 and used for System Request / Print Screen key.


As CJBS said, The output picture will be saved in /sdcard/Pictures/Screenshots

@CJBS 2015-04-29 23:00:38

The output picture will be saved here: /sdcard/Pictures/Screenshots

@mattlaabs 2015-10-23 16:16:18

doesn't seem to work on Android 5

@Taranmeet Singh 2015-12-23 05:59:07

does it require root permission??

@Jeegar Patel 2015-12-23 06:02:45

@Taranmeet No it does not require root permission

@karanatwal.github.io 2016-12-06 19:31:53

will it works on marshmallow ? or will it works in service background @JeegarPatel

@mehmet6parmak 2017-01-29 20:43:59

not worked programmatically, but works from shell. Tried with nougat.

@ipcjs 2017-02-03 17:55:40

su -c "input keyevent 120" is ok!!

@vijaypalod 2017-02-06 11:22:19

It is working from terminal but not programmatically..Any idea...?

@Lord Sepid 2017-03-12 06:44:50

It doesn't work on marshmallow too. and doesn't even throw an exception !

@Abdallah Alaraby 2014-10-27 08:45:55

I have created a simple library that takes a screenshot from a View and either gives you a Bitmap object or saves it directly to any path you want

https://github.com/abdallahalaraby/Blink

@Nilesh Agrawal 2015-02-10 19:20:22

Does it requires rooted phone ?

@Abdallah Alaraby 2015-02-10 20:33:51

No rooting required :)

@Nilesh Agrawal 2015-02-10 20:38:30

In usage u mentioned Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view‌​, mPath)); How to get view of current activity. I dont want to use the id of the xml.

@Abdallah Alaraby 2017-10-17 10:52:16

use takeScreenshotForScreen() instead.

@Parsania Hardik 2016-04-30 06:25:38

If you want to take screenshot from fragment than follow this:

  1. Override onCreateView():

             @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) {
                // Inflate the layout for this fragment
                View view = inflater.inflate(R.layout.fragment_one, container, false);
                mView = view;
            }
    
  2. Logic for taking screenshot:

     button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         View view =  mView.findViewById(R.id.scrollView1);
          shareScreenShotM(view, (NestedScrollView) view); 
     }
    
  3. method shareScreenShotM)():

    public void shareScreenShotM(View view, NestedScrollView scrollView){
    
         bm = takeScreenShot(view,scrollView);  //method to take screenshot
        File file = savePic(bm);  // method to save screenshot in phone.
        }
    
  4. method takeScreenShot():

             public Bitmap takeScreenShot(View u, NestedScrollView z){
    
                u.setDrawingCacheEnabled(true);
                int totalHeight = z.getChildAt(0).getHeight();
                int totalWidth = z.getChildAt(0).getWidth();
    
                Log.d("yoheight",""+ totalHeight);
                Log.d("yowidth",""+ totalWidth);
                u.layout(0, 0, totalWidth, totalHeight);
                u.buildDrawingCache();
                Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
                u.setDrawingCacheEnabled(false);
                u.destroyDrawingCache();
                 return b;
            }
    
  5. method savePic():

     public static File savePic(Bitmap bm){
    
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
             File sdCardDirectory =  new File(Environment.getExternalStorageDirectory() + "/Foldername");
    
           if (!sdCardDirectory.exists()) {
                sdCardDirectory.mkdirs();
          }
           //  File file = new File(dir, fileName);
          try {
             file = new File(sdCardDirectory, Calendar.getInstance()
                .getTimeInMillis() + ".jpg");
            file.createNewFile();
            new FileOutputStream(file).write(bytes.toByteArray());
            Log.d("Fabsolute", "File Saved::--->" + file.getAbsolutePath());
             Log.d("Sabsolute", "File Saved::--->" + sdCardDirectory.getAbsolutePath());
         } catch (IOException e) {
              e.printStackTrace();
          }
         return file;
       }
    

For activity you can simply use View v1 = getWindow().getDecorView().getRootView(); instead of mView

@Oliver Hausler 2015-05-20 21:09:12

Based on the answer of @JustinMorris above and @NiravDangi here https://stackoverflow.com/a/8504958/2232148 we must take the background and foreground of a view and assemble them like this:

public static Bitmap takeScreenshot(View view, Bitmap.Config quality) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), quality);
    Canvas canvas = new Canvas(bitmap);

    Drawable backgroundDrawable = view.getBackground();
    if (backgroundDrawable != null) {
        backgroundDrawable.draw(canvas);
    } else {
        canvas.drawColor(Color.WHITE);
    }
    view.draw(canvas);

    return bitmap;
}

The quality parameter takes a constant of Bitmap.Config, typically either Bitmap.Config.RGB_565 or Bitmap.Config.ARGB_8888.

@Shaleen 2015-06-25 10:57:34

drawing canvas with white color in case background is null did the trick for me. Thanks Oliver

@validcat 2013-09-25 15:07:24

My solution is:

public static Bitmap loadBitmapFromView(Context context, View v) {
    DisplayMetrics dm = context.getResources().getDisplayMetrics(); 
    v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
            v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(returnedBitmap);
    v.draw(c);

    return returnedBitmap;
}

and

public void takeScreen() {
    Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
    String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
    File imageFile = new File(mPath);
    OutputStream fout = null;
    try {
        fout = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
        fout.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        fout.close();
    }
}

Images are saved in the external storage folder.

@Wotuu 2014-05-01 09:31:59

You should close the FileOutputStream in a finally block. If you encounter an exception now the stream will not be closed.

@AlikElzin-kilaka 2015-12-16 03:57:46

What's the view you're passing to ImageUtils.loadBitmapFromView(this, view)?

@serj 2016-01-28 16:23:16

why do you use v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); ? Doesn't that change the view (v) ?

@Akshay Paliwal 2015-02-27 08:50:28

if you want to capture a view or layout like RelativeLayout or LinearLayout etc. just use the code :

LinearLayout llMain = (LinearLayout) findViewById(R.id.linearlayoutMain);
Bitmap bm = loadBitmapFromView(llMain);

now you can save this bitmap on device storage by :

FileOutputStream outStream = null;
File f=new File(Environment.getExternalStorageDirectory()+"/Screen Shots/");
f.mkdir();
String extStorageDirectory = f.toString();
File file = new File(extStorageDirectory, "my new screen shot");
pathOfImage = file.getAbsolutePath();
try {
    outStream = new FileOutputStream(file);
    bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
    Toast.makeText(getApplicationContext(), "Saved at "+f.getAbsolutePath(), Toast.LENGTH_LONG).show();
    addImageGallery(file);
    //mail.setEnabled(true);
    flag=true;
} catch (FileNotFoundException e) {e.printStackTrace();}
try {
    outStream.flush();
    outStream.close();
} catch (IOException e) {e.printStackTrace();}

@b devloper 2017-01-23 11:18:44

and where is loadBitmapFromView code?

@rockeye 2015-04-10 15:57:46

For those who want to capture a GLSurfaceView, the getDrawingCache or drawing to canvas method won't work.

You have to read the content of the OpenGL framebuffer after the frame has been rendered. There is a good answer here

@Viswanath Lekshmanan 2013-03-04 18:36:14

Note: works only for rooted phone

Programmatically, you can run adb shell /system/bin/screencap -p /sdcard/img.png as below

Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();    

then read img.png as Bitmap and use as your wish.

@zoom 2014-11-14 09:17:50

Is it need root access?

@Viswanath Lekshmanan 2014-11-14 09:19:49

Yes you need root access. Please check the Note at the heading

@Eddy 2015-06-23 09:14:31

Hi, I got a System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null , my device is android 5.0

@Demian 2016-05-31 20:32:41

@Eddy It depends on your device

@Yazan W Yusuf 2017-05-11 20:53:09

Is there a way to read the output directly without saving the result into file then reading it again? stackoverflow.com/questions/43914035

@Viswanath Lekshmanan 2017-05-13 08:55:34

@YazanWYusuf I don't know any way a process will directly communicate with our application. Will check and get back to you on this.

@Vaishali Sutariya 2014-08-21 12:01:28

public class ScreenShotActivity extends Activity{

private RelativeLayout relativeLayout;
private Bitmap myBitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    relativeLayout = (RelativeLayout)findViewById(R.id.relative1);
    relativeLayout.post(new Runnable() {
        public void run() {

            //take screenshot
            myBitmap = captureScreen(relativeLayout);

            Toast.makeText(getApplicationContext(), "Screenshot captured..!", Toast.LENGTH_LONG).show();

            try {
                if(myBitmap!=null){
                    //save image to SD card
                    saveImage(myBitmap);
                }
                Toast.makeText(getApplicationContext(), "Screenshot saved..!", Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    });

}

public static Bitmap captureScreen(View v) {

    Bitmap screenshot = null;
    try {

        if(v!=null) {

            screenshot = Bitmap.createBitmap(v.getMeasuredWidth(),v.getMeasuredHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(screenshot);
            v.draw(canvas);
        }

    }catch (Exception e){
        Log.d("ScreenShotActivity", "Failed to capture screenshot because:" + e.getMessage());
    }

    return screenshot;
}

public static void saveImage(Bitmap bitmap) throws IOException{

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 40, bytes);
    File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
    f.createNewFile();
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
    fo.close();
}

}

ADD PERMISSION

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

@AlikElzin-kilaka 2015-12-16 03:59:01

This answer takes a screenshot of just the app - not the "phone screen" as asked in the question - or am I doing something wrong?

@GDR 2010-04-18 08:41:50

EDIT: have mercy with the downvotes. It was true in 2010 when I answered the question.

All the programs which allow screenshots work only on rooted phones.

@GDR 2011-12-27 23:05:57

It looks that these days it's possible on Androids with Tegra based chipset

@Yogesh Maheshwari 2012-08-21 06:30:57

How is it possible.. please elaborate..

@FabianCook 2012-09-04 21:07:25

My tablet running 4.0.3 allows screen shots, not rooted, Acer Iconia A500...

@GDR 2012-09-05 11:32:50

4.0.3 - then it's probably one of these new-school tegra tablets

@Rui Marques 2012-12-12 10:28:42

AFAIK when devices have a stock app to capture screenshots it is an app with special signature privileges which allow it to capture the framebuffer (a buffer with contains the screen pixels). So it is true, if your ROM has such an app, you will not need to be rooted, but only that app can make captures, not yours.

@Chris Stratton 2015-04-30 19:20:46

Strictly speaking, along with root ADB's "shell" user account has always had permission to do this as that was the intended use case. What was not historically available (except on occasional builds as a mistake) was a way for application user id's to do so.

@Kevin Tan 2011-03-05 20:07:44

You can try to do something like this,

Getting a bitmap cache from a layout or a view by doing something like First you gotta setDrawingCacheEnabled to a layout(a linearlayout or relativelayout, or a view)

then

Bitmap bm = layout.getDrawingCache()

Then you do whatever you want with the bitmap. Either turning it into an image file, or send the bitmap's uri to somewhere else.

@trgraglia 2011-03-06 19:13:02

This is the best method if it is your app that you are writing to a bitmap. Also, beware of methods which have delays before taking the cache... like Notify...() for list views.

@Kevin Tan 2011-03-14 08:51:27

Not just that. The layout must be displayed on the screen first. It's the "cache" you're getting afterall. Tried hiding the view and taking screenshots in the background(in theory), but it didn't work.

@sivi 2015-08-18 12:03:44

By far more efficient than other solutions

@JustinMorris 2013-04-19 17:08:12

Call this method, passing in the outer most ViewGroup that you want a screen shot of:

public Bitmap screenShot(View view) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
            view.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}

@jophde 2014-11-30 05:55:41

This is seems to be cleaner code than the accepted answer. Does it perform as well?

@JustinMorris 2014-12-04 20:43:08

I've used it for a while in a few different apps and haven't had any issues.

@AlikElzin-kilaka 2015-12-15 12:06:14

If you want to get a screenshot of the phone, where your app is in the background, what do you pass as the view?`

@AlikElzin-kilaka 2015-12-16 03:45:40

Passing getWindow().getDecorView().getRootView() as the view results in taking a screenshot of just the app - not the screen.

@AlikElzin-kilaka 2015-12-16 03:49:07

This answer takes a screenshot of just the app - not the "phone screen" as asked in the question - or am I doing something wrong.

@android developer 2015-12-27 14:12:27

@AlikElzin-kilaka No, it's not for taking a screenshot no matter in which app you are. For this, there is a special API, but I can't find out how to use it: stackoverflow.com/q/32513379/878126

@user512 2016-01-30 09:01:01

when i am trying this its generating screen shot with bad quality. how can i overcome this?

@DariusL 2016-03-31 08:13:05

There's a small issue, this does not seem to capture the activity background color. Any ideas?

@Xar E Ahmer 2016-09-06 11:12:14

to take a screen shot of Screen Use getActivity().getWindow().getDecorView() but it requires api 21

@AB1209 2017-12-13 06:56:22

In my case I have a WebView in which I load an animating image url. After creating bitmap, it captures everything except the animating objects. Can we do something for that?

@Ramani Hitesh 2018-01-01 08:52:53

i want current any screen capture screenshot during start mobile so please let me know how is there –

@Rui Marques 2012-12-12 10:40:22

As a reference, one way to capture the screen (and not just your app activity) is to capture the framebuffer (device /dev/graphics/fb0). To do this you must either have root privileges or your app must be an app with signature permissions ("A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission") - which is very unlikely unless you compiled your own ROM.

Each framebuffer capture, from a couple of devices I have tested, contained exactly one screenshot. People have reported it to contain more, I guess it depends on the frame/display size.

I tried to read the framebuffer continuously but it seems to return for a fixed amount of bytes read. In my case that is (3 410 432) bytes, which is enough to store a display frame of 854*480 RGBA (3 279 360 bytes). Yes, the frame, in binary, outputted from fb0 is RGBA in my device. This will most likely depend from device to device. This will be important for you to decode it =)

In my device /dev/graphics/fb0 permissions are so that only root and users from group graphics can read the fb0.

graphics is a restricted group so you will probably only access fb0 with a rooted phone using su command.

Android apps have the user id (uid) = app_## and group id (guid) = app_## .

adb shell has uid = shell and guid = shell, which has much more permissions than an app. You can actually check those permissions at /system/permissions/platform.xml

This means you will be able to read fb0 in the adb shell without root but you will not read it within the app without root.

Also, giving READ_FRAME_BUFFER and/or ACCESS_SURFACE_FLINGER permissions on AndroidManifest.xml will do nothing for a regular app because these will only work for 'signature' apps.

Also check this closed thread for more details.

@Chris Stratton 2014-03-27 14:51:24

This works (worked?) on some phones, but note that GPU based phones don't necessarily provide a linear framebuffer to the applications processor.

@xamar 2012-06-25 11:37:33

Mualig answer is very good, but I had the same problem Ewoks describes, I'm not getting the background. So sometimes is good enough and sometimes I get black text over black background (depending on the theme).

This solution is heavily based in Mualig code and the code I've found in Robotium. I'm discarding the use of drawing cache by calling directly to the draw method. Before that I'll try to get the background drawable from current activity to draw it first.

// Some constants
final static String SCREENSHOTS_LOCATIONS = Environment.getExternalStorageDirectory().toString() + "/screenshots/";

// Get device dimmensions
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);

// Get root view
View view = mCurrentUrlMask.getRootView();

// Create the bitmap to use to draw the screenshot
final Bitmap bitmap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ARGB_4444);
final Canvas canvas = new Canvas(bitmap);

// Get current theme to know which background to use
final Activity activity = getCurrentActivity();
final Theme theme = activity.getTheme();
final TypedArray ta = theme
    .obtainStyledAttributes(new int[] { android.R.attr.windowBackground });
final int res = ta.getResourceId(0, 0);
final Drawable background = activity.getResources().getDrawable(res);

// Draw background
background.draw(canvas);

// Draw views
view.draw(canvas);

// Save the screenshot to the file system
FileOutputStream fos = null;
try {
    final File sddir = new File(SCREENSHOTS_LOCATIONS);
    if (!sddir.exists()) {
        sddir.mkdirs();
    }
    fos = new FileOutputStream(SCREENSHOTS_LOCATIONS
            + System.currentTimeMillis() + ".jpg");
    if (fos != null) {
        if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)) {
            Log.d(LOGTAG, "Compress/Write failed");
        }
        fos.flush();
        fos.close();
    }

} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

@Wangchao0721 2012-09-22 14:47:19

I have a listview with android:cacheColorHint="#00000000" in my activity , and I use this code to screenshot , I still got a black background , because I found that background that get from theme is black , how can I deal with this listview?

@Shabbir Dhangot 2014-08-26 07:14:51

Activity activity = getCurrentActivity giving Eroor undefined method.

@Kuba 2010-09-07 13:53:11

You can try the following library: http://code.google.com/p/android-screenshot-library/ Android Screenshot Library (ASL) enables to programmatically capture screenshots from Android devices without requirement of having root access privileges. Instead, ASL utilizes a native service running in the background, started via the Android Debug Bridge (ADB) once per device boot.

@Jana 2010-10-15 07:14:39

I tried this.but it takes screenshot of the running app alone. Its cant help if i want to take screenshot of the homescreen. do you how to take screenshot of the homescreen withthat code?

@trgraglia 2011-02-08 08:28:13

@Janardhanan.S: This is what the question is asking for. Can you elaborate with a new answer instead of asking a separate question.

@Newts 2012-02-03 11:54:34

@Kuba i installed this app but it shows native service not found. Help me please.

@Yogesh Maheshwari 2012-08-17 10:57:25

Same Problem with me.. "Native Service Not Running!!"

@Pankaj Kumar 2013-06-20 09:59:48

Same with me "Native Service Not Running!!".... can anybody add the help text here?

@user347187 2014-04-15 07:42:05

same here! "Native Service Not Running!!" and in their latest version 1.2 they use API LEVEL 19 classes, like Socket for example.

@kuma DK 2015-03-19 03:52:28

need to enable the service via pc each times the phone restart. :(

Related Questions

Sponsored Content

45 Answered Questions

[SOLVED] Is there a unique Android device ID?

50 Answered Questions

[SOLVED] Stop EditText from gaining focus at Activity startup

94 Answered Questions

[SOLVED] Close/hide the Android Soft Keyboard

53 Answered Questions

[SOLVED] How do I fix android.os.NetworkOnMainThreadException?

25 Answered Questions

[SOLVED] Website screenshots

  • 2009-04-16 19:25:18
  • Tom
  • 306105 View
  • 400 Score
  • 25 Answer
  • Tags:   php screenshot

77 Answered Questions

39 Answered Questions

[SOLVED] Get screen dimensions in pixels

14 Answered Questions

[SOLVED] Take screenshots in the iOS simulator

11 Answered Questions

[SOLVED] Proper use cases for Android UserManager.isUserAGoat()?

3 Answered Questions

[SOLVED] Using HTML5/Canvas/JavaScript to take in-browser screenshots

Sponsored Content