I am trying to diagnose an issue in an app I have written. The issue is a sporadic one, and occurs only under real-world conditions: in the field, away from my PC, and when I’m in the middle of something else, with no resources to spare for immediate debugging. Therefore, my best bet is collecting and analyzing log data.
Unfortunately, by the time I realize the issue has struck again and get around to debugging it, any log data has already rotated out of the Android log as I frequently have other chatty apps running at the same time. Increasing the size of the log buffer has not helped (either Android does not honor it or other apps are still too chatty) so I have abandoned this route.
For this reason, I am now considering having my app log to a separate text file in addition to the regular log.
Now I could easily double every call like
Log.i(TAG, "something happened");
adding another call that writes the same thing to the log file—but that does not seem very elegant to me.
Another option would be to replace all calls to Log with a wrapper that writes the event both to the Android log and the log file.
Question: Does the Android API provide a built-in mechanism for this, i.e. telling Log to write its data to the default log and a text file at the same time? Or do I need to code this by myself?
Edit:
Assumptions:
I know where in my code I need to generate log output (which can happen anywhere, which may or may not involve an exception) and what I want to be written to the log.
Getting log data from the device to my PC is also not a concern (one-man show, I just plug my phone into my PC and transfer the log file).
If you know the current Android API has no built-in mechanism to achieve what I want, then ”no, Android does not support this” is a perfectly acceptable answer. In that case the solution is clear—I would fall back to the wrapper function. I am specifically not looking for a different approach to the problem.
After doing some more research, it seems the Android API does not provide a standard way to do this. There are two possible workarounds:
Mirror output at the source
System.out and System.err output, which is written to the console in desktop systems, writes to the log on Android. These two can be redirected into any PrintStream of your choice, which would give you all Java console output. You can subclass PrintStream to duplicate its input, feeding it into the default stream as well as into a file of your choice.
Create a class which exposes the same methods as android.util.Log. In each method, call through to the respective android.util.Log method and additionally log the data to a file. If you call your class Log (but with a different package name, e.g. org.example.Log), then all you need to do is replace imports of android.util.Log with an import of your class, and any Log method calls will go to your class.
Caveats: This will only give you data explicitly logged by your code (i.e. for which you have the source files), as well as anything that goes to System.out or System.err. It will not include log output from JAR libraries (if you cannot modify their source code), nor any output generated by the system (such as stack traces from default exception handlers) or by other processes (some of which may be system processes and report conditions related to your process).
Read the logs from the command line
This article explains how to read the logs from within Android. In a nutshell:
Android includes a command line utility called logcat on the device, which will give you a continuous feed of log messages until stopped. (Try it by adb shelling into your device and running it. It has a bunch of command-line options to control its behavior. Not sure if it is present on all distributions, though.)
Launch this command via Runtime.getRuntime().exec("logcat"), then obtain the input stream of the process returned. This will give you an input stream of log messages.
According to the article, your app needs the android.permission.READ_LOGS permission to read logs.
I have read statements that certain versions of Android (4.2 was mentioned) do not allow this permission to be granted to non-system apps, though. According to my own tests, behavior without this permissions differ: Anbox will return the full logcat, while LineageOS (tested on 15.1) will only show log entries from the app which called it (including previous instances, presumably everything associated with the same Linux user). This can be a limitation or a welcome filter feature. YMMV.
logcat conveniently has a command line option, -f, to specify an output file. I tried
Runtime.getRuntime().exec("logcat -f " + absolutePathToLogFile);
and logcat keeps logging as long as the app’s process runs. Killing the app (by clicking the X in the title bar on Anbox) apparently also terminated the child process.
Now you can either run this code when your app starts up, or you can turn this functionality into a separate app which starts on boot and continuously collects logs for all apps.
Caveats: This may fill up your storage space quickly if you have some chatty apps running (which is why entries rotate out of the logcat so quickly in the first place). It is recommended to make log mirroring configurable (e.g. via Preferences) and/or ensure old files are deleted regularly. Also, if you keep the logcat process running until your app terminates, you will not be able to access the file over MTP as there is no easy way to run the media scanner (if you scan the file while it is still written to, it will appear truncated over MTP until another media scan runs).
You have not specified if some exception are thrown but you don't handle.
In case, take a look at this answer:
Android Handling Unhandled Exception
If you must look at a bunch of variables and objects, I'd suggest two choices:
Write a copy of your logs on a file. When your problem occurs, just ask the user to send the file to you. This is ideal during tests with self-aware users.
Obtain statistics about usage, like commercial software do. Just log user operations and send the data to your server (you would need one for this). This is the most transparent way to do remote logging.
In the case of writing log to a file, you can read and write what you want in internal memory (inside the app's sandbox) or external memory (in this case, write permission is required and explicit permission must have been granted at runtime if you are targeting Android 6 and above).
Related
When testing on a device in Android Studio you get an awful lot of output in the logcat.
I'm only interested in the output for the app I'm developing. I can see just this, after running, by opening the Devices section and manually selecting my apps process. Problem is, it's pretty tedious to do this every time I run my app, which seems to be the case.
Is there a way to get it to remember this setup?
How about a way to get it to stop reporting anything after I'm done with my app or it's crashed ? (otherwise my app specific stuff gets buried so quickly by output from other proccesses on my phone)
I'm open to other ways of filtering the logcat too, however I couldn't think of a way to set up filters so that I would get my tagged Log messages AND other exceptions I wasn't expecting.
Any suggestions?
Normally this is done by default, but if not,
in logcat, the green plus sign, when you click it you get a dialog, fill the byApplicationName with your package name, and also your filter name with something, now you can filter your output according to your app
with that beeing said, sometimes you don't get the filter column info (application name) in logcat at all (blank), here (and I my self don't know the cause of it) just forget it for a while and retry again
I am a little confused to differenate System.err/out, e.printStackTrace and log while logging RuntimeException.
At first, I thought that log information is not saved in a file if I use System.err/out, e.printStackTrace and just printed on console.
But System.err/out, e.printStackTrace also seem to be logged in a log buffer and we can see it through logcat.
Threfore, if we can save log in a file and also System.err/out, e.printStackTrace results can saved in a file.
Q1. What I understand is right?
Q2. If it is, which logging type is better to debug field issues after production?
Q3. If any RuntimeExceptions occur, where can I find the log file in android folder?
UPDATE
I got an answer for Q3.
In case of android, RuntimeException log seems to be saved in /data/system/dropbox.
With Android, it's more efficient to log exceptions and write messages using the methods in Log. In emulators and on most devices, writing directly to System.out or System.err get redirected to Log.i. On some devices, writes to System.out/err are lost. From the Android docs:
By default, the Android system sends stdout and stderr (System.out and System.err) output to /dev/null.
Using e.printStackTrace also just writes to System.err, and I believe that it is less informative than the Log methods, since you can add a log tag to the latter.
As far as I know, all the logging information, including output from app crashes, is kept in the logs. (If you catch RuntimeExceptions, there is no output unless your code generates it.) You can find the logs, I believe, in /system/bin/logcat; however, it's not in plain text format. You can pull the information off the device in a readable form by attaching it to a development environment and entering the command:
adb logcat -d -v time > logfile.txt
There's also a logcat view in Eclipse. There are also some free utilities (aLogCat and CatLog come to mind) for looking at the logcat data on a device.
What I understand is right?
Your understanding seems fine. Most things written to standard output or error are displayed in Logcat. As Ted Hopp noted, though, it's preferable to use the Log class for logging. This information is not saved to an easily-accessed file by default, but you could perform that step yourself.
If it is, which logging type is better to debug field issues after production?
It's difficult to collect debugging information if you're storing it on the device in a file. If you're deploying your app to the Google Play Store, you can use the Developer Console to view stack traces from your app (provided that your users have opted to send crash reports). A more reliable solution would be to use a service that tracks crashes in the wild and aggregates a lot of useful statistics for you (e.g., Crittercism).
If any RuntimeExceptions occur, where can I find the log file in android folder?
They're not stored in a log file, as far as I know. You could catch each exception and write something to a custom log file (whose location you can choose), but that tends to be unwieldy; the services that I mentioned above will be much more efficient for doing this.
I am developing an android app. My app gets crashed often. I want to save the logcat messages in sd card while the apps gets crashed to find the root cause. Is ther any way to do this?
A few ideas which might help you step toward fully automated crash log gathering. We have yet to roll a full system here, we've had enough luck with just grabbing devices after they've crashed or asking for more info from our QA group, but:
ACRA is relatively easy to implement, and even if you don't implement it, the source is on github for you to poke around in.
The related question Android crash reporting library (pre Froyo) has a number of links and solutions, including android-remote-stacktrace, the aforementioned ACRA, Android-Error-Reporter, and other commercial solutions.
Some devices capture the crash output automatically, you can grab it via adb pull /data/log/dumpstate_app_native.txt.gz or similar -- the paths should appear in logcat. These tend to be overwritten with each crash, though. (If anyone can answer whether this is a manufacturer-specific feature or something that appeared in some version of android's core, I'd love to know!)
You can get a logcat app, e.g. aLogCat or many others, that you can install on your device.
TestFlight is going into beta on Android side; they have crash reporting on the iOS side and should on the Android side too, and there are various other lovely benefits to using their services -- and integration is really easy in our experience.
If you're rolling your own inside your app, you need the READ_LOGS and WRITE_EXTERNAL_STORAGE manifest permissions (even for local builds), then you can use the logging API or a regular File.copy or even a system call off to logcat itself. There are a bunch of options and examples in the "Related" links to the side of this question:
Stream android logcat output to an sd card
How to redirect my log output from logcat to the SD-Card on an android device?
...and so on.
Hopefully this helped.
Reading your own logcat messages is covered by other questions.
how can i access logcat file on device
Read logcat programmatically within application
In order to do this when your app crashes you need to install an defaultUncaughtExceptionHandler.
Either on your activity on create or your application on create. Add the following code.
final Thread.UncaughtExceptionHandler oldUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
// DO your error handling here.
// Write your log cat, or write your exception stack trace here.
// Get rid of this line if you don't want a popup letting you know that your app has crashed.
oldUncaughtExceptionHandler.uncaughtException(thread,throwable);
}
});
I am using HTC One X.
There are some system application that has too many logs.
Because of that, I am able to see my application log only for some seconds. After some time, my logs are being remove from buffer since too many new logs from other application.
Can i disable log by using the tag.
Firstly, you cannot stop other applications from logging! Probably some apps more than others log too extensively causing an overflow. What you could try to do is
Force stop some apps so that thier logging activity is reduced(less chance it might reduce).
Secondly, as Rasel suggets,
Use DDMS features like filtering logs using application name, package name, TAG's etc. and pause logging.
In this way you will get a snapshot of your logs. Hope this helps!
On Android I am using the android.util.Log to log within my application and during development I am using the adb logcat or Eclipse to see the logs - I use it even more then debugging...
On device I can save the logfile from my code or use some application form Android Market to save the logs - e.g. aLogCat.
Now can I do the same on the iPhone? I can use the NSLog(#"message");, but can I easily save the log file from my application and access it? Are there any ways for that?
Regards,
STeN
This is from NSFoundation reference
NSLog:
Simply calls NSLogv, passing it a variable number of arguments.
NSLogv:
Logs an error message to the Apple System Log facility (see man 3 asl). If the STDERR_FILENO file descriptor has been redirected away from the default or is going to a tty, it will also be written there. If you want to direct output elsewhere, you need to use a custom logging facility.
Thus, it is only a matter of redirecting the file-descriptor "stderr" (2) to a custom file, and you will get everything that you print using NSLog in that file.
This seems to be exactly what you want.
Note that if you want to get logs on console when you are connected to the debugger, you can wrap your code around this to avoid redirection in this case:
if (!isatty(STDERR_FILENO)) { // Not connected to any terminal
// your redirection code
}
You can access the console log from Organizer->Device->Your device->console.
If that is not powerful enough, consider using utilities like NSLogger.
The previous answers are good; also see this if you're inclined to making system calls.