My application freezes after a superuser request - android

I am writing an application which involves getting information on all running processes (name/package name to begin with). I am doing this by invoking "ps" in my code. I requested superuser access from within the application before invoking the "ps" command. However, when I attempt to read the input stream, the application freezes and I do not get any output in the Logcat. Below is the code that I am using:
Process process = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(process.getOutputStream());
outputStream.writeBytes("ps -t -x -P -p -c");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String topInfo = bufferedReader.readLine(); //Where it freezes
while(topInfo != null)
{
Log.i(appInfo, topInfo);
topInfo = bufferedReader.readLine();
}
outputStream.flush();
outputStream.close();
The code works as expected without superuser request, however the result only consists of my application and the "ps" process.
Is there something that I have missed, or something I need to research before I attempt to fix this?I have tried to search this issue on the Internet before asking here, without success. Any help is appreciated.
Thanks in advance.
P.S The application is being run on a rooted device running Android 7.1.1

I have found the cause of the problem. As it turns out, the BufferedReader was not ready to read, therefore it was not getting any input from the input stream. I confirmed this with the following code:
while(bufferedReader.ready())
{
String topInfo;
while ((topInfo = bufferedReader.readLine()) != null)
{
Log.i(appInfo, topInfo);
}
}
The fix to this problem is to wait for the BufferedReader to be ready to to read the process input stream. This can either be done by pausing the thread for some time, or including a loop that will loop through till the BufferedReader is ready to read. I opted for the latter, as shown below:
do
{
//Wait
} while(!bufferedReader.ready());
This gave me the desired results, which was a list of processes running on my device.

Related

How to get current Thermal values in Android Programatically?

I am trying to get thermal values of my device programatically. I am able to do it in adb but unable to do this programatically. How can I loop over each and every directory in the directory "thermal" to get the particular value. Some part of my code is as following :
Process p=Runtime.getRuntime().exec("cd sys/class/thermal/");
You cannot access /sys/class/thermal/ through an app because the user performing the action (something like u0_aXYZ) does not have enough permission to perform this action compared to a (root) adb shell.
You can do for instance:
adb shell
run-as your-app-package-name
and from now on you can navigate across the device file system and take a look at the folders your app can access.
If you want to proceed with that your only option is to have a rooted device and build an app with root permissions.
Now I found to do this programatically. I used for loop to find the values. Visit the detailed answer here.
for(int i=0;i<29;i++){
float temp;
Process process = Runtime.getRuntime().exec("cat sys/class/thermal/thermal_zone" + i + "/temp");
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine();
if (line != null) {
temp = Float.parseFloat(line);
}
reader.close();
process.destroy();
}

Executing command line, cd doesn't work

I'm trying to execute cd using
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader stream = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = stream.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append('\n');
}
stream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((line = stream.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append('\n');
}
} catch (IOException e) {
e.printStackTrace();
}
ls works. But cd dir doesn't work. It doesn't change the directory. If I execute pwd, it still shows /. I read that each time Runtime.getRuntime().exec(command); is executed, it creates a new shell. I think I need to capture that shell some how and maintain it till the user closes the app.
Not just that, I'm not getting any errors in my output. Eg. when I put a command that does not exist, I don't get the error message.
I read that each time Runtime.getRuntime().exec(command); is executed,
it creates a new shell.
That is correct. When you call Runtime.exec() for each command, you are creating a new process. Each process gets its own environment, including a separate working directory which does not affect the parent process (your app), or any other processes you create afterwards.
I'm not getting any errors in my output
You don't get any errors because the shell commands do not fail to execute. The commands simply return a status code indicating success or failure when the process terminates - the code can be obtained via Process.exitValue() - but make sure the process has finished first using Process.waitFor().
If you want to execute multiple commands, you could use exec() to launch a shell executable and then write commands and read replies via the input and output streams, or just join all the commands together using semicolons and execute them directly using a command line like:
sh -c 'cd /;pwd'

implement at command on rooted android and get the result

I'm a beginner in stackoverflow so I cant add a comment.
I saw this page:
Read command output inside su process
and I tried this answer and it is ok:
Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
//from here all commands are executed with su permissions
stdin.writeBytes("ls /data\n"); // \n executes the command
InputStream stdout = p.getInputStream();
byte[] buffer = new byte[BUFF_LEN];
int read;
String out = new String();
//read method will wait forever if there is nothing in the stream
//so we need to read it in another way than while((read=stdout.read(buffer))>0)
while(true){
read = stdout.read(buffer);
out += new String(buffer, 0, read);
if(read<BUFF_LEN){
//we have read everything
break;
}
}
//do something with the output
but when I tried at command in the shell the response was the same command.
I put this command:
stdin.writeBytes("echo AT+CQI?\n");
the answer was:
AT+CQI?
I wrote:
stdin.writeBytes("echo ATinkd\n");
the answer was:
ATinkd
That is mean "bla..bla..bla..". that is mean the android system does not recognize this commands as at commands.
I wonder if any body have an advice or solution.
First I think you are just sending the AT command to stdout in the shell which will not do anything other than giving you an echo which you read back. For this approach to work you have to redirect the echo command to the serial port device file. Android phones use various devices for this, /dev/ttyGS0 and /dev/smd0 seems to be common names.
However I would suggest using the program atinput to send AT commands and capture modem responses. It is specifically written to be used from the command line like that. That will relieve you from communicating directly with the modem and the only thing left is the pipe handling reading the response.

How to print the logcat log to cmd prompt

I'm running scenarios in UIAutomator.My output is displayed in CMD prompt. Whenever there is a failure i'm printing strings (displayed in Cmd prompt). When the scenarios fails, Is it possible to print the log snippet from logcat logs to cmd prompt?
Late Answer, but better late than never ;-)
You can construct a BufferedReader that reads from logcat like this:
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec("logcat -d").getInputStream()));
and then continue using BufferedReader for getting the text content as usual and print for example to Cmd prompt as you wanted.
Not sure if that is the best practice doing it this way, but it works.

Android app using android.permission.READ_LOGS - is that impolite?

I have an app that is available from the Android Market.
Some users have asked for a way of debugging when things don't work out as expected.
I have been looking into adding a menu item that will display the output of
Process mLogcatProc = null;
BufferedReader reader = null;
mLogcatProc = Runtime.getRuntime().exec(
new String[] {"logcat", "-d", "AndroidRuntime:E BDtN:V *:S" });
reader = new BufferedReader(new InputStreamReader (mLogcatProc.getInputStream()));
String line;
ArrayList listOfLogLines = new ArrayList();
while ((line = reader.readLine()) != null)
{
listOfLogLines.add(line);
}
Basically I am extracting the parts of the Log.* lines that my app has been writing and the errors that the AndroidRuntime has been throwing.
I have a working prototype that will display to the user the contents of the part of the log that I have extracted in a ListView.
I will have to add android.permission.READ_LOGS to the AndroidManifest.xml file in order for my app to have read access to the log, and this of course will be information that the user will be prompted with before installing.
And the question is if this is considered impolite, dangerous or otherwise out of the ordinary. Will it keep users from installing?
I wouldn't install an app that did this. If all you want is your own logs, your app can keep its own private log buffer that it writes into along with the system log.
You may not even need to do this though: http://android-developers.blogspot.com/2010/05/google-feedback-for-android.html
Don't make your live difficult and risk problems with your user! java.util.logging is available on android as well (and even forwarded to android.util.Log) and a java.util.logging.Handler will do everything you want.

Categories

Resources