Unable to execute sendevent shell command through the android code - android

I have tried following code snippet to execute the batch of command for sendevent to click the coordinate 44,129 on the emulator. But it is not showing any result. But if i am giving the same batch of command to the shell prompt it is able to click the mentioned coordinate succesfully.
String[] cmmandemulatorarr = {"/system/bin/sendevent /dev/input/event0 3 0 44",
"/system/bin/sendevent /dev/input/event0 3 1 129",
"/system/bin/sendevent /dev/input/event0 1 330 1",
"/system/bin/sendevent /dev/input/event0 0 0 0",
"/system/bin/sendevent /dev/input/event0 1 330 0",
"/system/bin/sendevent /dev/input/event0 0 0 0", };
for (int i = 0; i < cmmandemulatorarr.length; i++) {
Process process =
Runtime.getRuntime().exec(cmmandemulatorarr[i]);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
Is there is anything i am missing here or i have to try something else to get click event on some coordinate through the code.
Note :: I am not getting any exception in the log while executing the code which seems that command is executed successfully.
Regards
Pinu

But it is not showing any result.
This is a good thing.
But if i am giving the same batch of command to the shell prompt it is able to click the mentioned coordinate succesfully.
The shell runs with root-level privileges. Your SDK application does not, unless you root your device and arrange to execute your code that way.
Bear in mind that not all devices will have a /system/bin/sendevent command and it can be removed at any time. This is not part of the Android SDK.
i have to try something else to get click event on some coordinate through the code.
This is not possible from the Android SDK for ordinary devices, for obvious security reasons.

Here you have answer. You need to find touch event id with getevent. Sendevent use decimal space, getevent use hex. This code from first "answer" works on 7.0.

Related

Adb sleep function working on adb but not in a .sh file

i am trying to make a simple "tap and wait" script to run on my Android device through adb.
Opening adb on Powershell with the command ./adb shell works, running input tap 300 300 works, and running sleep 1does sleep for a second.
However, if I run a test.sh script with the Powershell command ./adb shell "sh /sdcard/Download/test.sh" the tapping part still works, but the sleep call gives me this instead: 'sdcard/Download/MIOPROGRAMMA.sh[2]: sleep: syntax error: Invalid argument '1 .
Any idea why this happen?
Just add ; after the int, i.e.:
input tap 250 250
sleep 3;
input tap 350 250
sleep 3;
input tap 450 250
sleep 3;
input tap 550 250
sleep 3;
input tap 650 250
sleep 3;
Why not use powershell's Start-Sleep cmdlet ? Have all your logic in the powershell script.
$sendTapCmd = "adb shell `"input tap 250 250`" "
$numberOfTaps = 5
for ($i=0;$i -lt $numberOfTaps;$i++) {
$output = Invoke-Expression $sendTapCmd
Start-Sleep -Milliseconds 3
}

Process getRuntime taking a long time - Android

I am working on a new application and I need to input some Shell command into android , however it seems that my command is taking quite a long time to start
Process process = Runtime.getRuntime().exec("top -m 10 -n 10");
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
while ((line = reader.readLine()) != null) {
//Parsing result to a StringBuffer
(...)
}
Almost half of the total time (34sec) is used to start the process , is it normal ?
Is there a way to do something. This is in an Async Task , however for the first 17sec there is nothing display on the textView which is quite annoying ...
If you have any idea , just comment !
-n 10 means update the display 10 times and then exit. You don't need 10 updates, 1 is enough. Use this command instead and it should be much faster:
top -m 10 -n 1

How to get the content of /dev/logo in shell?

I can read the content of /dev/logo in C,
fd = open("/dev/logo", O_RDONLY);
len = read(fd, logo_addr, 512);
Now I want to do these things using shell command, how to do?
Can I use
$ adb shell cat dev/logo >logo.dev
?
Are you able to use dd? Something like:
dd /dev/logo bs=1 count=512 of=logo.dev
Assuming you need to read 512 bytes of the device.

Android simulate fast swipe

I am doing a generic automation script.
I need to send complex swipe events to the android screen without specifically having access to the focused application(s)
Best way I figured so far is to use adb, create a file with sendevent commands, push it on the device and run it from there. Even that, it is painfully slow (much slower compared to if I record it with getevent and pipe it back in).
I managed to optimize the file since I figured out that each sendevent block does not specifically require both X and Y, but it is still a few orders of magnitude slower
Example of part of the file (I'm trying on a HTC One):
sendevent /dev/input/event5 3 57 49
sendevent /dev/input/event5 3 53 942
sendevent /dev/input/event5 3 54 2747
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1207
sendevent /dev/input/event5 3 54 2483
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1472
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 54 2218
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1207
sendevent /dev/input/event5 3 54 2483
sendevent /dev/input/event5 0 0 0
sendevent /dev/input/event5 3 53 1472
So my focus is to optimize the speed of single long-complex swipes, not of multiple small ones.
Anyone know of a better way to do this?
So, Chris Stratton's idea worked in principle (re-piping the cat-ed output generates the same swipe successfully), but I can't be able to create my own code to pipe it back in. I'm guessing it's something to do with the separators between send event commands... but I still can't get it to work
I used a modification of the sendevent.c file to get a file with triples per line and output to another file. Do you happen to know what could be the issue? Conversion looks good ...
SOLLUTION: I managed to solve it, mostly thanks to the answers bellow. Here is a C script that takes a file with HEX values and outputs the appropriate binary file.
Usage: (for me the touch driver file is /dev/input/event5 - HTC One - for other devices it might be a different file !!!)
$> adb shell getevent > tmp.in
$> ./sendevent tmp.in tmp.out
$> adb shell push tmp.out /mnt/sdcard/
$> adb shell "cd /mnt/sdcard/ && cat tmp.out > /dev/input/event5"
and the source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
typedef uint32_t __u32;
typedef uint16_t __u16;
typedef __signed__ int __s32;
__attribute__((aligned(1),packed)) struct input_event {
__u32 time_dummy_1;
__u32 time_dummy_2;
__u16 type;
__u16 code;
__s32 value;
};
int convert (char * str) {
return (int) strtol(str, NULL, 16);
}
#define S_ALL (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH)
int main (int argc, char *argv[]) {
int i;
int fd;
int ret;
if(argc < 3) {
fprintf(stderr, "use: %s in-file out-file\n", argv[0]);
return 1;
}
fd = open(argv[2], O_CREAT | O_WRONLY, S_ALL);
if(fd < 0) {
fprintf(stderr, "could not open %s, %s\n", argv[2], strerror(errno));
return 1;
}
FILE * fd_in = fopen(argv[1], "r");
if (fd_in == NULL) {
fprintf(stderr, "Can't open input file: %s\n", argv[1]);
return 1;
}
struct input_event event;
char type[32];
char code[32];
char value[32];
int count = 0;
while (fscanf(fd_in, "%s %s %s", type, code, value) != EOF) {
memset(&event, 0, sizeof(event));
// printf("%d) %s %s %s\n", ++count, type, code, value);
event.type = convert(type);
event.code = convert(code);
event.value = convert(value);
memset(type, 0, sizeof(type));
memset(code, 0, sizeof(code));
memset(value, 0, sizeof(value));
ret = write(fd, &event, sizeof(event));
if(ret < sizeof(event)) {
fprintf(stderr, "write event failed, %s\n", strerror(errno));
return -1;
}
}
return 0;
}
Please note that this answer pertains to circa-2013 versions of Android and may not apply to current ones. Jellybean was contemporary at the time, Kitkat came out a few weeks after the question was asked
Your delay is likely a result of inefficiently having to repeatedly launch a new sendevent process, parse the textual event record, and open the device node - for each individual event. If you instead do everything from within a single process, opening the device file only once, it will be much more efficient.
If we look at the source for sendevent in toolbox contemporary with the date of the question (for example, https://android.googlesource.com/platform/system/core/+/jb-release/toolbox/sendevent.c ) we see that the core of what it is doing is encoding the events into binary records
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
and writing them to the appropriate device
memset(&event, 0, sizeof(event));
event.type = atoi(argv[2]);
event.code = atoi(argv[3]);
event.value = atoi(argv[4]);
ret = write(fd, &event, sizeof(event));
Provided that you are executing something as the shell userid or another in the input unix group, you should be able to accomplish the same thing that sendevent does from your own custom program, or using other command line tools like cat, thus efficiently pushing a binary file of event records.
For example
adb shell
cd /mnt/sdcard
cat /dev/input/event2 > events
Do a few touch screen events, then ctrl-C to kill cat
Now you can play back the captured file of binary events:
cat events > /dev/input/event2
(Note: sendevent is zeroing the timeval part of each record; recording and playback may not do that; you'll have to see, and if it matters zero those portions of each record from the file before you write it back)
If you just want to produce linear swipes, you can use input swipe command on shell.
$ adb shell input
usage: input ...
input text <string>
input keyevent <key code number or name>
input [touchscreen|touchpad|touchnavigation] tap <x> <y>
input [touchscreen|touchpad|touchnavigation] swipe <x1> <y1> <x2> <y2> [duration(ms)]
input trackball press
input trackball roll <dx> <dy>
Command below draws a nice line for me in a drawing application
$ adb shell input swipe 300 300 500 1000
and a quicker one
$ adb shell input touchscreen swipe 300 300 500 1000 100

Retrieve default gateway of android phone

I am coding a native application in android and I need to get the default gateway of a device on my application. Here is my current code to get the default gateway.
static int get_default_gateway(char *def_gateway, int buf_size)
{
FILE* pipe;
char buffer[128];
char result[2049];
char cmd[] = "netstat -r | grep ^default | awk '{print $2}'";
pipe = popen(cmd, "r");
if (!pipe) return 1;
memset(result, 0, sizeof(result));
while(!feof(pipe)) {
memset(buffer, 0, sizeof(buffer));
if(fgets(buffer, 128, pipe) != NULL)
{
strcat(result, buffer);
}
}
pclose(pipe);
memset(def_gateway, 0, buf_size);
strncpy (def_gateway, result, buf_size );
return 0;
}
It works on my LG p500 but on some devices it doesn't return anything.
My question is: Does popen() works on android? I read somewhere that it is not included in bionic.
And is there any other method to get the default gateway? I need it to be written in C and not java.
Thank you
Yea, probably popen() should work on any Android. But unfortunately grep and awk - not. Take a look at /proc/net/route - line where Destination equals to 00000000 is your default gateway. Also perhaps you can use NETLINK_ROUTE socket, though I never used it and can't say more.
See also this related question.

Categories

Resources