1

I want to execute the screenshot command "adb shell /system/bin/screencap -p /sdcard/img.png" into C. I was searching for the same and I got a solution for another command and I modified the command as

execl("/system/bin/screencap", "-p", "storage/sdcard0/screenShot.png", (char *)NULL);

but when I run my application and call method of above command, application gets crash.

How should I modify the "/system/bin/screencap -p /sdcard/img.png" command to run from C code.


Update after tom answer

Application is getting closed again and here is log

06-21 11:52:01.488: I/WindowState(279): WIN DEATH: Window{40fed2c0 u0 com.mytest.ndktestapplication/com.mytest.ndktestapplication.MainActivity}
06-21 11:52:01.498: I/ActivityManager(279): Process com.mytest.ndktestapplication (pid 7745) has died.
06-21 11:52:01.498: W/ActivityManager(279): Force removing ActivityRecord{40ea9ab8 u0 com.mytest.ndktestapplication/.MainActivity}: app died, no saved state
Community
  • 1
  • 1
Android Learner
  • 2,559
  • 6
  • 34
  • 43
  • why not system() call? – Dayal rai Jun 21 '13 at 11:47
  • I didn't get you. Actually I wan to run the screenshot command from C code. So I am trying? I am not sure that it will be possible by excel(). if you have any idea share with me.. – Android Learner Jun 21 '13 at 11:49
  • is it in c. Can you please give me an example? – Android Learner Jun 21 '13 at 11:54
  • @AndroidLearner Have you tried running it in a shell like suggested in the linked post? `execl("/system/bin/sh", "sh", "-c", "/system/bin/screencap -p storage/sdcard0/jni_knox_test.png")` – tom Jun 21 '13 at 12:04
  • @tom Not working till... but as Chris said that we can't take screenshot most of devices (can only on rooted devices) then it might be possible that this command is running but due to permission issue not giving the result.. I am trying and will update you – Android Learner Jun 21 '13 at 12:15

2 Answers2

3

This is the expected result of exec() family functions.

What they do is replace the current program with the specified one. So bye-bye app.

To avoid that you would first need to call fork(), and then call exec() only in the child, something like this:

if (!fork()) {
    // fork() returned zero, so we are in the child
    execl...
}

You might also have to do some cleanup before calling the exec function.

Note however that you will not be able to take a screenshot from an app on most devices, as application code runs under a user id which lacks the permission to do so. But I seem to recall that there was a narrow period where some devices shipped without permission checks on this functionality, so it might work on those.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
  • You are right for permission issue. this is a major problem which I am facing is that I am unable to know that if command executed or not :(. Is there any other command which can I test to verify that if commands are running? – Android Learner Jun 21 '13 at 12:13
  • Without shell redirection it is a pain to capture output, though you could open a file as *stdout* and then execute 'ls' or something. Or you could use 'am' with a lengthy list of arguments to send an Intent. It may be that you could get an 'sh' to just sit there and detect it in the process list. I forget if you can 'setprop' something entirely custom. Writing you own program which logs hello world with the android native log function would be an option too. There's probably a perfect idea I am not thinking of. – Chris Stratton Jun 21 '13 at 12:19
  • Is there any simple command which I can run and test that `excel()` is executing or not? – Android Learner Jun 21 '13 at 12:28
  • @AndroidLearner See [Check running processes in C](http://stackoverflow.com/questions/5460702/check-running-processes-in-c). – tom Jun 21 '13 at 12:28
  • 2
    An exec function failing to return - and thus crashing your program - is ironically a hint of success. See the execve linux manual page, which will mostly apply. – Chris Stratton Jun 21 '13 at 12:44
1

The invocation is

execl(path, arg0, arg1, ..., (char*) NULL);

The second argument, arg0, is the name the program is told was used to invoke it. The actual arguments given to the program only start at arg1.

So you should change your code to

execl("/system/bin/screencap", "screencap", "-p", "<pic>", (char *)NULL);
tom
  • 21,844
  • 6
  • 43
  • 36
  • Hi tom, I used your code but result is same. application is getting closed. Can you give idea about `system()` plz – Android Learner Jun 21 '13 at 11:57
  • `system("/system/bin/screencap -p storage/sdcard0/jni_knox_test.png")`, but I don't think it will give you different results. – tom Jun 21 '13 at 11:59
  • 1
    system() should at least avoid the crash, as unlike the exec family it is not fatal to the calling program. Basically the implementation forks a child to execute the command, and the parent waits for that child to terminate before returning. – Chris Stratton Jun 21 '13 at 12:28
  • 1
    hey tom You helped me alot but chris was more correct, thts why I am accepting the answer... Thanks alot – Android Learner Jun 21 '13 at 14:17