How to prevent executing Linux commands in java in separate process? - android

I am developing application to filter logcat generated by android.I executed linux comand '/system/bin/logcat -b main -f /sdcard/logcat.txt'using getruntme.exec. to execute the command but it is running in separate process though i uninstall my application the process keeps on running .Is there any way i can prevent running in another process.

By getruntme.exec, do you mean you're using something like this? (borrowed from here):
import java.io.*;
public class TestExec {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("cmd /C dir");
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then you could kill it with p.destroy()

No. exec spawns a new process, that is what it is supposed to do - and what you want to do if you start an external command. But it returns a Process object that you can use to manipulate the running process.

Related

Android: Android kill tcpdump process

First sorry for my bad English.
I have developed an app in Android Studio. It call tcpdump (Process process = Runtime.getRuntime().exec("su -c tcpdump -s 0 -v -w /sdcard/capture.pcap");). Initially it works correctly. However, tcpdump process is killed abruptly. Would anyone tell me why?
Thank you
It might tell you why on standard error:
final Process p = Runtime.getRuntime().exec(tcpdumpCommand);
final BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getErrorStream()));
(new Thread() {
public void run() {
while ((line = reader.readLine()) != null) {
Log.d("tcpdump", "stderr: " + line);
}
Log.d("tcpdump", "end of stderr");
}
}).start();
...and then look in logcat. Or try the same with getOutputStream() (for stdout) instead of getErrorStream().
Also if tcpdump was successfully capturing traffic and then abruptly stopped, one possible reason is you've filled the SD card.

getRuntime Android show process

I'm doing a simple app that show the currently process in android, like a shell.
My app execute ls, cd, makedir and other commands, but top or htop command doesnt. (htop doesn't recognize, and top, the app freeze). I need root to this? I've downloaded the terminal app in unrooted android and top command works.
my app has 2 class. a principal and a shell
principal class
public void onClick(View arg0) {
// TODO Auto-generated method stub
ShellExecuter exe = new ShellExecuter();
command = input.getText().toString();
String outp = exe.Executer(command);
out.setText(outp);
Log.d("Output", outp);
}
shell class
public String Executer(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
String response = output.toString();
return response;
}
Why some commands the app works and top for example doesn't??
If you have your Device connected, go to the shell to see what commands you have available using the following command in your computer's command line:
adb shell
At first glance you will be able to tell that "top" is a job that "displays and update sorted information about processes" and it blocks the shell commands line, hence, in your application is locking the thread that executed that command.
Hope it Helps!
Regards!
thanks. adb shell with top command show the process
but
p = Runtime.getRuntime().exec("top");
doesn't maybe works??
I don't understante cause my app freeze
or a top -n 1 not fixed?

Android take screenshot on rooted device

UPDATE There are a number of other posts asking how to get a Screenshot in android but none seemed to have a full answer of how to do so. Originally I posted this as a question due to a particular issue I was running into while attempting to open a stream to the Frame Buffer. Now I've swapped over to dumping the Frame Buffer to a file so I've updated my post to show how I got there. For reference (and acknowledgement), I found the command to send the FrameBuffer to a file from this post (unfortunately he didn't provide how he got to that point). I'm just missing how to turn the raw data I pulled from the Frame Buffer into an actual image file.
My intention was to take a full dump of the actual screen on an Android Device. The only way I could find to do so without using the adb bridge was to directly access the Frame Buffer of the system. Obviously this approach will require root privileges on the device and for the app running it! Fortunately for my purposes I have control over how the Device is set up and having the device rooted with root privileges provided to my application is feasible. My testing is currently being done on an old Droid running 2.2.3.
I found my first hints of how to approach it from https://stackoverflow.com/a/6970338/1446554. After a bit more research I found another article that describes how to properly run shell commands as root. They were using it to execute a reboot, I use it to send the current frame buffer to an actual file. My current testing has only gotten as far as doing this via ADB and in a basic Activity (each being provided root). I will be doing further testing from a Service running in the background, updates to come! Here is my entire test activity that can export the current screen to a file:
public class ScreenshotterActivity extends Activity {
public static final String TAG = "ScreenShotter";
private Button _SSButton;
private PullScreenAsyncTask _Puller;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_SSButton = (Button)findViewById(R.id.main_screenshotButton);
_SSButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (_Puller != null)
return;
//TODO: Verify that external storage is available! Could always use internal instead...
_Puller = new PullScreenAsyncTask();
_Puller.execute((Void[])null);
}
});
}
private void runSuShellCommand(String cmd) {
Runtime runtime = Runtime.getRuntime();
Process proc = null;
OutputStreamWriter osw = null;
StringBuilder sbstdOut = new StringBuilder();
StringBuilder sbstdErr = new StringBuilder();
try { // Run Script
proc = runtime.exec("su");
osw = new OutputStreamWriter(proc.getOutputStream());
osw.write(cmd);
osw.flush();
osw.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
if (proc != null)
proc.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
sbstdOut.append(readBufferedReader(new InputStreamReader(proc.getInputStream())));
sbstdErr.append(readBufferedReader(new InputStreamReader(proc.getErrorStream())));
}
private String readBufferedReader(InputStreamReader input) {
BufferedReader reader = new BufferedReader(input);
StringBuilder found = new StringBuilder();
String currLine = null;
String sep = System.getProperty("line.separator");
try {
// Read it all in, line by line.
while ((currLine = reader.readLine()) != null) {
found.append(currLine);
found.append(sep);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
class PullScreenAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
File ssDir = new File(Environment.getExternalStorageDirectory(), "/screenshots");
if (ssDir.exists() == false) {
Log.i(TAG, "Screenshot directory doesn't already exist, creating...");
if (ssDir.mkdirs() == false) {
//TODO: We're kinda screwed... what can be done?
Log.w(TAG, "Failed to create directory structure necessary to work with screenshots!");
return null;
}
}
File ss = new File(ssDir, "ss.raw");
if (ss.exists() == true) {
ss.delete();
Log.i(TAG, "Deleted old Screenshot file.");
}
String cmd = "/system/bin/cat /dev/graphics/fb0 > "+ ss.getAbsolutePath();
runSuShellCommand(cmd);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
_Puller = null;
}
}
}
This also requires adding the android.permission.WRITE_EXTERNAL_STORAGE permission to the Manifest. As suggested in this post. Otherwise it runs, doesn't complain, doesn't create the directories nor the file.
Originally I couldn't get usable data from the Frame Buffer due to not understanding how to properly run shell commands. Now that I've swapped to using the streams for executing commands I can use '>' to send the Frame Buffer's current data to an actual file...
Programmatically you can run "adb shell /system/bin/screencap -p /sdcard/img.png" as below :
Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
An easy solution for ICS devices is to use the following from the command line
adb shell /system/bin/screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png screenshot.png
This'll save the screenshot.png file in the current directory.
Tested on a Samsung Galaxy SII running 4.0.3.
That would be different for different phones. It depends on the underlying graphics format of your device. You can poll what the graphics format is using system calls. If you are only going to run this on devices that you know the graphics format of you can write a converter that turns it into a known format.
You can have a look at the following project: http://code.google.com/p/android-fb2png/
If you look at the source code for fb2png.c you can see that they poll FBIOGET_VSCREENINFO which contains info about how the device stores the screen image in memory. Once you know that, you should be able to convert it into a format you can use.
I hope this helps.

execute pipes command in android?

I want to display application logs.
On terminal I used this command: adb logcat -s brief *:V|grep "pid"
It's display My Application logs.
pid means application pid which is display in logcat table.
public static String logProc()
{
String value = "";
try
{
String cmd[] = {"logcat","-s","brief","*:V","|","grep",
android.os.Process.myPid()+""};
Process p = Runtime.getRuntime().exec(cmd,null, null);
BufferedReader reader = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while (line != null)
{
value += line + "\n";
line = reader.readLine();
}
p.waitFor();
}
catch (IOException e1)
{
e1.printStackTrace();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return value;
}
Most official Android builds do not come with grep (Edit: more recent releases now do)
You can install busybox if you want extra commands - without root you would have to put it in an alternate location.
You have the additional problem that you are trying to exec() a shell command to connect two programs via pipes, which isn't going to work unless you exec a shell interpreter and give it that command. Or you could set up the pipe yourself and exec both programs.
But since you are writing a program, it would probably be simpler to do your pattern matching in the java code.

Android Not Granting Dump Permission

For the purposes of monitoring Battery usage etc. I have code that executes a few dumpsys calls, reads and parses the output to extract data that I am interested in.
dumpsys battery, dumpsys statusbar, and dumpsys power all give me an error message for output like "Permission Denial: can't dump Battery service from pid..."
Also, when the application is launched there is an item in the log tagged with "PackageManager" statingNot granting permission android.permissionDUMP to package.... (protectionLevel = 3 ...)"
However, dumpsys cpuinfo and dumpsys netstat work and give me the correct output, which seems to be inconsistent.
I am able to generate dumpsys battery and the like from the adb shell, but when I try to call it programmatically it does not work.
I have tried running this on a HTC Nexus One phone as well as the emulator and get the same results for each. The weird thing is that this code worked on my Nexus One a day ago (before I upgraded from 2.2 to 2.3), and now it does not. Is this because of the upgrade?
An example of the code I am trying to run is as follows:
String command = "dumpsys battery";
try {
String s = null;
Process process = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
How do I get the dumpsys to give me the correct output programmatically and how to I get the dump permission to be granted?
*The Nexus One is not rooted and I would like to get this working without having to root it for the purposes of my project
Thank you for your help
Regular applications cannot get the DUMP permission. It is reserved to system applications.
android.permission.Dump is protected by system, signature, and development permission protection levels. Line 1993 of the source shows you this. If your APK is signed with the framework cert, is in the priv-app directory, or debuggable (see below) you can use the pm service to grant the permission, but otherwise the code specifically prevents what you're asking for (line 2624 of source).
Debuggable APKs can be created through setting the debuggable attribute on a buildType via build.gradle. Sample Android DSL:
android {
...
buildTypes {
debug {
debuggable true
...
}
quality_assurance {
debuggable true
}
...
}
If your handset had been rooted, 'dumpsys activity' will work on Android2.3:
private static void dumpIT0(String sCmd) {
try {
String s = null;
String command = "su -c " + sCmd;
Process process = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
process.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
}
}
sCmd = "dumpsys activity";

Categories

Resources