Rather odd behaviour of Log - android

I wrote a very simple Android Activity:
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TAG", "onCreate() Log call 1");
Log.d("SMS", "onCreate() Log call 2");
Log.d("TEST", "onCreate() Log call 3");
finish();
}
#Override
protected void onDestroy() {
Log.d("TAG", "onDestroy() Log call 1");
Log.d("SMS", "onDestroy() Log call 2");
Log.d("TEST", "onDestroy() Log call 3");
super.onDestroy();
}
}
I would expect this to generate 6 log messages (3 from onCreate(), 3 from onDestroy()). Here is the logcat:
04-14 17:31:58.363: D/TAG(18084): onCreate() Log call 1
04-14 17:31:58.363: D/TEST(18084): onCreate() Log call 3
04-14 17:31:59.905: D/TAG(18084): onDestroy() Log call 1
04-14 17:31:59.905: D/TEST(18084): onDestroy() Log call 3
As can be seen, the lines with the tag "SMS" don't get through. This is not, as far as I can tell a documented thing. The question is, why?
EDIT: More details on the answer.
A rather good answer is given below by Matthew Burke. In short, on the basis of the source code for logd_write.c, it seems that:
Log requests with the following tags are automatically redirected to the radio log:
HTC_RIL
tags starting with RIL
AT
GSM
STK
CDMA
PHONE
SMS
No Log requests are redirected to the events log (or the system log, see also http://elinux.org/Android_Logging_System)
All other Log requests go to the main log, the one that is usually monitored.

I should have read the documentation for logcat before I started hunting through source. According to logcat's documentation:
The Android logging system keeps multiple circular buffers for log messages, and not all of the log messages are sent to the default circular buffer.
Messages with a tag of SMS are sent to the radio buffer, not the main buffer. Hence you won't see them unless you go out of your way to do so. If you run the command:
adb logcat -b radio
you should see your missing log messages. The above information can be found in https://developer.android.com/tools/debugging/debugging-log.html.
Now, for those of you interested in code spelunking, below is my original answer:
The methods in the Log class are all wrappers around println_native which is a JNI method.
println_native performs some validation of its parameters and then calls __android_log_buf_write.
Now this latter method compares the tag parameter (from the original Log.d call) against several hard-coded strings (with the tag SMS being one of this list) and if it finds a match, winds up writing the log message to a different file!
By the way, other tags that get rerouted are GSM, STK, PHONE, CDMA, and a few others.
Relevant source can be read in
http://www.java2s.com/Open-Source/Android/android-core/platform-frameworks-base/android/util/Log.java.htm
https://pdroid.googlecode.com/svn/android-2.3.4_r1/trunk/frameworks/base/core/jni/android_util_Log.cpp
https://in-the-box.googlecode.com/svn-history/r4/trunk/InTheBoxSim/liblog/logd_write.c
http://www.takatan.net/lxr/source/drivers/staging/android/logger.h#L33
These aren't the official links and may disappear at some point. I'll try and track down the official links and edit this later this evening.

EDIT Ignore this, I'm apparently quite off base according to this.
So I thought this was interesting, and after digging through the source, I ended up finding out about Log.isLoggable():
Checks to see whether or not a log for the specified tag is loggable
at the specified level. The default level of any tag is set to INFO.
This means that any level above and including INFO will be logged.
Before you make any calls to a logging method you should check to see
if your tag should be logged. You can change the default level by
setting a system property: 'setprop log.tag. '
Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or
SUPPRESS. SUPPRESS will turn off all logging for your tag. You can
also create a local.prop file that with the following in it:
'log.tag.=' and place that in /data/local.prop.
Parameters
tag
The tag to check. level The level to check. Returns
Whether or not that this is allowed to be logged.
Apparently some tags are not allowed at certain log levels, seemingly defined in /data/local.prop, but there must be some system level properties file I haven't found yet. You can check against it using something like this, though:
boolean isLoggableV = Log.isLoggable("SMS", Log.VERBOSE);
boolean isLoggableD = Log.isLoggable("SMS", Log.DEBUG);
boolean isLoggableI = Log.isLoggable("SMS", Log.INFO);
boolean isLoggableW = Log.isLoggable("SMS", Log.WARN);
boolean isLoggableE = Log.isLoggable("SMS", Log.ERROR);
boolean isLoggableA = Log.isLoggable("SMS", Log.ASSERT);
Log.v("LogTest", String.format("Verbose: %b Debug: %b Info: %b Warn: %b Error: %b Assert: %b", isLoggableV, isLoggableD, isLoggableI, isLoggableW, isLoggableE, isLoggableA));
Which for me returned the following:
Verbose: false Debug: false Info: true Warn: true Error: true Assert: true
So you can log the tag SMS at a log level of INFO and above, but not VERBOSE or DEBUG.
I have to assume this is to prevent applications from accidentally logging personal information, but it seems like a fairly crude way of doing so.

Related

glympse client sdk sample - failed to create error message

I am using the examples from https://developer.glympse.com/docs/core/client-sdk/downloads link.
I tried the GlympseSendDemo and GlympseCreateDemo using Android Studio(without any changes apart from editing the temporary developer API key that I created by creating an account online).
When I run both examples, I get a
"Failed to create"
message. What could be wrong with this?
EDIT 1
Debugging both the samples, the _glympse member is null when it hits the breakpoint i set at createGlympse() method of GlympseWrapper class.
EDIT 2
The GE.PLATFORM_STOPPED event from the Glympse SDK is getting fired that causes the _glympse variable to be set to null through the call GlympseWrapper.instance().clear();.
So my question is why is this event getting fired within a few seconds of the app starting up?
Try setting a breakpoint in GlympseWrapper.clear(). I suspect the platform is stopping after starting causing _glympse to be set to null. If that's happening, double check the api key is entered correctly.
_glympse = GlympseFactory.createGlympse(context, BASE_URL, API_KEY);
// Also try adding this line here to get some additional log information
_glympse.overrideLoggingLevels(CoreConstants.INFO, CoreConstants.INFO);

Get list of available chromecasts on demand

Ok, so I am trying to figure at how to get an up-to-date list of available chromecast devices, I'm doing this so that my app can check when the chromecast is not in use and then open my receiver app.
I am having some unexpected behaviour from the code below:
public class MainActivity extends Activity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
...
mMediaRouterCallback = new MyMediaRouterCallback();
mMediaRouter = MediaRouter.getInstance(context);
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(CastMediaControlIntent.categoryForCast(context.getString(R.string.app_id)))
.build();
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
}
This adds a MediaRouter callback to the MediaRouter. I have chosen to use the active scan flag.
private class MyMediaRouterCallback extends MediaRouter.Callback {
...
#Override
public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "Description 1 " + info.getDescription());
mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
Log.d(TAG, "Description 2 " + mSelectedDevice.toString());
if(info.getDescription().equals("Chromecast")) {
// code to launch chromecast receiver app here.
}
}
}
My implementation of the MediaRouter.Callback overrides onRouteAdded, it simply prints some information about the devices it has found Description 1 describes the receiver app the device is using, description 2 gives its name.
However when this code is run initially the same device is discovered twice printing:
07-05 21:01:12.270: D/MainActivity(9730): Description 1 Casting HelloText
07-05 21:01:12.280: D/MainActivity(9730): Description 2 "Downstairs"
07-05 21:01:12.280: D/MainActivity(9730): Description 1 Casting HelloText
07-05 21:01:12.280: D/MainActivity(9730): Description 2 "Downstairs"
Then periodically the onRouteAdded callback is called sometimes only listing the device once, other times listing the device twice. My understanding however is that this callback should only be called when a new route is added.
I want to find all the available devices on command, not at random intervals that I can't control, what do I need to be doing? I can't find a callback that seems to be appropriate for this situation (such as whenever devices update/change), nor can I find a way to list them without using callbacks, so I'm a bit stuck.
(I have been basing these tests of the HelloText-Android example found here https://github.com/googlecast/CastHelloText-android, also I started this (my first android project) only a couple of days ago, so I apologise if I am missing something horrendously obvious)
Thanks in advance.
Call getRoutes() to get the list of known routes at the point in time that you desire. Iterate over them. Call matchesSelector() on each to filter out those that match your desired control category.
If you are listening for "onRouteAdded()", you would also need to listen to "onRouteRemoved()" to do a correct bookkeeping; if a device is added, it can be removed and added again so if you just listen to onRouteAdded(), it may seem it is being added multiple times. Getting the list from MedaiaRoute.getRoutes() might be easier if you don't want to be notified immediately and only want to know the list at certain points on demand.

Using Log.d() or Log.e() in my code

I have used Log.d() and Log.e() through out my android application for debugging purpose.
I would like to know if I release my application like this, will the user sees all those debug statement that I put in? Do I need to do something special so that user won't see the debug log even if they hook up 'adb logcat'?
Thank you.
Leaving logging statements can, in some cases, be very bad:
http://web.archive.org/web/20121222023201/http://vbsteven.com/archives/535
You can use ProGuard to automatically remove them all:
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** e(...);
}
Consider using this : isLoggable()
Checks to see whether or not a log for the specified tag is loggable at the specified level. The default level of any tag is set to INFO. This means that any level above and including INFO will be logged. Before you make any calls to a logging method you should check to see if your tag should be logged. You can change the default level by setting a system property: setprop log.tag.<YOUR_LOG_TAG> <LEVEL> Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will turn off all logging for your tag. You can also create a local.prop file that with the following in it: log.tag.<YOUR_LOG_TAG>=<LEVEL> and place that in /data/local.prop
Personally for releases, I'd remove the debug logs and keep the error logs using Proguard.
It is better to wrap it like so:
public class MyLog {
public static void d(String tag, String msg) {
if (Log.isLoggable(tag, Log.DEBUG)) {
Log.d(tag, msg);
}
}
public static void i(String tag, String msg) {
if (Log.isLoggable(tag, Log.INFO)) {
Log.i(tag, msg);
}
} // and so on...
You can set logging level by issuing an adb command
Not only can the user (or any app with log access) see your logs, but your logs also cause your app to run slower and use more battery power.
Writing a log, especially from Java, is probably much more expensive than you think: just building the string in Java is a lot of work.
There are apps in the Market that allow users to see logs even without hooking up a development environment.
CatLog is one I have personally used and it will show you everything.
What I've done in my app is create a wrapper class that I can turn off myself with a boolean flag. It has the added benefit of having the TAG parameter being common throughput my code.
public class QLog {
private static final String TAG = "MyAppTag";
private static final boolean DEBUG_MODE = true;
public static void d(String msg) {
if(DEBUG_MODE) {
Log.d(TAG, msg);
}
}
...
}
As it is said in android.developer.com
when you're building the string to pass into Log.d, the compiler uses a StringBuilder and at least three allocations occur: the StringBuilder itself, the buffer, and the String object. Realistically, there is also another buffer allocation and copy, and even more pressure on the gc. That means that if your log message is filtered out, you might be doing significant work and incurring significant overhead.
here is the link:
http://developer.android.com/reference/android/util/Log.html
They can be used when developing. When release, it is better to remove or obfuscate the message to protect PII(Personally identifiable information). The answer here is very useful: Android Log.v(), Log.d(), Log.i(), Log.w(), Log.e() - When to use each one?
Here is the one teach you the tool to deal with these logs when release the software.Remove all debug logging calls before publishing: are there tools to do this?
If your user is a developer, and connects the device to a developing machine and have LogCat opened he will se all logs on Logcat if he interracts with that application. When you are going to publish the application to the final user you should remove those logs.
Logging guidelines
Log.v(String tag, String msg) (verbose)
Log.d(String tag, String msg) (debug)
Log.i(String tag, String msg) (information)
Log.w(String tag, String msg) (warning)
Log.e(String tag, String msg) (error)
To only show logs on debug builds:
if (BuildConfig.DEBUG) Log.d(TAG, "The value of x is " + x);

Does too many log writing decreases android application performance?

I would to know whether logging can decrease application performance?
Also, please give me some tips to increase android application performance.
Yes. Excessive logging affects the performance of any application not just Android.
The developer guide suggests you to deactivate and disabled logging before release:
Turn off logging and debugging Make sure you deactivate logging and
disable the debugging option before you build your application for
release. You can deactivate logging by removing calls to Log methods
in your source files. You can disable debugging by removing the
android:debuggable attribute from the tag in your
manifest file, or by setting the android:debuggable attribute to false
in your manifest file. Also, remove any log files or static test files
that were created in your project.
Also, you should remove all Debug tracing calls that you added to your
code, such as startMethodTracing() and stopMethodTracing() method
calls.
So, you should suppress the logs in "release" or "production" build of your App.
Turn off it in Android Manifest by setting debuggable:
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:debuggable="false">
Another way
Create your own logger class and check for debugging mode before executing log. It allows single point modification between debugging mode and deployed application and allows extra things to do such as writing to log file.
import android.util.Log;
public class MyLog {
private static final boolean isDebug = false;;
public static void i(String tag, String msg) {
if (isDebug) {
Log.i(tag, msg);
}
}
public static void e(String tag, String msg) {
if (isDebug) {
Log.e(tag, msg);
}
}
}
For further info read http://rxwen.blogspot.com/2009/11/logging-in-android.html
and The SO QAs :
Log.d and impact on performance
Android Logging - How to clear for better performance
use 'if' statement before log writing.
you can disable log when application release.
example :
public class LogTest extends Activity {
private static final String TAG = "YOUR_LOG_TAG_NAME";
private static final boolean mDebug = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//--[Start Log example]-----------------------------------------
if(mDebug) Log.d(TAG, "Log Write Test");
//--[End Log example]-----------------------------------------
}
}
Any text output in excess will slow down your application, even with a desktop application. Excessive logging does slow things down, but you would basically need an insane amount of data being sent through, which by the way, isn't that hard to do with a for or while loop. Things that happen in the background while logging sometime include string manipulation, text rendering, cache management, data filtering, log length limiting, and the list goes on.
There's several ways to remove logcat from your final app, especially those involving ProGuard. ProGuard didn't work for me, but there's plenty of brilliant ideas out there on how to remove them including scripting programs like sed.

Time code execution in Android

What is the easiest to time execution in Android?
I have looked around a bit and I found TimingLogger on the Android SDK,
and instructions here. It looks very convenient.
But I can't get it work. This is my code:
TimingLogger timings = new TimingLogger("TopicLogTag", "Parsing html");
My code to time here...
timings.dumpToLog();
It's supposed to dump the times in LogCat. But I can't see anything.. I What am I doing wrong? Eclipse doesn't show any varnings. I guess it has something with verbose ouput, but I have set LogCat to show Verbose.
Thank you..
I gave it a test run and I am experiencing the same thing. It all boils down to this little bit of the description in the Javadoc for TimingLogger:
If the Log.isLoggable is not enabled
to at least the Log.VERBOSE level for
that tag at creation time then the
addSplit and dumpToLog call will do
nothing.
I did a test locally:
TimingLogger timings = new TimingLogger("MyTag", "Initialization");
Log.d("MyTag", "Is Loggable? " + Log.isLoggable("MyTag", Log.VERBOSE));
timings.dumpToLog();
And oddly, I get an output to the log:
06-28 08:35:18.693: DEBUG/MyTag(24366): Is Loggable? false
But that's it. And since it's false, I doubt TimingLogger is doing anything, based on the TimingLogger code:
90 /**
91 * Clear and initialize a TimingLogger object that will log using
92 * the tag and label that was specified previously, either via
93 * the constructor or a call to reset(tag, label). If the
94 * Log.isLoggable is not enabled to at least the Log.VERBOSE
95 * level for that tag at creation time then the addSplit and
96 * dumpToLog call will do nothing.
97 */
98 public void reset() {
99 mDisabled = !Log.isLoggable(mTag, Log.VERBOSE);
100 if (mDisabled) return;
101 if (mSplits == null) {
102 mSplits = new ArrayList<Long>();
103 mSplitLabels = new ArrayList<String>();
104 } else {
105 mSplits.clear();
106 mSplitLabels.clear();
107 }
108 addSplit(null);
109 }
I'm not sure why Log.isLoggable is returning false when it's obviously logging at above VERBOSE, since my Log.d obviously logged.
You can enable logging for that tag manually from the [Log class Javadoc][3]:
You can change the default level by
setting a system property: 'setprop
log.tag. ' Where
level is either VERBOSE, DEBUG, INFO,
WARN, ERROR, ASSERT, or SUPPRESS.
SUPPRESS will turn off all logging for
your tag. You can also create a
local.prop file that with the
following in it:
'log.tag.=' and
place that in /data/local.prop.
Which I did through adb shell:
$ adb shell
# setprop
usage: setprop <key> <value>
# setprop log.tag.MyTag VERBOSE
#
Results in:
06-28 08:53:42.447: DEBUG/MyTag(24739): Is Loggable? true
06-28 08:53:44.744: DEBUG/MyTag(24739): Initialization: begin
06-28 08:53:44.744: DEBUG/MyTag(24739): Initialization: end, 0 ms
See droidgren's comment on this answer - apparently a call to addSplit is also necessary.
[3]: http://developer.android.com/reference/android/util/Log.html#isLoggable(java.lang.String, int)
I found another more simple solution which measures the exact same time as TimingLogger, which doesn't require setprop.
private long startnow;
private long endnow;
startnow = android.os.SystemClock.uptimeMillis();
*Your time consuming code here*
endnow = android.os.SystemClock.uptimeMillis();
Log.d("MYTAG", "Execution time: " + (endnow - startnow) + " ms");
If you guys take a look at its source code, actually the implementation for the TimingLogger class is quite simple.
So what I did, which perfectly fits for my use case, was to make my own version of the class but changing the reset() method to
public void reset() {
mDisabled = false; // <- This is what has changed.
if (mDisabled) return;
if (mSplits == null) {
mSplits = new ArrayList<Long>();
mSplitLabels = new ArrayList<String>();
} else {
mSplits.clear();
mSplitLabels.clear();
}
addSplit(null);
}
The catch here is changing from
mDisabled = !Log.isLoggable(mTag, Log.VERBOSE);
to
mDisabled = false;
This way we don't have to mess with adb.
If you simply looking for logs as explained in developer.android.com, you will not be able to see logs. So use below command:
adb shell setprop log.tag.MyTag VERBOSE
Note: MyTag is the first parameter you passed when creating new TimingLogger as below:
TimingLogger timings = new TimingLogger("MyTag", "MyMethodName");
For your questions's answer, you should execute below command:
adb shell setprop log.tag.TopicLogTag VERBOSE
And there you are. Happy coding !!!
Sometimes we don't need to know the exact time that took us an operation but we want to know, why that operation took so long. Thus, for speeding up code, we only need to know some kind of relational order of parts of that operation where the one taking up the most time seems to be the one you should optimize. Therefore, android brings method tracing:
Debug.startMethodTracing("YOUR_TRACE_FILE_NAME");
// Do your operations
Debug.stopMethodTracing();
Then, the os writes the trace file containing all call infos to filesystem.
Simply drag'n'drop that file onto traceview.bat and start inspecting what calls took how long.
Benefits:
You can inspect all called functions and methods that have been called while tracing.
No need to synchronize data for multithreaded apps.
Trace is written to file automatically - no log cat magic or whatever is necessary. All data is encapsulated together, ready to be inspected.
As soon as you start adding time measuring and especially logging, you wreck your timing anyways.
Link: http://developer.android.com/tools/debugging/debugging-tracing.html
Try doing:
adb shell logcat

Categories

Resources