I'm using the Android's log to supervise an application use, so I'm using logcat into the phone not in Eclipse.
Well, if I just write in the log and send me the information everything it's ok, but I receive information from previous executions.
I decided to clear the log every time that my application starts, but now I usually lose the first log messages. Maybe logcat needs some time to get cleared? because when I try to do into debug everything it's ok.
Example:
clear log, message 1, message 2, message 3, ...
Sometimes I don't receive message 1, sometimes don't receive 1 and 2...
I have checked all my code for possible accidental clears but I didn't find anything...
I call this function at the beginning (in onCreate())
public static void clearLog(){
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("logcat");
commandLine.add("-c");//CLEAR
Runtime process = Runtime.getRuntime();
process.exec(commandLine.toArray(new String[0]));
TAG = "";
}
Then I add logs
log.i(TAG, "message1");
..
log.i(TAG, "messageN");
And this is how I collect the log:
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("logcat");
commandLine.add("-d");//dump and exit
commandLine.add("-v");//especify verbose mode
commandLine.add("raw");//raw show only the message, brief for show all
commandLine.add(TAG + ":V");//show TAG's log
commandLine.add("*:S");//hide others
Process process = Runtime.getRuntime().exec(
commandLine.toArray(new String[0]));
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line, log = "";
while ((line = bufferedReader.readLine()) != null) {
log += line + LINE_SEPARATOR;
}
From the docs for exec():
Executes the specified command and its arguments in a separate native process.
So it's running in a separate process. There's not really a good way to tell if it has finished before you start logging.
Instead of clearing the log, you could change the log TAG on each run. Just use the regular tag an append some number that identifies the run, even just a random one. Then when you collect your logs, you can filter by that, and only collect the ones you want.
Related
I'm working on an app that uses Android's MediaMuxer for recording the screen. Using Crashlytics, a significant number of users have the "Failed to stop the muxer" crash, but I can't reproduce it locally on any of my devices. According to another question, the MPEG4Writer logs generated while MediaMuxer is running should indicate what the source of the problem is, but since I'm unable to reproduce it locally, I need to collect those logs remotely and pass them over to Crashlytics.
So here's my problem: MediaMuxer and MPEG4Writer are system classes, so obviously I can't edit them to add Crashlytics.log() lines. I've thought of having the app read the Logcat output and storing all entries containing MPEG4Writer, which are then sent to Crashlytics if the muxer crashes, using this implementation as a base. Here's my code:
public class LogRetriever extends Thread {
private static final String TAG = LogRetriever.class.getCanonicalName();
public static ArrayList<String> logStorage = new ArrayList<>();
private AtomicBoolean mLoggingActive = new AtomicBoolean(true);
#Override
public void run() {
try {
String[] command = new String[] { "logcat" };
Process process = Runtime.getRuntime().exec(command);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while (mLoggingActive.get() && ((line = bufferedReader.readLine()) != null)){
if(line.contains("MPEG4Writer")) {
logStorage.add(line);
}
}
}
catch (IOException ex) {
Log.e(TAG, "start failed", ex);
}
}
public void stopLogging() {
mLoggingActive.set(false);
}
}
Using the above method, I only seem to get the first four log lines generated by MPEG4Writer. The rest are visible through Android Studio's logcat, but aren't collected by my code. I've also tried this library which seems to do the same thing, but again, same problem, only the first 4 lines are collected. I suspect that MediaMuxer is creating its own process after those 4 lines, at which point I can no longer read its logcat output because my LogRetriever class is now in a different process. So how am I supposed to collect those logs? Am I taking the wrong approach here?
So how am I supposed to collect those logs?
Generally, unless you are working for a device manufacturer, you don't collect those logs.
First, accessing LogCat at runtime has never been officially supported; hence, the clunky "fork logcat" approach that you have to take.
Beyond that, you need the READ_LOGS permission to get more than what you are. That permission has signature|privileged|development for the protectionLevel, meaning that ordinary apps cannot hold that permission.
This is for privacy reasons. READ_LOGS gives you access to all of LogCat, and lots of apps (and some system processes) log information that may be sensitive.
I have a Java SE Application that use
input = new Scanner(System.in);
to get Input parameters
and use System.out.println("..");
to print results
Since all Java APIs used in the original Java Project are also available in Android, I have tried to import all classes without any error, but now I don't know how replicate the behaviour of the classic Java console in Android.
I have seen that there are developers that have achieved this in some IDE-like apps, but I don't know how.
Could you help me?
Example:
assume that you want to port this dummy Java SE Application in Android mantaining the console-like approach of the original code
public static void main(String[] args) {
System.out.println("Please enter your choice");
System.out.println("A, B");
Scanner myScanner = new Scanner(System.in);
String choice = myScanner .nextLine();
if (choice.charAt(0) == 'A') {
...do something
}
else{
...do something
}
}
You can execute system commands with exec(). Here is how to do it:
Runtime r = Runtime.getRuntime();
Process p = r.exec("uname -a"); // here goes your input
p.waitFor();
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null) {
System.out.println(line);
}
Update:
Ok, from what I understand, you would like to compile and run code written by user. I can see 3 options:
Most difficult I think. Get the source code of some Java compiler and include it in your project. So, user inputs a text. You compile it, run and give the output.
Using already built compiler. This requires root. Install javac on your device. Then, in your application you can call it with the above exec() code.
Easiest one. Using internet and for example, Ideone.com. In your app you send code to compile on Ideone. You get back the output and present it to the user.
I am trying to write an app which reads the logs created by adb logcat. Following the code on link1 and link2, I have the following code:
try {
Process process = Runtime.getRuntime().exec("logcat");
System.out.println("Process : " + process); // shows process id
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
System.out.println("Buffered reader : " + bufferedReader.readLine());
StringBuilder log = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(log.toString());
} catch (IOException e) {
}
To test what the buffered reader is reading, I put a println, but I get a message "cannot bind tcp:5038". The above code does not read any logs. I also tried using "logcat *:V" but I did not get logs of even lowest priority.
I gave my app the permission: android.permission.READ_LOGS.
I am testing my code on Android emulator.
Can someone please point out what am I doing wrong.
Thanks for helping.
EDIT:
I tried "logcat -d" and I got one line of log. In the code, it can be observed that a try/catch block has been provided; when I remove the permission READ_LOGS from the app, no exception is raised and the bufferReader simply prints null (Usually when an app does not find a permission it requires, it raises an exception). What is the reason for this behavior ?
EDIT2:
I tried Log.d(TAG, log.toString()) and got more than one line of text. Can someone please explain the last question from the previous edit: when I remove the required permission, why is an exception not raised by the app ?
You are likely getting the message "cannot bind tcp:5038" due to not having
<uses-permission android:name="android.permission.INTERNET" />
in your manifest
You can never get the permission to read logs through Runtime.getRuntime().
The android dev team decided to stop granting these permissions to third-party apps. Only system apps can now get them.
More details:https://code.google.com/p/acra/issues/detail?id=100
I want to run excutable such as ping(or any other which gives continuous output) and read its output and print it in my GUI.
I used following method to run my commands:
command=Runtime.getRuntime().exec("ping www.google.com");
and I am reading the output as following:
BufferedReader in = new BufferedReader(new InputStreamReader(command.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println(line+"\n");
}
this works fine , although display output pretty late compared to time taken when i execute ./excutable using adb -d shell.
As I want to this output(line) in gui so I make a TextView and append the output(line) in it as:
txtview=(TextView)findViewById(R.id.textview);
while ((line = in.readLine()) != null) {
txtview.append(line+"\n");
System.out.println(line+"\n");
}
but this crashes my application.
please tell me how to get over this problem.
If your last block of code is being executed in an Activity, then you are probably blocking the UI thread for too long. This will cause Android to force close your application. Try using AsyncTask to get the output and update your GUI.
To the best of my (current) understanding, Android has no console to send the messages to so the System.out.println messages get lost. Instead, Log.x (outputing to LogCat) should be used.
Yet, in the acclaimed Pro Android 2 book, listing 8-1 does just that:
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String page = sb.toString();
System.out.println(page);
Does System.out.println really work in Android or is it only a typo?
If the former (i.e. not a typo), what does it really do and where should I expect to find the output?
System.out.println prints to whatever is currently defined as the "standard" output PrintStream. It is possible to hook this up to point to the log stream, but really there is no good reason to use it. Use Log.x.
This is probably just a typo in the book. Nothing in that code snippet is Android specific.
That System.out.println code does work (despite what the android documentation says). I've tried it on my on my Android development set up (without changing the settings as they describe in the documentation). I've had tried on the set ups of my Android programming students, both on their Windows and Macs. And it always comes out the same way:
The following line does output to logcat by default.
System.out.println("blah blah");
Now of course, it's probably best to stick to Log.x() anyway. It's probably never a good idea to rely on undocumented features, especially in a book. This feature could be here today, and be just as well gone the next time the tools get updated.
From the android docs:
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null.
It also explains how to use System.out and System.err properly.
If you're using Eclipse, System.out will be displayed on the LogCat tab not in the Console.
You can also try the Log.i("MyLog", "The message here...."); also displayed on the LogCat.
Enjoy!