|
Android Native Screen capture application using the FramebufferBy Radu Motisan Posted on November 18th, 2010 , 6244 Views (Rate 6.81) |
|
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:
static int get_framebuffer(GGLSurface *fb) { int fd; void *bits; fd = open("/dev/graphics/fb0", O_RDWR); if(fd < 0) { perror("cannot open fb0"); return -1; } if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { perror("failed to get fb0 info"); return -1; } if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) { perror("failed to get fb0 info"); return -1; } //dumpinfo(&fi, &vi); bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(bits == MAP_FAILED) { perror("failed to mmap framebuffer"); return -1; } fb->version = sizeof(*fb); fb->width = vi.xres; fb->height = vi.yres; fb->stride = fi.line_length / (vi.bits_per_pixel >> 3); fb->data = bits; fb->format = GGL_PIXEL_FORMAT_RGB_565; fb++; fb->version = sizeof(*fb); fb->width = vi.xres; fb->height = vi.yres; fb->stride = fi.line_length / (vi.bits_per_pixel >> 3); fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2); fb->format = GGL_PIXEL_FORMAT_RGB_565; return fd; }
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.
//convert pixel data uint8_t *rgb24; if (depth == 16) { rgb24 = (uint8_t *)malloc(w * h * 3); int i = 0; for (;i<w*h;i++) { uint16_t pixel16 = ((uint16_t *)gr_framebuffer[0].data)[i]; // RRRRRGGGGGGBBBBBB -> RRRRRRRRGGGGGGGGBBBBBBBB // in rgb24 color max is 2^8 per channel (*255/32 *255/64 *255/32) rgb24[3*i+2] = (255*(pixel16 & 0x001F))/ 32; //Blue rgb24[3*i+1] = (255*((pixel16 & 0x07E0) >> 5))/64; //Green rgb24[3*i] = (255*((pixel16 & 0xF800) >> 11))/32; //Red } } else if (depth == 24) { rgb24 = (uint8_t *) gr_framebuffer[0].data; } else { //free close(gr_fb_fd); exit(2); }; //save RGB 24 Bitmap int bytes_per_pixel = 3; BMPHEAD bh; memset ((char *)&bh,0,sizeof(BMPHEAD)); // sets everything to 0 //bh.filesize = calculated size of your file (see below) //bh.reserved = two zero bytes bh.headersize = 54L; // for 24 bit images bh.infoSize = 0x28L; // for 24 bit images bh.width = w; // width of image in pixels bh.depth = h; // height of image in pixels bh.biPlanes = 1; // for 24 bit images bh.bits = 8 * bytes_per_pixel; // for 24 bit images bh.biCompression = 0L; // no compression int bytesPerLine; bytesPerLine = w * bytes_per_pixel; // for 24 bit images //round up to a dword boundary if (bytesPerLine & 0x0003) { bytesPerLine |= 0x0003; ++bytesPerLine; } bh.filesize = bh.headersize + (long)bytesPerLine * bh.depth; FILE * bmpfile; //printf("Bytes per line : %d\n", bytesPerLine); bmpfile = fopen("screen.bmp", "wb"); if (bmpfile == NULL) { close(gr_fb_fd); exit(3); } fwrite("BM",1,2,bmpfile); fwrite((char *)&bh, 1, sizeof (bh), bmpfile); //fwrite(rgb24,1,w*h*3,bmpfile); char *linebuf; linebuf = (char *) calloc(1, bytesPerLine); if (linebuf == NULL) { fclose(bmpfile); close(gr_fb_fd); exit(4); }
Now the next thing to do is to align the BGR triplets and to switch order , to match the BMP RGB24 color format.
int line,x; for (line = h-1; line >= 0; line --) { // fill line linebuf with the image data for that line for( x =0 ; x < w; x++ ) { *(linebuf+x*bytes_per_pixel) = *(rgb24 + (x+line*w)*bytes_per_pixel+2); *(linebuf+x*bytes_per_pixel+1) = *(rgb24 + (x+line*w)*bytes_per_pixel+1); *(linebuf+x*bytes_per_pixel+2) = *(rgb24 + (x+line*w)*bytes_per_pixel+0); } // remember that the order is BGR and if width is not a multiple // of 4 then the last few bytes may be unused fwrite(linebuf, 1, bytesPerLine, bmpfile); } fclose(bmpfile); close(gr_fb_fd);
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:

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:
if (depth == 32) //skip transparency channel { rgb24 = (uint8_t *) malloc(w * h * 3); int i=0; for (;i<w*h;i++) { uint32_t pixel32 = ((uint32_t *)gr_framebuffer[0].data)[i]; // in rgb24 color max is 2^8 per channel rgb24[3*i+0] = pixel32 & 0x000000FF; //Blue rgb24[3*i+1] = (pixel32 & 0x0000FF00) >> 8; //Green rgb24[3*i+2] = (pixel32 & 0x00FF0000) >> 16; //Red } }
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:
echo $?
|
|























November 18th, 2010 at 1:15 pm
[...] « Android Native Screen capture application using the Framebuffer [...]
April 26th, 2011 at 11:55 am
How to do this for a 32 bit depth screen
April 26th, 2011 at 12:51 pm
its very much the same code, see if (depth == 24) …
June 14th, 2011 at 8:55 am
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?
June 14th, 2011 at 4:57 pm
do you have root access?
June 15th, 2011 at 2:01 pm
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?
August 12th, 2011 at 6:45 am
Is it possible to access framebuffer via JNI?
August 12th, 2011 at 9:47 am
yes, you simply compile my code above with a JNI interface.
August 12th, 2011 at 10:53 am
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?
August 12th, 2011 at 11:38 am
Thanks, you’re right.
I forgot chmod 777 /dev/graphics/fb0.
August 12th, 2011 at 10:26 pm
good.
November 8th, 2011 at 10:37 pm
How to do this for a 32 bit depth screen…
Can you explain more detail?
November 9th, 2011 at 8:50 am
hello gyeonghochu, what do you need to know?
November 9th, 2011 at 3:59 pm
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…
November 23rd, 2011 at 8:49 am
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″);
November 23rd, 2011 at 8:59 am
Hi,
It is a rooted device,requested for super user access after SU command but fb0 is not accessible.
December 28th, 2011 at 10:02 pm
hy, can you tell me what to put in
else if( depth == 32 ){
??????
}
can someone help me?
February 17th, 2012 at 9:54 am
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++;
}
February 24th, 2012 at 11:43 am
Is necessary have be root
March 4th, 2012 at 10:17 pm
hi every body
i am new to android development i just want to know that the code above will work in eclipse or not.
April 3rd, 2012 at 1:07 pm
New code added to this article. Enjoy!
April 9th, 2012 at 3:06 pm
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
April 10th, 2012 at 9:20 am
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.
April 13th, 2012 at 4:40 pm
Hi,
Can’t we save the image in jpeg or png format, instead of BMP??? if so, than how to do it??
April 13th, 2012 at 8:08 pm
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
April 16th, 2012 at 8:32 am
For me blue color is showing as orange, and orange color is shown as blue….
any help?
April 16th, 2012 at 10:17 am
Just invert blue channel with the red one.
April 16th, 2012 at 11:32 am
Thanks a lot Radu !! It works perfectly fine now !! Its been a great help by you.
April 16th, 2012 at 11:34 am
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.
April 16th, 2012 at 4:20 pm
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.
April 25th, 2012 at 3:50 pm
hi,
when i change android minsdk version 3 to 4 code does not work.any reason???
Thanks in advance
April 30th, 2012 at 6:15 pm
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
April 30th, 2012 at 6:42 pm
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.
May 1st, 2012 at 2:54 pm
Works very well… thanks Radu. Kind regards.
May 7th, 2012 at 6:47 am
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
May 7th, 2012 at 9:52 am
@shah, see the NDK tutorial, here is the link again: http://www.pocketmagic.net/?p=1462
May 10th, 2012 at 4:23 pm
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
May 10th, 2012 at 4:58 pm
@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.
May 10th, 2012 at 9:55 pm
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…
May 11th, 2012 at 11:25 am
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.
May 11th, 2012 at 4:41 pm
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
May 11th, 2012 at 4:44 pm
It is not enough to install cygwin and unzip the NDK, you will need to follow all the instructions presented there.
May 11th, 2012 at 4:57 pm
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
May 21st, 2012 at 1:03 pm
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 .
May 21st, 2012 at 3:03 pm
@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)
May 21st, 2012 at 3:13 pm
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 ^^ ).
May 21st, 2012 at 7:41 pm
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.
May 21st, 2012 at 11:27 pm
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
May 21st, 2012 at 11:32 pm
unfortunately that doesn’t help. see my previous comment.
May 21st, 2012 at 11:33 pm
but i’m using a rooted phone. and my application is only for the rooted ones
May 22nd, 2012 at 10:11 am
in this case it will work.
May 22nd, 2012 at 10:36 am
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 ?
May 22nd, 2012 at 1:16 pm
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.
May 22nd, 2012 at 1:23 pm
I finally find a way to work with it
.Thanks so much for your help.
May 22nd, 2012 at 1:28 pm
Feel free to provide more details and explain what you did: Others reading this might need your help too.
May 22nd, 2012 at 1:37 pm
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();
}
}
May 28th, 2012 at 8:52 am
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.
May 28th, 2012 at 9:34 am
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.
May 28th, 2012 at 1:20 pm
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?
May 31st, 2012 at 8:53 am
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.
June 15th, 2012 at 6:26 am
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
June 15th, 2012 at 10:14 am
Yes, this should be the fastest approach.
June 16th, 2012 at 1:21 am
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
June 16th, 2012 at 1:23 am
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
June 16th, 2012 at 11:55 am
make sure you’ve set the permissions for /dev/graphics/fb0 with chmod first.
July 26th, 2012 at 12:49 pm
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!!!!!!!!!!!
July 26th, 2012 at 2:21 pm
@Karan, simply change the Blue channel with the Red channel.
for 2), is the file path correct?
July 27th, 2012 at 8:56 am
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!!!!!
July 27th, 2012 at 1:03 pm
So you’re saying it fails at a) ?
July 27th, 2012 at 5:59 pm
[...] can draw the cursor at the framebuffer level, and while this provides optimum performance, it requires special privileges that regular apps [...]
July 28th, 2012 at 5:22 am
@Radu yes, it is failing at 2(a)
July 28th, 2012 at 8:08 am
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.
July 28th, 2012 at 7:19 pm
what’s the value returned by fd? Did you check the error codes to identify the problem?
July 30th, 2012 at 9:11 am
Hi,
fd value is -1.
July 30th, 2012 at 2:07 pm
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!!!!
August 1st, 2012 at 1:37 pm
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.
August 3rd, 2012 at 3:57 pm
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 …
September 5th, 2012 at 8:10 am
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.
September 5th, 2012 at 12:49 pm
I face this problem on Galaxy tab 10.1 (android 3.1) only. Everything fine on Nook-Color (Android 2.2)
September 11th, 2012 at 11:49 am
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();
October 24th, 2012 at 10:59 am
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.
October 24th, 2012 at 1:25 pm
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.
December 19th, 2012 at 1:47 pm
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!!!
January 22nd, 2013 at 7:56 am
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
February 18th, 2013 at 7:03 pm
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?
February 18th, 2013 at 9:54 pm
@arjun, you can invoke chmod from your java source code. so you don’t need to connect to the PC.
March 4th, 2013 at 2:26 pm
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
March 11th, 2013 at 11:50 am
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.
March 11th, 2013 at 1:08 pm
Is it possible to access the fb0 file without using “su” to run your this as a native code ?
March 11th, 2013 at 1:12 pm
@Kalandar: you need to chmod fb0 as explained in the article
@SKC: you need root to set fb0 permission, see chmod in the article
March 11th, 2013 at 2:59 pm
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.
March 11th, 2013 at 3:27 pm
@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.
March 13th, 2013 at 1:45 am
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?
March 13th, 2013 at 9:13 am
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?
March 19th, 2013 at 5:35 pm
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
March 19th, 2013 at 10:31 pm
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
April 30th, 2013 at 2:10 am
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???!!!
April 30th, 2013 at 12:22 pm
check the bitmap format.
May 7th, 2013 at 10:44 pm
Anyway converting this native code to a function that can be called from within java code and return an image?
May 8th, 2013 at 1:56 pm
Yes, it is both possible and easy , using JNI. I might write an article on that later.
May 20th, 2013 at 7:57 am
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?