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();
}
Related
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.
I want to generate a file while app is running thus my computer can monitor my app status in time(the cell phone is connected via usb all the time).
Is there anyway to let both adb and app point the same directory?
Also, If there has another way to make android can communicate with computer, please tell me.
Methods I tried:
At first, I though
echo $EXTERNAL_STORAGE
and
Environment.getExternalStorageDirectory()
would return the same value.
The value adb shell returned:
/storage/emulated/legacy
However, the result of calling Environment.getExternalStorageDirectory() In program is:
/storage/emulated/0
Then, I make android run shell command
Process su = Runtime.getRuntime().exec("echo $EXTERNAL_STORAGE");
//also tried "echo \\$EXTERNAL_STORAGE"
su.waitFor();
in = su.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine())!= null){
result = result + line + "\n";
}
reader.close();
in.close();
su.destroy();
return result;
but it return empty string.
echo is not a separate executable but rather a shell's built-in command.
Use Runtime.getRuntime().exec("sh -c 'echo $EXTERNAL_STORAGE'"); instead
Finally, I got the value by following command.
Runtime.getRuntime().exec(new String[] { "sh", "-c", "echo $EXTERNAL_STORAGE" });
Thanks Alex P. inspiring me.
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'
I'm writing a file explorer which will be capable of modifying system files with root access, but I came across some problems.
What I'm doing now is to grant my app root access, but executing "su" doesn't work.
If I set permissions to the folder in adb shell, the app works fine but I think root browsing doesn't rely on chmods.
Can anyone tell me is there a proper way to make my app work as if it were with root privileges?
Running an android application process (its dalvik VM and native libraries) as root is extremely difficult to achieve, and inadvisable for a number of reasons including not just security but memory waste resulting from having to load private copies of system libraries instead of using the shared read-only copies available when you inherit an unprivileged process from zygote as in a normal application launch.
What the unofficial "su" hack on some rooted phones does is lets you launch a helper process which runs as root while your application process remains unprivileged. It does not change the userid of the application calling it - indeed, there really isn't by design any mechanism for doing that on unix-like operating systems.
Once you have a privileged helper process, you would then need to communicate with it via some means of interprocess communication such as its stdin/stdout or unix domain sockets to have it do file operations on your behalf. The shell present on the phone could probably even be used as the helper application - most of what a file manager needs to do can be implemented with the 'cat' command. Officially, none of this is a stable API, but then an application-accesable "su" hack isn't in official android anyway, so the whole project is deep in "unsupported" territory to begin with.
Root access creates a new Process, so, your app does not have root privileges.
The unique thing you can do with root privileges is execute commands, so, you have to know the commands of android, many of commands is based on Linux, like cp, ls and more.
Use this code for execute commands and get output:
/**
* Execute command and get entire output
* #return Command output
*/
private String executeCommand(String cmd) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec("su");
InputStream in = process.getInputStream();
OutputStream out = process.getOutputStream();
out.write(cmd.getBytes());
out.flush();
out.close();
byte[] buffer = new byte[1024];
int length = buffer.read(buffer);
String result = new String(buffer, 0, length);
process.waitFor();
return result;
}
/**
* Execute command and an array separates each line
* #return Command output separated by lines in a String array
*/
private String[] executeCmdByLines(String cmd) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec("su");
InputStream in = process.getInputStream();
OutputStream out = process.getOutputStream();
out.write(cmd.getBytes());
out.flush();
out.close();
byte[] buffer = new byte[1024];
int length = buffer.read(buffer);
String output = new String(buffer, 0, length);
String[] result = output.split("\n");
process.waitFor();
return result;
}
Usages for a file explorer:
Get list of files:
for (String value : executeCmdByLines("ls /data/data")) {
//Do your stuff here
}
Read text file:
String content = executeCommand("cat /data/someFile.txt");
//Do your stuff here with "content" string
Copy file (cp command not working on some devices):
executeCommand("cp /source/of/file /destination/file");
Delete file (rm command not working on some devices):
executeCommand("rm /path/to/file");
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.