Is it possible to call getevent from an Android service? - android

Is is possible to run getevent from an Android service and get output similar to what you see when running adb to call getevent from a command prompt on a development machine? When I try something like:
ProcessBuilder builder = new ProcessBuilder()
.command("getevent")
.redirectErrorStream(true)
.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(builder.getInputStream()));
...
the output I get for each device looks like:
could not open /dev/input/event[n], Permission denied
Is it just not possible to access low level information like this because of Android's security protections? Would it be possible on a "rooted" device?
Why I am trying to do this:
I would like to record a user's actions (touch and gesture events) on an Android device for the purpose of usability testing. An accessibility service seems to be the way to go, but the information is not detailed enough. For a swipe gesture, for example, I cannot get the screen coordinates of where the user swiped. I was thinking that getting the low-level input from the touch screen might let me get more detailed information. Maybe there is a better way to do this?
(I'm a newbie in the Android world. This kind of thing is easy on Windows.)

You can do like this.
th = new Thread(new Runnable(){
private Process exec;
#Override
public void run() {
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c","getevent -t " + device});
InputStreamReader is = new InputStreamReader(
exec.getInputStream());
String s;
BufferedReader br = new BufferedReader(is);
while(((s = br.readLine()) != null) && run){
...
}
is.close();
exec.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
You must use 'su' to get the root permission, but by this way you can't get the real time event, because there is a buffer size of 4k, you could get data only after contained 4k data.

Search for UIAutomator. This does what you want to do.

Your phone must be rooted to execute getevent/sendevent command.
One way is to install any terminal emulator from play store like Qute: Command Console & Terminal Emulator.
In terminal enter following:
1) su (it'll gain the root access required for getevent)
2) getevent (or getevent -c 8 to output only 8 lines else it would flood the terminal)

Related

Android running su within app

When I use adb to access my device (Android 4.4.2 straight from the manufactures with their custom rom - its not a regular device - it has built in 2D barcode scanner) it goes straight to having a # which I've read means I have root access. And if I run "id" I get the following:
uid=0(root) gid=0(root) context=u:r:adbd:s0
However, when I run "su" from within my app and then "id" I get the following:
uid=10079(u0_a79) gid=10079(u0_a79) groups=50079(all_a79) context=u:r:untrusted_app:s0n
So it's clearly not running as root.
Is my understanding all wrong, in believing that it should be running as root from within the app, or is there something else I need to do in order to get this working?
Any advice would be much appreciated.
Here is the code I'm currently using to run the su and id commands:
p = Runtime.getRuntime().exec("su");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "n");
}
p = Runtime.getRuntime().exec("id");
p.waitFor();
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "n");
}
One other thing I forgot to mention - I copy the app to /system/priv-app and run it from there. Still no luck.
I had a Chinese tablet with problem like that. Just re-root it (replace su binary). Should work.
P.S. Seeing any code would also help.
There is an android manifest permission you can use to gain root access
<uses-permission android:name="android.permission.FACTORY_TEST" />
Your app will run as a manufacturer test application, running as the root user. Thus making the 'su' command accessible to your app.
However, I doubt that Google Play will allow you to upload in store with such permission.

Android - getevent command logging in thread

#Override
public void run() {
try {
exec = Runtime.getRuntime().exec("getevent | grep event1");
InputStreamReader is = new InputStreamReader(
exec.getInputStream());
String s;
BufferedReader br = new BufferedReader(is);
Log.i("br.readLine", " = " + br.readLine());
while ((s = br.readLine()) != null) {
Log.i("s2", " " + s);
}
// is.close();
// exec.destroy();
} catch (IOException e) {
Log.e("thread ioexception", " " + e.getCause());
e.printStackTrace();
}
}
I tried logging the results of the command to getevent in thread.
But put the results of the command in the buffer, the buffer is empty(null).
Perhaps as soon as this command is executed, it seems that ends without receiving any input.
While maintaining thread I want to continue to be run getevent command.
How this can be done? any idea?
Edit
getErrorStream()
getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)
-d: show HID descriptor, if available
-p: show possible events (errs, dev, name, pos. events)
-i: show all device info and possible events
-l: label event types and names in plain text
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
GetErrorStream comes out as the result of a manual getevent.
If the instruction is to operate normally, it would not have been any log (the other normal commands actually did. Ex) ls )
I think getevent command seems to have caused various problems since the CALLBACK method.
Edit: I think now I got your problem. The pipe behavior is not cross-platform, as it is a functionality of the executed shell. Thats why it is not working as you expect in java. Try to use a script like the following to spawn a new shell which implements the pipe function as you expect.
String[] cmd = {
"/system/bin/sh",
"-c",
"getevent | grep event1"
};
I'll keep the rest of the answer, as it could help somebody.
I think you are executing getevent | grep event1 without the correct permissions. At least you need to be root user or in input group.
Edit: I still think you do not have the correct permissions. Of course, for running getevent no special permissions are necessary, as it can be executed by everyone. But keep in mind, that getevent reads /dev/input/*, which has the following permissions:
crw-rw---- root input 13, 64 2016-01-24 21:34 event1
Try to make sure your application is really allowed to read event1.
You should also try to use getErrorStream() instead of getInputStream() to see what is going wrong.
Regarding the second part of your question, I am not sure I understand it correctly. You want to execute the command periodically in the same thread right? (I did not, see edit below.)
Then you can simply run your code in a while(1) loop and sleep as long as you want. A bit more advanced would be to use a Timer and a TimerTask.
If you want to control every loop from outside your Thread you can simply use Object.wait() and Object.notify(). Another, also more advanced, possibility is to use Thread pools. The interesting one for you could be the SingleThreadExecutor.
Edit: As I thought, I did not understood you correctly. However, I'll keep the second part of my answer, maybe it helps someone else.
For your use case your code should work correctly. I think it does return immediately because an error is happening. As described above, try to use getErrorStream() to see what is actually happening.

Android - Can i get total running time?

Please excuse my english.
In the Device Settings the system status just shows the recent uptime.
I want the total uptime from factory.
In Android, there is no direct way to get total Uptime from factory.
There is a kinda-workaround, where via PackageManager you can get the install time of and app using getPackageInfo() and long firstInstallTime. So, you can try to get the oldest app installed and take it from there.
Besides that - like I have said, there is no direct way.
Based on answer from here
adb shell commend in java.lang.Runtime.getRuntime().
String cmd = "shellscript.sh";
String cmdreturn = "";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line=buf.readLine())!=null) {
System.out.println(cmdreturn);
}
Refer adb and Debugging

Android - how to stop continuous terminal action (ping) programmaticaly?

I am working on a simple app but don't know how to stop continuous action in terminal such as PING programmatically.
I just want to know the command, then I'll add it to runtime.getruntime.exec...
I know there's a CTRL+C shortcut in pc but how do I execute this on Android?
Sorry for not adding examples, I'm writing from my phone.
Another way:
Process proc = Runtime.getRuntime().exec("ping 127.0.0.1");
proc.destroy();
As you execute your command, you get the relating process. You can use it to stop your ping, too.
You can't directly send CTRL + C, but take a look at Process.sendSignal() (Android Developers)
First, get the process ID of the ping-process.
Then you can easily send a Process.sendSignal(yourPid, Process.SIGNAL_QUIT);
After debugging for a long time I found out how to solve the problem
"Kill results without the ping statistics being returned".
Get pid of ping process.
Ex:
Progress proc = runtime.exec("ping 192.168.1.1");
where proc will be something like Process[pid=2343], so you need to extract 2343.
Then when you are reading the ping output, you can use
"Runtime.getRuntime().exec("kill -INT " + 2243);" to kill the process.
InputStreamReader reader = new InputStreamReader(proc.getInputStream());
BufferedReader buffer = new BufferedReader(reader);
String line;
while ((line = buffer.readLine()) != null) {
echo.append(line).append("\n");
if (UserStopPing) {
Runtime.getRuntime().exec("kill -INT " + temp);
}
proc.waitFor();
This program will stop ping and you will get the statistic also [variable echo].
You can try this.
There is a CTRL option on your screen. Press that and then enter c.
This might help you.
Just in case people are still looking for a solution to this -- On an Android the equivalent of CTRL+C is "Volume down button" + C on your keyboard. This should stop the ping.

Wrong output with logcat inside my application

I'm developing a multi-tab application. In one of the tab I want to show the logcat but I have a lot of problem running it correctly.
Right now I'm using the following command but I don't get anything in my TextView. :
Process process = Runtime.getRuntime().exec("/system/bin/logcat -s com.vittorio:I");
But when I run the same command into Terminal it works flawlessy.
I've also tryed this other command :
Process process = Runtime.getRuntime().exec("/system/bin/logcat *:I");
but for some reason it prints also Debug level messages ...
EDIT (1):
I've by-passed the problem by adding an high-level filter (java) to the whole log.. so I only print in my textview what I need. It's a very dirty solution but for now is the only one I managed to come with.
I would like to point out that I'me experiencing different behaviours on my phones :
Galaxy S Plus (rooted) : I can see the log.
Galaxy Y (rooted) : No log
Nexus One (not-rooted) : No log
EDIT (2) - SOLVED (NEED ROOTED PHONE):
After some struggling I managed to solve my problem. Actually navigating through the init.rc system file I saw that the permissions for /dev/log/main and /dev/log/system where setted to 620.. that's why I couldn't open the log on some of my phones. So I rooted also my Nexus One and added this commands into my activity before calling the logcat command :
Process process_su = Runtime.getRuntime().exec("su");
Process process_ch = Runtime.getRuntime().exec("chmod 777 /dev/log/main");
Done! :D
Hope this info will help anyone who will face my same issue.
You have to use this permission :
<uses-permission android:name="android.permission.READ_LOGS" />
and then you can use that snippet i found
try {
Process process = Runtime.getRuntime().exec("logcat -v");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder logString=new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
logString.append(line);
}
TextView tv = (TextView)findViewById(R.id.logTextView);
tv.setText(logString.toString());
} catch (IOException e) {
}
I didn't try it but it seems correct

Categories

Resources