I need to capture all the logs written through my application. I know from Jetllybean OS we can read need only our application log. But when I tried by using command "logcat -d" using exec method by application and I did not get any data.
Please help me on this.
Thanks,
Saravanakumar
This is the example that I was playing around with before that will generate a log text file in local storage:
private static String generateLogcatLogCommond = "logcat -d > /sdcard/IssueReport/log.txt";
public static String generateLogcatLog() throws InterruptedException {
try {
File issueReport = new File(Environment.getExternalStorageDirectory(), "IssueReport");
if (!issueReport.exists())
issueReport.mkdir();
File logFile = new File(issueReport,"log.txt");
logFile.createNewFile();
Process process = Runtime.getRuntime().exec("/system/bin/sh -");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes(generateLogcatLogCommond);
logLocation = "/sdcard/IssueReport/log.txt";
Log.d("Client", logLocation);
} catch (IOException e) {
e.printStackTrace();
}
return logLocation;
}
What the above code is doing is using 'sh' to run 'logcat -d' command and save it as a file locally. This will get ALL the logcat log. For you, you can change that to 'logcat -s ""' and it will save all logcat log of your application to a file.
Related
I have a rooted Android 7 phone and I would like to dump unix input event files. Using adb I could do it using the following command:
adb shell getevent -t /dev/input/event7 > recorded_touch_events.txt
This will dump the event7 file into recorded_touch_events.txt. But this only works when the phone is connected by usb cable with the PC. Using Android I can dump files with the following code:
th = new Thread(new Runnable(){
private Process exec;
#Override
public void run() {
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c","getevent -t /dev/input/event7"});
InputStreamReader is = new InputStreamReader(
exec.getInputStream());
String s;
BufferedReader br = new BufferedReader(is);
while(((s = br.readLine()) != null) && run){
// write line to text file
}
is.close();
exec.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
In this way, I could store every read line in a text file.
Are there other approaches (probably faster ones) for directly dumping the event file?
getevent is used to print input events out in human readable form. For example during interactive debug session. You do not need to use getevent for just dumping or any other computer processing task. Just open and read the input file. The event record format is very simple.
Certainly No, you are doing it right.
I have been working on this small project in college about changing the default DNS of wifi network to a custom DNS like Google, OpenDNS, Metacert, etc.
I know I have to write a shellscript inside the app's code that would edit the hosts file in the filesystem.
The problem is I have no idea where to start from. I have researched on google for some time and I couldn't figure anything.
If anyone knows about it, please guide me. Please tell me the name of the file to be edited, its location, what commands are required and how to run those commands' combination as a shellscript on a click of a button on the UI of app.
EDIT : I'm stuck only at this. Any help will be greatly appreciated.
I'm not sure about which files you would have to edit but this should give you the tools you need to do that.
The first thing you need to do is root the phone if you haven't already. If it's not rooted, you'll run into an issue like: Working Directory : null environment when running Process.Builder on android
There are a lot of guides available for that online. Install SuperSU as well. In order to run shell commands or scripts you should look at the ProcessBuilder class in Android:
http://developer.android.com/reference/java/lang/ProcessBuilder.html
I've given some sample code below to help you along the way. You could execute this in an OnClick() for a button.
/**
* Runs the shell command.
*
* #param command an array of Strings. command[0] contains the name of the
* shell command. command[1]... contains parameters.
*
* #return the text outputted by the command to stderr or stdout
*/
String runCmd(String[] command, boolean readOutput,
boolean waitForExit) {
ProcessBuilder probuilder = new ProcessBuilder()
.command(command)
.redirectErrorStream(true);
String output = "";
Process process;
// Log.d("MyShellCommand", "Executing " + command[0]);
try {
process = probuilder.start();
} catch(IOException e) {
return e.getMessage();
}
if (readOutput) {
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
try {
while ((line = br.readLine()) != null) {
// Log.d("MyShellCommand", "Read a line: " + line);
output += line + "\n";
}
} catch(IOException e) {
output = e.getMessage();
}
}
I'm writing an android app, and i need to read 7 SYSTEM files at start up. What would be the most efficient way to do this?
This is my code right now and it's pretty slow
read(file1);
read(file2);
...
read(file7);
...
public static String read(String file) {
String fileContents = "";
try {
String[] args = {"/system/bin/cat", file };
ProcessBuilder cmd = new ProcessBuilder(args);
Process p = cmd.start();
InputStream stream = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
fileContents = reader.readLine();
reader.close();
stream.close();
}
catch (IOException e) {
e.printStackTrace();
}
return fileContents;
}
There has to be some way to cat each file without closing the stream which should significantly speed things up. I tried making a shell script with the 7 cat cmds and reading the output but everything is all mashed together and i can't split the results.
I tried splitting the cat cmds with echo cmds to form a deliminator in the output:
cat file1
echo !
cat file2
echo !
But the deliminators "!" don't show up in the output and i can't figure out why.
Any suggestions?
I guess you could try multiple threads. Probably 7 would do just fine, but you have to check if 7 is not too much for the slowest device you are targeting. You need to leave some CPU for UI thread.
Is there a way to redirect the logcat's output towards an InputStream or something like that? I'm thinking of something in the lines of how you can redirect the stderr in C.
I want to do it so its redirected when my app starts and everything that happends get dumped to a file.
If you can connect the device for debugging, you can this from the command line
$ adb logcat > textfile.txt
The easiest way I found is to use System.setErr. I allows you to easily redirect the error output to a file.
Example:
System.setErr(new PrintStream(new File("<file_path>"))
The only redirecting possibilites of LogCat output are documentend here and here.
It is not possible to reuse the LogCat output in your app itself. You can however, export it to a file like you ask.
to filter logcat just from your app try this:
int pid = android.os.Process.myPid();
File outputFile = new File(Environment.getExternalStorageDirectory() + "/logcat.txt");
Log.d("zzz","outputFile: " + outputFile);
try {
String command = "logcat | grep " + pid + " > " + outputFile.getAbsolutePath();
Log.d("zzz","command: " + command);
Process p = Runtime.getRuntime().exec("su");
OutputStream os = p.getOutputStream();
os.write((command + "\n").getBytes("ASCII"));
} catch (IOException e) {
}
In Kotlin, this is what I used and it seems to create and log to the logcat.txt file (located in the app directory) whether the app is being debugged or run directly from the tablet. (Sidenote: For some reason the directory doesn't refresh or show up in file explorer until I stop the app and reconnect the device.) (thanks for the help from the previous contributors)
located in utilities...
val publicDirectory = globalContext.getExternalFilesDir(null)
publicDirectoryName = publicDirectory?.toString() + "/"
fun redirectLogcatToFile() {
try {
val filename =
File(Utilities.publicDirectoryName + "logcat.txt")
filename.createNewFile()
val cmd = "logcat -v time -f " + filename.getAbsolutePath() +" -s " + logcatTag
Runtime.getRuntime().exec(cmd)
} catch (ex: Exception ) {
Utilities.toastOnAnyThread("Utilities.redirectLogcatToFile: " + ex.message)
}
}
fun Log( message : String ){
Log.i(logcatTag, message )
}
I've been trying to build a Terminal Emulator for Android. Being pretty new to this, my idea was to execute each command and store the output in a file, whose contents would be displayed after each execution.
Pseudo Code :
public Boolean execCommands(String command) {
try {
rt = Runtime.getRuntime();
process = rt.exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("echo $ \""+command+ "\" >> /sdcard/Android/data/terminalemulatorlog.txt\n\n\n");
/**** Note : String command = (EditText)findViewById(R.id.command).getText().toString(); ****/
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
}
// Error Handling
displayOutput(); //Loads and displays the Text File (/sdcard/Android/data/terminalemulatorlog.txt)
return true;
}
This piece of code works except for a few special commands (Eg. 'clear').
But what I'm more concerned about are the following problems :
Each time a command is to be executed, I end up seeking SuperUser permissions (second line of code). And I'd like to do away with this.
In cases when the user enters one command followed by another,
Such as :
cd /sdcard
touch File.txt
The File.txt is created in '/' and not in '/sdcard'. As of now to avoid this, I'm keeping a track of all the 'cd' commands to figure out what the present working directory is. And I'm hoping that there is a better way around this.
I'd be grateful if someone could help me out here.
Not sure if you are still needing this or not, but here is how I am issuing multiple commands at one time and not using "su" to have them run.
try {
String[] commands = {
"dumpstate > /sdcard/LogFiles/dumpstate.txt",
"dumpsys > /sdcard/LogFiles/dumpsys.txt",
"logcat -d > /sdcard/LogFiles/log.txt",
"cat /sdcard/LogFiles/dumpstate.txt /sdcard/LogFiles/dumpsys.txt /sdcard/LogFiles/log.txt > /sdcard/LogFiles/bugreport.rtf" };
Process p = Runtime.getRuntime().exec("/system/bin/sh -");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : commands) {
os.writeBytes(tmpCmd + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
This a bit late but here a few ways of doing this.
1)
Instead of using su as a starting point use /system/bin/sh.
and after calling
rt.exec("/system/bin/sh");
You should hold onto the Output Stream and Input Stream to give further commands.
After you issued a command you should echo a magic line like "---EOF---" and stop reading input after reading that line. If you don't have this you'll end up with the read function from the InputStream blocking.
2) Pipe the data to a native process you've written that simply moves the data on to your Android Application with a terminating character or string attached to the end.
I am not entirely sure how to do this, but it is essentially the same as the previous method just relies on you native application as a middle man.
This will get you close to a functioning "Terminal Emulator".
3)If you wan't a true Ternimal Emulator then there's no other way to do it than : using a native application that opens a connection to a psuedoterminal.
Here's some basic information of how to open a pty : link
Terminal Emulator is a open source project that uses this technique.
Have a look here
Regarding problem 1:
Each time a command is to be executed, I end up seeking SuperUser permissions (second line of code). And I'd like to do away with this.
Thanks to Xonar's suggestion from another answer:
After you issued a command you should echo a magic line like "---EOF---" and stop reading input after reading that line.
Solution in Kotlin:
private lateinit var suProcess: Process
private lateinit var outputStream: DataOutputStream
private fun getSu(): Boolean {
return try {
suProcess = Runtime.getRuntime().exec("su")
outputStream = DataOutputStream(suProcess.outputStream)
true
} catch (e: Exception) {
e.printStackTrace()
false
}
}
private fun sudo(command: String): List<String>? {
return try {
outputStream.writeBytes("$command\n")
outputStream.flush()
outputStream.writeBytes("echo ---EOF---\n")
outputStream.flush()
val reader = suProcess.inputStream.bufferedReader()
val result = mutableListOf<String>()
while (true) {
val line = reader.readLine()
if (line == "---EOF---") break
result += line
}
result
} catch (e: Exception) {
e.printStackTrace()
null
}
}
private fun exitTerminal() {
try {
outputStream.writeBytes("exit\n")
outputStream.flush()
suProcess.waitFor()
} catch (e: Exception) {
e.printStackTrace()
} finally {
outputStream.close()
}
}
//Activity method
override fun onDestroy() {
super.onDestroy()
exitTerminal()
}