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.
Related
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
}
I am writing a small code to search for a number in whatsapp and send a text message.
I am able to send text message if I type in the script itself, but I wanted to paste the message from a file.
Is there any way to copy the content from a file instead os using the adb shell input text command.
My code below.
adb shell input keyevent 82
adb shell am force-stop com.whatsapp
adb shell am start -n com.whatsapp/.Main
adb shell input text "9800000000"
adb shell input keyevent 66
adb shell input text 'This%sis%sa%stest%smessage'
adb shell input keyevent 66
adb shell input text 'I%sam%schecking%slots%sof%sthings'
adb shell input keyevent 61
adb shell input keyevent 61
adb shell input keyevent 66
adb shell am force-stop com.whatsapp
Thanks,
Deepak
You don't say which scripting language you are using.
You can do it from a Native binary (written in C/C++).
1. Open the file for reading.
2. LOOP
3. Read a line into a string.
4. convert all special characters to escape strings
5. Use the command system to send the text:
system("input "text Hello%sWorld");
6. LOOP
I wrote such a binary called inputer. pasting into it works quite well, but
each line is fork/exec'd so big files can get out of order, you need to test for each line completing or send as one huge call.
Yes, you actually can do this. It's kind of kludgy looking when you inspect the clipboard, but it works just fine.
First off, you can inspect the current clipboard contents with service call clipboard 1 from an adb shell (or, without shelling in first, adb shell service call clipboard 1). It may start out initially blank after a reboot, for example:
service call clipboard 1
Result: Parcel(
0x00000000: 00000000 00000001 00000000 00000000 '................'
0x00000010: 00000000 00000000 '........ ')
#
You can put text into the clipboard using service call clipboard 2, which basically takes 3 parameters - two ints and the string you want to put on the clipboard:
# service call clipboard 2 i32 1 i32 0 s16 "Hi there"
Result: Parcel(00000000 '....')
To be honest, I'm not sure what the first two parameters are. One answer on Stack Overflow has suggested the first int is "number of items in the parcel" (one in this case) and that the second is the length of the string. However, I've used 0 for the second parameter and it works fine, and I can't find any documentation that matches up with this particular function...so take that for what it's worth.
In any case, it's basically creating a Parcel object with 3 fields, then passing it into the clipboard. The clipboard then unpacks the Parcel and sets the string value passed in as the clipboard's contents. You can see this when you go to retrieve the value afterwards:
# service call clipboard 1
Result: Parcel(
0x00000000: 00000000 00000001 00000000 00000008 '................'
0x00000010: 00690048 00740020 00650068 00650072 'H.i. .t.h.e.r.e.'
0x00000020: 00000000 00000000 '........ ')
#
Similarly, if you long-press on a text entry field and hit "Paste" after doing this, you will get the text that was set via the call service clipboard 2 line above (and it will look completely normal).
(The above examples come from my HTC EVO, running CyanogenMod 7)
Reference : https://android.stackexchange.com/questions/19710/is-it-possible-to-write-to-a-devices-clipboard-using-adb
I'm trying to use adb to find the precise available disk space on an Android device. I'm using this in a powershell command:
$deviceInfo = adb shell df
$storageDriveArray = $deviceInfo -match 'data'
$storageDriveString = $storageDriveArray | out-string
$splitStorageDriveString = $storageDriveString -split "\s+"
$freeSpaceString = $splitStorageDriveString[3]
adb shell df
works, but doesn't give me enough precision (1.7G will be reported). df on Android doesn't seem to take parameters, so I can't use df -k or similar to get a more precise value.
Is there an alternative way to do this?
I'm quite new to powershell so please excuse any hacky stuff!
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
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.