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.
Related
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();
}
I want to measure an app's accurate CPU, GPU, RAM utilization on Android phone. How can I achieve this goal? Is there any methods to read some information from Android system file? Any tutorial or advice will be very appreciated! Thank you very much!
The bottom layer of Android is a distribution of Linux. Hence, you can get information from "/proc/cpuinfo"
Below is an example:
String filePath = "/proc/meminfo";
FileReader localFileReader = new FileReader(filePath);
BufferedReader localBufferedReader = new BufferedReader(localFileReader, 8192);
String ret = localBufferedReader.readLine();
Log.i("Infor:", ret);
Second approach: Call linux commands:
String pid = android.os.Process.myPid();
Process process;
String[] cmd = {
"sh",
"-c",
"top -m 1000 -d 1 -n 1 | grep \""+pid+"\" "};
process = Runtime.getRuntime().exec(cmd);
String line = reader.readLine();
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 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.
I have rooted my device, then in my application
Process p = Runtime.getRuntime().exec("su");
and it work fine, my application will be root mode. Then I try add wlan address space, but it doesn't work, when I check out in terminal, following error message is shown
busybox ifconfig there is not a new wlan address space.
I try with following way:
Process p = Runtime.getRuntime().exec("su");
p = Runtime.getRuntime().exec("busybox ifconfig wlan0 add xxxxxxxxxxxx");
p.waitfor();
When I run my application, the toast shows that the app is root mode but there is not added wlan0.
The "su -c COMMAND" syntax is not really supported. For better portability, use something like this:
p = Runtime.getRuntime().exec("su");
stream = p.getOutputStream();
stream.write("busybox ifconfig wlan0 add xxxxxxxxxxxx");
The write() command doesn't exists as-is, but I'm sure you'll find how to write your stream to it, maybe encapsulating the output stream in a BufferedOutputWriter or so.
because the process that started with "busybox" is not the same one
which started with "su". you should like this:
Process process = Runtime.getRuntime().exec("su");
OutputStream os = process.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeBytes("busybox ifconfig wlan0 add xxxxxxxxxxxx" + "\n");
dos.flush();
That might be because when you run su, it launches one process. Then you run busybox ..., and it happens in another process, which is not started as a superuser.
Try something like
Process p = Runtime.getRuntime().exec(new String[] {"su", "-c", "busybox ifconfig wlan0 add xxxxxxxxxxxx"});
, i.e. executing it in a single command-line.