PocketMagic

PocketMagic

Where Technology meets magic


Android
45 Posts
BlackBerry
4 Posts
Electronics
68 Posts
Hardware
120 Posts
High Voltage
49 Posts
iPhone
4 Posts
Linux
2 Posts
Nuclear
20 Posts
Optics
11 Posts
Photography
7 Posts
Photoshop
3 Posts
Research
19 Posts
Reviews
18 Posts
Robotics
8 Posts
Security
7 Posts
Software
73 Posts
Symbian
2 Posts
Tubes
18 Posts
Windows
3 Posts
Windows Mobile
11 Posts

Top Articles!       See PocketMagic on Facebook


uRADMonitor - Online Radiation monitoring station | 14967 Views | Rate 70.27
uRADMonitor - Online Radiation monitoring station
Bluetooth and iOS - Use Bluetooth in your iPhone apps | 18318 Views | Rate 59.09
Bluetooth and iOS - Use Bluetooth in your iPhone apps
NMEA GPS Library for AVR Microcontrollers | 4845 Views | Rate 56.34
NMEA GPS Library for AVR Microcontrollers
Programmatically Injecting Events on Android - Part 2 | 5059 Views | Rate 44.77
Programmatically Injecting Events on Android - Part 2
Building a robot – Part 2 | 4645 Views | Rate 44.24
Building a robot – Part 2
Simple Switched power Supplies | 16205 Views | Rate 41.98
Simple Switched power Supplies
Capacitor Discharge Microspot Welder / Cutter | 11395 Views | Rate 36.52
Capacitor Discharge Microspot Welder / Cutter
Atmega8 and Nokia 5110 LCD  | 1556 Views | Rate 34.58
Atmega8 and Nokia 5110 LCD

 
  

Android Native Screen capture application using the Framebuffer


By Radu Motisan Posted on November 18th, 2010 , 6244 Views (Rate 6.81)



  




android native screen capture tool screen It is possible to write a native C application, that opens the framebuffer (/dev/graphics/fb0) to extract bitmap data representing the screen surface image.

It is also possible to modify the framebuffer data and by doing so to do a low level drawing on screen (that is also very fast).

The data must be then converted (aligned/reversed) to standard BMP format, and saved to disc.

The framebuffer grabber:

  1.  
  2. static int get_framebuffer(GGLSurface *fb)
  3. {
  4. int fd;
  5. void *bits;
  6.  
  7. fd = open("/dev/graphics/fb0", O_RDWR);
  8. if(fd < 0) {
  9. perror("cannot open fb0");
  10. return -1;
  11. }
  12.  
  13. if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
  14. perror("failed to get fb0 info");
  15. return -1;
  16. }
  17.  
  18. if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
  19. perror("failed to get fb0 info");
  20. return -1;
  21. }
  22.  
  23. //dumpinfo(&fi, &vi);
  24.  
  25. bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  26. if(bits == MAP_FAILED) {
  27. perror("failed to mmap framebuffer");
  28. return -1;
  29. }
  30.  
  31. fb->version = sizeof(*fb);
  32. fb->width = vi.xres;
  33. fb->height = vi.yres;
  34. fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
  35. fb->data = bits;
  36. fb->format = GGL_PIXEL_FORMAT_RGB_565;
  37.  
  38. fb++;
  39.  
  40. fb->version = sizeof(*fb);
  41. fb->width = vi.xres;
  42. fb->height = vi.yres;
  43. fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
  44. fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
  45. fb->format = GGL_PIXEL_FORMAT_RGB_565;
  46.  
  47. return fd;
  48. }
  49.  

The BITMAP former:
The first thing to do is to convert the Framebuffer's 16 bit data into 24 bit. We're not gaining extra-quality here, we're just "stretching" the colors from:
5 bits blue : 2^5=32 blue color nuances
6 bits green : 2^6=64 green color nuances (in 16bit colors, green has more color space since the human eye is more sensitive to green color)
5 bits red : 2^5=32 red color nuances
32x64x32 possible 16bits colors (2^16)
To:
8 bits blue : 2^8 = 256 color nuances
8 bits green : 2^8 = 256 color nuances
8 bits red : 2^8 = 256 color nuances
A total of 2^24 colors, but as I said we're just "stretching" the color intervals without any information gain.

  1.  
  2. //convert pixel data
  3. uint8_t *rgb24;
  4. if (depth == 16)
  5. {
  6. rgb24 = (uint8_t *)malloc(w * h * 3);
  7. int i = 0;
  8. for (;i<w*h;i++)
  9. {
  10. uint16_t pixel16 = ((uint16_t *)gr_framebuffer[0].data)[i];
  11. // RRRRRGGGGGGBBBBBB -> RRRRRRRRGGGGGGGGBBBBBBBB
  12. // in rgb24 color max is 2^8 per channel (*255/32 *255/64 *255/32)
  13. rgb24[3*i+2] = (255*(pixel16 & 0x001F))/ 32; //Blue
  14. rgb24[3*i+1] = (255*((pixel16 & 0x07E0) >> 5))/64; //Green
  15. rgb24[3*i] = (255*((pixel16 & 0xF800) >> 11))/32; //Red
  16. }
  17. }
  18. else
  19. if (depth == 24)
  20. {
  21. rgb24 = (uint8_t *) gr_framebuffer[0].data;
  22. }
  23. else
  24. {
  25. //free
  26. close(gr_fb_fd);
  27. exit(2);
  28. };
  29. //save RGB 24 Bitmap
  30. int bytes_per_pixel = 3;
  31. BMPHEAD bh;
  32. memset ((char *)&bh,0,sizeof(BMPHEAD)); // sets everything to 0
  33. //bh.filesize = calculated size of your file (see below)
  34. //bh.reserved = two zero bytes
  35. bh.headersize = 54L; // for 24 bit images
  36. bh.infoSize = 0x28L; // for 24 bit images
  37. bh.width = w; // width of image in pixels
  38. bh.depth = h; // height of image in pixels
  39. bh.biPlanes = 1; // for 24 bit images
  40. bh.bits = 8 * bytes_per_pixel; // for 24 bit images
  41. bh.biCompression = 0L; // no compression
  42. int bytesPerLine;
  43. bytesPerLine = w * bytes_per_pixel; // for 24 bit images
  44. //round up to a dword boundary
  45. if (bytesPerLine & 0x0003)
  46. {
  47. bytesPerLine |= 0x0003;
  48. ++bytesPerLine;
  49. }
  50. bh.filesize = bh.headersize + (long)bytesPerLine * bh.depth;
  51. FILE * bmpfile;
  52. //printf("Bytes per line : %d\n", bytesPerLine);
  53. bmpfile = fopen("screen.bmp", "wb");
  54. if (bmpfile == NULL)
  55. {
  56. close(gr_fb_fd);
  57. exit(3);
  58. }
  59. fwrite("BM",1,2,bmpfile);
  60. fwrite((char *)&bh, 1, sizeof (bh), bmpfile);
  61. //fwrite(rgb24,1,w*h*3,bmpfile);
  62. char *linebuf;
  63. linebuf = (char *) calloc(1, bytesPerLine);
  64. if (linebuf == NULL)
  65. {
  66. fclose(bmpfile);
  67. close(gr_fb_fd);
  68. exit(4);
  69. }
  70.  

Now the next thing to do is to align the BGR triplets and to switch order , to match the BMP RGB24 color format.

  1.  
  2. int line,x;
  3. for (line = h-1; line >= 0; line --)
  4. {
  5. // fill line linebuf with the image data for that line
  6. for( x =0 ; x < w; x++ )
  7. {
  8. *(linebuf+x*bytes_per_pixel) = *(rgb24 + (x+line*w)*bytes_per_pixel+2);
  9. *(linebuf+x*bytes_per_pixel+1) = *(rgb24 + (x+line*w)*bytes_per_pixel+1);
  10. *(linebuf+x*bytes_per_pixel+2) = *(rgb24 + (x+line*w)*bytes_per_pixel+0);
  11. }
  12. // remember that the order is BGR and if width is not a multiple
  13. // of 4 then the last few bytes may be unused
  14. fwrite(linebuf, 1, bytesPerLine, bmpfile);
  15. }
  16. fclose(bmpfile);
  17. close(gr_fb_fd);
  18.  

Download the code: (old code removed, see update below)
Note that you are not allowed to distribute this code without visibly indicating it's author (me) and the source (this page) and You may not embedded it in commercial applications.
To compile the code, use the NDK, as presented in this article.
Running the code produces a screen.bmp file:
android native screen capture tool

screen.bmp
android native screen capture tool screen

Hope this helps.

Update, April 03, 2012

By popular demand, I have modified the code to support RGB32 as well. In this case, we have an extra alpha channel, that we need to ignore when creating the final bitmap. So I have added a RGB32->RGB24 converter, but it is only a alpha channel remover, since we are not talking about true RGB32. The Red,Green,Blue channel are still 8bits each, as in the case of RGB24. Peter's solution below works, but I felt the need to write a simpler code:

  1.  
  2. if (depth == 32) //skip transparency channel
  3. {
  4. rgb24 = (uint8_t *) malloc(w * h * 3);
  5. int i=0;
  6. for (;i<w*h;i++)
  7. {
  8. uint32_t pixel32 = ((uint32_t *)gr_framebuffer[0].data)[i];
  9. // in rgb24 color max is 2^8 per channel
  10. rgb24[3*i+0] = pixel32 & 0x000000FF; //Blue
  11. rgb24[3*i+1] = (pixel32 & 0x0000FF00) >> 8; //Green
  12. rgb24[3*i+2] = (pixel32 & 0x00FF0000) >> 16; //Red
  13. }
  14. }
  15.  

Here is the complete source code, and the native ELF binary file:
Native
And a BMP result of my Android using an RGB32 screen:

When using capturescr ELF file in ADB shell, you can get the returned error code using:

  1.  
  2. echo $?
  3.  






  

More on PocketMagic:

How to set the AVR Fusebits | 1721 Views | Rate 23.58
How to set the AVR Fusebits
Repairing a Victoreen CDV-700 6B Dosimeter  | 165 Views | Rate 23.57
Repairing a Victoreen CDV-700 6B Dosimeter
ATMega128 and HD44780 LCD using 3 Wires with the 74HC164 | 2067 Views | Rate 22.71
ATMega128 and HD44780 LCD using 3 Wires with the 74HC164
Developing for Blackberry 10 | 90 Views | Rate 22.5
Developing for Blackberry 10
Dual H-Bridge for controlling two motors | 1213 Views | Rate 21.28
Dual H-Bridge for controlling two motors
USBAsp -  AVR USB Programmer  | 8131 Views | Rate 21.06
USBAsp - AVR USB Programmer

101 Responses to “Android Native Screen capture application using the Framebuffer”

  1. 1
    PocketMagic » Android Native Play Sound using /dev/msm_pcm_out:

    [...]   « Android Native Screen capture application using the Framebuffer [...]

  2. 2
    deepali:

    How to do this for a 32 bit depth screen

  3. 3
    Radu Motisan:

    its very much the same code, see if (depth == 24) …

  4. 4
    Faizan:

    it is not working from Os 2.2.1l…works fine with 2.2

    /dev/graphics/fb0 “can not opened” not accessible or obsolete from 2.2.1…any suggestion?

  5. 5
    Radu Motisan:

    do you have root access?

  6. 6
    Faizan:

    how to check if i have root access? well the device i have lg optimus and galaxy s, working fine on lg optimus i guess its allows me root access,what about galaxy s? how to enable root access?

  7. 7
    Ekin:

    Is it possible to access framebuffer via JNI?

  8. 8
    Radu Motisan:

    yes, you simply compile my code above with a JNI interface.

  9. 9
    Ekin:

    I compiled your code with JNI and run it on the rooted emulator, but it can’t access the framebuffer(open(“/dev/graphics/fb0″, O_RDWR) failed).
    P.S I also tried to call Runtime.getRuntime().exec(“su”) from java before the native JNI function but it still failed.

    am i missing something?

  10. 10
    Ekin:

    Thanks, you’re right.
    I forgot chmod 777 /dev/graphics/fb0.

  11. 11
    Radu:

    good.

  12. 12
    gyeonghochu:

    How to do this for a 32 bit depth screen…
    Can you explain more detail?

  13. 13
    Radu Motisan:

    hello gyeonghochu, what do you need to know?

  14. 14
    gyeonghochu:

    Thank you for your reply.
    Now, I am capturing the screen that is galaxy S.
    But I have a problem…
    The problem is that “depth” returns 32.
    I think that it means that 32 bit..
    So I added source code like below…

    else if( depth == 32 )
    {
    rgb24 = (uint8_t *) gr_framebuffer[0].data;
    }

    But it did not correctly work.
    The image is crashed…

    So how can I resolve this problem…

  15. 15
    srinivas:

    Hi,
    I tried below to access fbo still i couldn’t open it.
    Runtime.getRuntime().exec(“su”);
    Runtime.getRuntime().exec(“chmod 777 /dev/graphics/fb0″);

  16. 16
    srinivas:

    Hi,
    It is a rooted device,requested for super user access after SU command but fb0 is not accessible.

  17. 17
    johny:

    hy, can you tell me what to put in
    else if( depth == 32 ){
    ??????
    }

    can someone help me?

  18. 18
    Peter:

    for 32Bit : (Format is : BGRX) X = transparency , we can ignore it)

    rgb24 = (uint8_t *) malloc(w * h * 3);
    int i = 0;
    int j = 0;
    int k = 0;
    for (k=0; k < w * h; k++) {
    uint8_t pixel8 = ((uint8_t *) gr_framebuffer[0].data)[i++];
    rgb24[j+2] = pixel8;
    j++;
    pixel8 = ((uint8_t *) gr_framebuffer[0].data)[i++];
    rgb24[j] = pixel8;
    j++;
    pixel8 = ((uint8_t *) gr_framebuffer[0].data)[i++];
    rgb24[j-2] = pixel8;
    j++;
    i++;
    }

  19. 19
    Daniel:

    Is necessary have be root

  20. 20
    shahhassan:

    hi every body
    i am new to android development i just want to know that the code above will work in eclipse or not.

  21. 21
    Radu Motisan:

    New code added to this article. Enjoy!

  22. 22
    Ali:

    Hi Radu,

    This sample can’t access /dev/graphics/fb0″ at my nexus one (note: My device is not rooted).

    Please can you help me to capture android screen.

    Thanks in advance.

    Ali

  23. 23
    Zeshan:

    Hi,
    Same issue here, i am unable to open the file /dev/graphics/fb0. I tried to change the mode by “chmod(“/dev/graphics/fb0″, 777)”, but its not changing the mode even. Am stuck.. Need help !!!
    Note: My device is not rooted.

  24. 24
    Zeshan:

    Hi,
    Can’t we save the image in jpeg or png format, instead of BMP??? if so, than how to do it??

  25. 25
    shahhassan:

    Hi
    how can we send bitmap using TCP socket. I have already transfer Text but i don’t know how to transfer bitmap. please help me

  26. 26
    Zeshan:

    For me blue color is showing as orange, and orange color is shown as blue…. :( any help?

  27. 27
    radu:

    Just invert blue channel with the red one.

  28. 28
    Zeshan:

    Thanks a lot Radu !! It works perfectly fine now !! Its been a great help by you. :)

  29. 29
    Zeshan:

    One little thing more, is it possible to save in any other format? like png or jpeg? Bimap is very large in size.
    Thanks in advance.

  30. 30
    ea:

    Hi,

    Thanks for the post it really helps! I tried it, and it worked, but in case that there is also video that is playing somewhere on the screen, the captured frame does not include the video, any idea why? and how I can get the video frame as well?
    Thanks.

  31. 31
    M.Bilal:

    hi,
    when i change android minsdk version 3 to 4 code does not work.any reason???
    Thanks in advance

  32. 32
    Asanka:

    Hi,

    I’m a newbie when it comes to native coding the android. Frankly, have only written a couple of HelloWorld programs. I understand this is a huge ask, and a waste of your time, but would you be able to explain how I can convert this code to be run via the JNI. What are the files I need to include.

    I have a rooted android, and I understand how the FrameBuffer works and also know how the bytes are formed and the conversion which I need to do. The only part I don’t know is how to open the “/dev/graphics/fb0″ file from within my program.

    Would be most grateful for any help you can provide.

    Cheers

  33. 33
    Radu Motisan:

    It is a relatively simple task to convert the code for JNI : you just rename the functions you plan to use while keeping an eye on the involved data structures: I suggest you return the image data as a byte array, directly to your java program. Then in your Java code you can do all the logic like converting the image to RGBXXX, or converting it to various formats.

    To get a start with JNI, see my tutorial on the Android NDK, on this blog.

  34. 34
    Asanka:

    Works very well… thanks Radu. Kind regards.

  35. 35
    shah hassan:

    Hi
    can any body please guide me how to use this code in eclipse i have tried more but unable to use the code please help me.
    Thanks

  36. 36
    Radu Motisan:

    @shah, see the NDK tutorial, here is the link again: http://www.pocketmagic.net/?p=1462

  37. 37
    shahhassan:

    Thanks Radu Motisan for replay. still i am unable to install NDK and my project is stuck for this point to take screenshot… if you guide with more detail i will be realy thankful to you…
    Thanks once again

  38. 38
    Radu Motisan:

    @Shah, what exactly didn’t work for you when installing the NDK? I cannot do the work for you, but I can help you if you have specific questions. If something is unclear about the NDK tutorial, please post your questions under the NDK article.

  39. 39
    shahhassan:

    sir
    Actually i have to 2 questions first one is how i can install NDK in eclipse i read almost every tutorial but could not install NDK and second question is that i want to use this code in my application to get screenshot. so how can i use it.. please guide me for this.
    thank you very much for your quick response…

  40. 40
    Radu Motisan:

    To install the NDK, follow the indicated steps: 1,2,3: http://www.pocketmagic.net/?p=1462

    If you encounter difficulties, indicate the step where you were unable to continue.

  41. 41
    shah hassan:

    sir
    i have install Cygwin and unzip android NDK to my D drive now i am trying to run this command to built native components but its not working cd /cygdrive/d/softkeyboard/project pleas help me to solve this problem

  42. 42
    Radu Motisan:

    It is not enough to install cygwin and unzip the NDK, you will need to follow all the instructions presented there.

  43. 43
    shah hassan:

    sir please guide me that how can i use this code in eclipse. I think i have install NDK but i don’t know how to cheak that its working correctly. please guide me so that i use this code and run it. thanks alot

  44. 44
    hamza:

    sir please would your code work if i launch it from another android application (i test it and i got error : cannot open fb0) thans in advance .

  45. 45
    Radu Motisan:

    @hamza, the “cannot open fb0″ error is exactly what it says: the native code app doesn’t have the right permissions to open fb0.

    You will need to set the fb0 to 666 at least. (chmod 666 /dev/graphics/fb0)

  46. 46
    hamza:

    Hi Radu, thanks for the quick answer.I tried this [Process process = Runtime.getRuntime().exec("chmod 666 /dev/graphics/fb0");] but it still show me cannot open fb0 . I try to work around by launching the compiled code from my application though the method above but it won’t work (but this, it s another problem ^^ ).

  47. 47
    Radu Motisan:

    First connect with adb (adb shell) and try chmod there. You will need ROOT permissions for chmod to work on this file :/

    The code for capturing screen doesn’t need root, but if the permissions are not set it willnot work. It is a vicious circle, blame Google, after all this time they refuse to grow up .

    I am so amazed the Windows Mobile platform went down, it was years in front of Android in terms of functionality and platform matureness.

  48. 48
    hamza:

    I think i just found a solution for my problem.
    http://stackoverflow.com/questions/10689193/execute-file-from-defined-directory-with-runtime-getruntime-exec/10690899#10690899
    I will test it tonight. the solution is to exec chmod +x for my file (from my java code) then launch the compiled code from a directory where i have right to write so i can save the screen.bmp. :)
    I don’t know if it’ll work.
    Thanks a lot for you’re tuto

  49. 49
    Radu Motisan:

    unfortunately that doesn’t help. see my previous comment.

  50. 50
    hamza:

    but i’m using a rooted phone. and my application is only for the rooted ones

  51. 51
    Radu Motisan:

    in this case it will work.

  52. 52
    hamza:

    Hi Radu, i just want to know if your compiled file close after taking the screenshot. because in my case when i do ./capturescr in my adb shell it execute the file, i get the screen but the file won’t close without pressing [Ctrl+C]. Any idea ?

  53. 53
    Radu Motisan:

    Looking at the code, the native program simply saves that file as BMP and exits with return 0. You should no need CTRL+C , but feel free to debug the code and see where it gets stuck on your hardware.

    But I think there’s a different issue there, better double check how you are calling that code.

  54. 54
    hamza:

    I finally find a way to work with it :) .Thanks so much for your help.

  55. 55
    Radu Motisan:

    Feel free to provide more details and explain what you did: Others reading this might need your help too.

  56. 56
    hamza:

    I think it’s not a good way to do it but it work for me.
    I just put your compiled file in my raw folder then i copy it to files of my application. execute it from an exec and then destroy my process because the compiled file won’t close automatically as i say before. Here the code :)

    private void doScreen(){
    try {
    //copy from raw
    InputStream ins = getResources().openRawResource(R.raw.capturescr);
    byte[] buffer;
    buffer = new byte[ins.available()];
    ins.read(buffer);
    ins.close();
    FileOutputStream fos = openFileOutput(“capturescr”, Context.MODE_WORLD_READABLE);
    fos.write(buffer);
    fos.close();
    //get permission
    Process process = Runtime.getRuntime().exec(“chmod +x “+getFilesDir()+”/capturescr”);
    process.waitFor();
    //execute the screen
    process = Runtime.getRuntime().exec(getFilesDir()+”/capturescr”,null,getFilesDir());
    Thread.sleep(1000);
    //kill the process
    process.destroy();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

  57. 57
    lanmic:

    Hi Radu, I just want to display YUV420sp(or YUV420p) video in ndk. You know, convert it to rgb565 then display is time consuming(the video is 720P). Can I use framebuffer in ndk to display yuv420SP/yuv420p ? any suggestions for that? thanks very much.

  58. 58
    Radu Motisan:

    Hello lanmic,

    It is possible , but you will distort the normal Android screen output by doing this. Your pushed content will look like some kind of unpolished overlay.

    I had a sample to draw some content directly with FB, I’ll see if I can find it.

  59. 59
    lanmic:

    great thanks. and have you any ideas on, what is a better way to display yuv420sp/yuv420p video with high definition(e.g. 1080p) in ndk?

  60. 60
    Karan:

    Hi Radu,
    I am new to NDK.Can you tell me how to call native method in java.
    i had put capturescr.c,format.h and pixelflinger.h in jni folder.
    Below is my mk and java file code.

    Andori.mk

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)

    LOCAL_MODULE := jreet
    ### Add all source file names to be included in lib separated by a whitespace
    LOCAL_SRC_FILES := capturescr.c

    include $(BUILD_SHARED_LIBRARY)

    Java file

    static
    {
    System.loadLibrary(“jreet”);
    }

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

    }
    Code compiles successfully but does not create screen.bmp file on sdcard.

    Please help what changes I have to make to work it properly.
    Thanks in advance.

  61. 61
    Seth:

    great article. I’m compiling android for panda as we speak. I’m diving through the code to find the fastest readback point. Would you say this is the fastest and easiest way to get a full screen readback? Glreadpixels is an awful pipeline stall. The goal is a to stream the output to disk

  62. 62
    Radu Motisan:

    Yes, this should be the fastest approach.

  63. 63
    Abhinav:

    Hi,

    I am trying to capture the screenshot of the device but I am unable to read the framebuffer file. I followed the steps mentioned in this post but the open call to the framebuffer file is failing. The code is simple,

    int fd = open(“/dev/graphics/fb0″, O_RDWR);
    if(fd /mnt/sdcard/fb0″);
    This java code seems to work.

    I wanted to know if there is anything else which I may be missing in my jni code.

    Thanks and Regards,
    Abhinav

  64. 64
    Abhinav:

    Sorry the comment seems to have been cut short the previous time

    I am trying to capture the screenshot of the device but I am unable to read the framebuffer file. I followed the steps mentioned in this post but the open call to the framebuffer file is failing. The code is simple,

    int fd = open(“/dev/graphics/fb0″, O_RDWR);
    if(fd < 0) {
    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Could not open framebuffer file!);
    return JNI_FALSE;
    }

    This piece of code always returns false. I have a rooted phone running cyanogen mod.

    Thanks and Regards,
    Abhinav

  65. 65
    Radu Motisan:

    make sure you’ve set the permissions for /dev/graphics/fb0 with chmod first.

  66. 66
    Karan:

    Hi Radu,

    I have 2 queries.
    1. Finally I am able get Image on Samsung Tab(2.2).But I am getting the same problem(blue color is showing as orange, and orange color is shown as blue) as Zeshan.Please write in detail how can I invert blue channel with the red one. Where in Code I have to make changes.
    2. On MotorolXoom I have change the the permission of fbo.Below is shell response.
    # cd /dev/graphics
    cd /dev/graphics
    # ls -l
    ls -l
    crwxrwxrwx root graphics 29, 0 2012-07-26 13:22 fb0
    crwxrwxrwx root graphics 29, 1 2012-07-26 13:22 fb1
    But when I run the application it gives error in Logcat
    07-26 16:17:43.050: D/JazzkActivity(5666): cannot open fb0:-1

    Please help!!!!!!!!!!!

  67. 67
    Radu Motisan:

    @Karan, simply change the Blue channel with the Red channel.

    for 2), is the file path correct?

  68. 68
    Karan:

    Hi,
    Thanks Radu for replying.

    1. done for first problem Now I am getting the exact colors.
    2. (a)for fbo i am writing like this
    fd = open(“/dev/graphics/fb0″, O_RDWR);
    (b) shell path is right as i am doing cd to /dev/graphics. ls -l showing files in current path and their permissions and output shows that that i have given permission to file.
    (c) capture image path is bmpfile = fopen(“/mnt/sdcard/screen.bmp”, “wb”);

    FYI—MotorolXoom sdk version is 3.2

    Please help to solve my problem!!!!!

  69. 69
    Radu Motisan:

    So you’re saying it fails at a) ?

  70. 70
    Android Overlay cursor « PocketMagic:

    [...] can draw the cursor at the framebuffer level, and while this provides optimum performance, it requires special privileges that regular apps [...]

  71. 71
    Karan:

    @Radu yes, it is failing at 2(a)

  72. 72
    Karan:

    Hi,

    The same case is with ACER ICONIA TAB(3.0.1). Device is rooted and permissions are set. but failing while opening file “fb0″. I think code works only at SDK version (2.2 and below).
    Please provide some solution which will work on 2.3 and above SDK version.

  73. 73
    Radu Motisan:

    what’s the value returned by fd? Did you check the error codes to identify the problem?

  74. 74
    Karan:

    Hi,

    fd value is -1.

  75. 75
    Karan:

    Hi,

    I had also try to pull,cat and cp command to copy fb0 file but it gives the following error.

    C:\Users\karan>adb pull /dev/graphics/fb0 /mnt/sdcard/fb0
    failed to copy ‘/dev/graphics/fb0′ to ‘/mnt/sdcard/fb0′: Device or resource busy

    i t is giving the same error for cat and cp “Device or resource busy”
    I search google but didn’t find anything. I think this is the reason why I am unable to open file file.

    Please help!!!!

  76. 76
    yangbo:

    hi,things worked out just fine ,no errors,except that the pic I got is totally black.And the same code works out on another android phone ,but always returns a black pic on my Galaxy Nexus.Please help.Thanks a lot.

  77. 77
    karunakaran:

    Hi ,,
    where i can see the Screen.bmp file ???
    My android Emulator rooted , but it cant able to open /dev/graphics/fb0

    Kindly Help me …

  78. 78
    MinhBinh:

    fd = open(“/dev/graphics/fb0″, O_RDWR);
    if(fd < 0) {
    perror("cannot open fb0");
    return -1;
    }

    My application always fails here. Is there any way to run the command "chmod 777 /dev/graphics/fb0" programatically?
    My devices is rooted.

  79. 79
    MinhBinh:

    I face this problem on Galaxy tab 10.1 (android 3.1) only. Everything fine on Nook-Color (Android 2.2)

  80. 80
    MinhBinh:

    Hi, I have resolved this by myself. I share the solution here for someone who is looking for it.
    This is how I change the system file permission.

    Process sh = Runtime.getRuntime().exec(“su”,null,new File(“/dev/graphics/”));
    OutputStream os = sh.getOutputStream();
    writeCommand(os, “chmod 777 /dev/graphics/fb0″);
    os.flush();

    readFrameBuffer();

  81. 81
    Prashant:

    Hello Radu,
    Is it possible to send this data to a Microcontroller to display it on another screen (Example: TV). Do I need to convert it into BMP or I can send raw data to the microcontroller in bytes and then to the TV screen.
    Thanks in advance.

  82. 82
    Radu Motisan:

    everything is possible, it would be better to convert it to RGB24 and see how to get to SVIDEO signal from there, that would be compatible with the TV.

  83. 83
    AC:

    Hi Radu,
    Thanks for a nice and wonderful blog.

    I saw your code and tried it for Samsung Galaxy SII, with some modification
    Actually I called function get_framebuffer() in while loop of 60 and saved all bmps after starting timer in mobile.
    It saved around 15 bmps per Second, but I saw bmps showed alternative seconds like 59,57,55,53 ….
    I tried to find the problem but failed.
    Please take a look on that and reply ASP.

    I hope you were doing great!!!

  84. 84
    Mamatha:

    Hi Radu,
    I am developing a application where user can draw/write something on the screen, and this is recorded as video. Then the user can see the video. How can I proceed? request ur guidance.
    Thanks in advance :)

  85. 85
    Arjun:

    Is it compulsory to access the framebuffer via a command-prompt,after connecting the mobile to PC,can I access this code by making the methods available in this code as a native method,and can I invoke it in a Java file using JNI,without the use of command-prompt,and without connecting the mobile everytime?

  86. 86
    Radu Motisan:

    @arjun, you can invoke chmod from your java source code. so you don’t need to connect to the PC.

  87. 87
    Kalandar:

    hi radu motisan… thank you for your share… i tried this code but the execution returned after this below if condition..

    fd = open(“/dev/graphics/fb0″, O_RDWR);
    if(fd < 0) {
    perror("cannot open fb0");
    return -1;
    }

    please help me… i am using rooted device only(xperia neo v (ICS))..
    what

  88. 88
    SKC:

    Hi

    When i am trying to make a call to the native function get_framebuffer from my Main activity, i am getting a return value of -1. Please note that i am trying to use it from a system app which is signed with proper signatures to access all the system level privileges.

    Is it not possible to access the fb0 file from the JNI code? Please suggest on the following.

  89. 89
    SKC:

    Is it possible to access the fb0 file without using “su” to run your this as a native code ?

  90. 90
    Radu Motisan:

    @Kalandar: you need to chmod fb0 as explained in the article

    @SKC: you need root to set fb0 permission, see chmod in the article

  91. 91
    SKC:

    Thanks Radu for your answer
    Having an application signed with system certificates isn’t equivalent to a root permission ?
    As suggested by you, I have tried the chmod, but it didn’t work as my phone is not rooted, but whichever app is trying to run these commands are signed with system certificates.

  92. 92
    Radu Motisan:

    @SKC: unfortunately that is not enough, and it is imperative that you set the fb0 permissions or you won’t be able to read it. So no, will not work if your phone is not rooted. Sorry.

  93. 93
    Murdoch1976:

    If someone could wrap this into a library for Basic4Android I’d be very grateful, or even a .jar with a list of properties and methods so I could wrap it myself.

    At the moment, with root access, I am having to spoof a “su” shell command in my Basic4Android code to “cat” the raw “fb0″ file into a temporary folder, and I am now stuck with the nightmare of decoding the raw file to a more useful image format.

    What would be far more useful would be to have this wrapped up in a few useful methods / functions, or perhaps even one such as…

    GrabFrameBuffer(destinationpath,format,quality,width,height)

    I understand this would of course mean that the library would have to detect the exact format of the raw image itself.

    Going right back to this base “C” code, can anyone tell me how quick it runs? I’d like to be able to snapshot fast enough to transcode the snapshots to video (at the very least 15 snaps a second, including conversion to jpg or png)

    Feel free to flame the hell out of me for not being very good at C, or Java, or the SDK in Eclipse, or anything for that matter. It just irks me that a user can press a combination of buttons to take a screenshot on most android devices, but there is no exposed command in the SDK to do so unless it’s a snap of your own activity. Surely there should be an “add permission” that the user could accept to allow your application to snap whatever is on the screen at any time?

  94. 94
    Kunal:

    Hi,
    I tried your code and it gave me http://i.imgur.com/VSWPNBs.png?1 this screenshot. Any idea how can I correct it?

  95. 95
    danQ:

    Hi Radu,

    I downloaded the latest code and ran the capturescr on the adb shell (I just used the provided file and didnt compile), it gave me a screen.bmp file. The image file just have black, blue, and red streaks. After unchecking the “force gpu rendering” option, i get a pix somewhat resembling the screen, but still very streaky.

    My device is a rooted HTC OneX on ICS.
    1. Am I missing anything?
    2. Or is it just not reliable to get the screenshot from the framebuffer in recent devices?

    Thanks

  96. 96
    danQ:

    To add on to the previous post, I noticed a seg fault when running the capturescr. Here’s the link to the screenshot img: http://imgur.com/im8eXW3

  97. 97
    Prav:

    Same thing is happening with me too danQ. I am using a Atrix HD which is almost identical to OneX.

    The dump function gives these values:

    vi.xres = 720
    vi.yres = 1280
    vi.xresv = 720
    vi.yresv = 2560
    vi.xoff = 0
    vi.yoff = 0
    vi.bits_per_pixel = 32
    fi.line_length = 2944

    And the screenshot looks similar to your one.

    Radu???!!!

  98. 98
    Radu Motisan:

    check the bitmap format.

  99. 99
    nll:

    Anyway converting this native code to a function that can be called from within java code and return an image?

  100. 100
    Radu Motisan:

    Yes, it is both possible and easy , using JNI. I might write an article on that later.

  101. 101
    Vish:

    Hello Radu – I am able to use this code and capture screenshots from Samsung phones. But it captures a black screen shot for Nexus 4. Do you know how to correct it?

Thank you for commenting. Your comment won't show until approved, which can take some time.

Please copy the string Hvq1A5 to the field below: