There was a new wave of discussions around possibility of packaging of the Android Library into a .JAR file and how to access resources in it. It is quite understandable, as current traditional solution, consisting of creating special Library Project and referencing such project from your main project, quite plainly, sucks. If you have multiple projects linked like this, your IDE will turn into crawling and you will constantly face breaks in this very fragile system.
What are our options to solve this problem ?
One possibility is to skip it altogether, and always copy all the files into the single project. It requires both discipline and good tracking system not to modify "library code" in two different projects, but it is manageable this way, and single flat project with no dependencies usually offers considerable speed advantages.
But it is not always possible to use this, especially when you want to package your code into "Library" to be used by the third party. Google is well aware of this problem and in the latest iteration of its ADK (based on Idea and Gradle) plans to introduce a new system that would allow similar mechanism. But their choice to introduce yet another archive format (although it is very similar to .JAR, with just different manifest file) is puzzling, and there is no guarantee this would work for this particular purpose, given the long history of failures of the ADK team. Also there are cases, where .JAR is the only option. We were exactly in the same position as our ObjectForms library would be best served as .JAR library thus we spent considerable amount of research on the matter in order to have a working solution.
Lets have a look what it takes to create Android .JAR library and how to access the eventual resources packed into it. There are many myths around this, with some people claiming "it is not possible at all", some of this information is inaccurate.
First part of the series will cover options in creation of a .JAR file, stay tuned for a link appearing here.
Saturday, June 15, 2013
Thursday, May 30, 2013
Saving time while logging on Android, four key strokes at a time
I guess pretty much every Android developer uses logging system, and thus is familiar with the following page from the Android documentation:
That means to log a line you use a call like this:
Log.i(TAG, "Index=" + i);
Where TAG is defined as:
private static final String TAG = "MyActivity";
Proactive developers often don't like the refactoring time bomb of String literal to represent the log tag and often replace it with a following line:
private static final String TAG = MtActivity.class.getSimpleName();
Still this is a lot of code to type, plus the "TAG," parameter every time you use the log command in your code.
Well, you probably don't mind extra four characters typed, but if you multiply this by the number of times you scatter this line in your code (which is quite likely a big, big number), it becomes a large chunk of time that can be better spent doing something else, just because the API asks you to provide the value of the parameter that might be obtained for you automatically.
Let's have a look if there is an alternative. Well, lets just have a similar method, which just omits the TAG parameter. The modified call looks like this:
prn.log("Index=" + i);
Plus we don't have to declare the TAG static variable anymore as well. Sounds like a problem solved. But we still want to have the information in the log file about the location of the log message. Where we get this from ? Will we use the magic ? That's definitely one option, but other one is to leverage the Java Exception system, and do the Stack Trace analysis to obtain the origin of the log message. The scenario is quite simple. First we throw a new Exception and surround it with the catch block that will do the Stack Trace analysis:
What's the catch ? Many of you probably noticed that there is a new object created for every log method call - the new Exception needs to be thrown to get the Stack Trace to analyze. This might be definitely problematic inside the tight loop, but there are ways to deal with this. First, you can shortcut the log message origin inspection (for production environment, for example) or use the excessive object allocation (and subsequent garbage collection calls) to your advantage to spot these tight loops with unintended log calls in them (you most likely don't want to have logs in the tight loops anyway). Another alternative is to resort to the original API: it is still there for you to use and there is nothing wrong with it if you know what is the purpose of explicitly provide the log context information. It just feels stupid to me to do so every single time just because the poor designed API asks you to do so.
If you liked the idea of the simplified logging on Android, there is easy way for you to hop the train. Just go to the following address:
https://github.com/actiwerks/logdroid
and either grab the copy of the entire project, or just download the jar file (located at: https://github.com/actiwerks/logdroid/blob/master/library/bin/logdroidlibrary.jar) and include it in your Android project. All you have to do to make the log system to work is to work is to import the correct package:
import objectforms.utils.prn;
Please note that while logdroid is available as the separate open source package in GITHub, it has been originally developed as part of the ObjectForms framework and it still keeps the original package name. Another aspect of this heritage is that prn.log(); call is platform independent and should work anywhere ObjectForms get ported to in the future. In order to fully integrate it with the native Android logging (including correctly filling the TAG argument), you need to connect the two systems at a start of your Android application or any similar appropriate moment. This can be done by calling the following method of the prn class :
public static void setPrinter(LogPrinter myPrinter);
There is implementation of the LogPrinter ready for you, in form of class:
actiwerks.logdroid.LogPlug;
All you need to do in your application is inserting this line of code :
prn.setPrinter(new actiwerks.logdroid.LogPlug());
and you are done. If you fail to provide this connection, the logging still works but it would resort to the platform neutral bottom line, System.out.println(); which in turn would omit the TAG information.
Hope you find the simplification to the default Android logging system useful and become a happy user of logdroid library. It only saves four key strokes at a time, but in the long run we hope it would be well worth the investment.
That means to log a line you use a call like this:
Log.i(TAG, "Index=" + i);
Where TAG is defined as:
private static final String TAG = "MyActivity";
Proactive developers often don't like the refactoring time bomb of String literal to represent the log tag and often replace it with a following line:
private static final String TAG = MtActivity.class.getSimpleName();
Still this is a lot of code to type, plus the "TAG," parameter every time you use the log command in your code.
Well, you probably don't mind extra four characters typed, but if you multiply this by the number of times you scatter this line in your code (which is quite likely a big, big number), it becomes a large chunk of time that can be better spent doing something else, just because the API asks you to provide the value of the parameter that might be obtained for you automatically.
Let's have a look if there is an alternative. Well, lets just have a similar method, which just omits the TAG parameter. The modified call looks like this:
prn.log("Index=" + i);
Plus we don't have to declare the TAG static variable anymore as well. Sounds like a problem solved. But we still want to have the information in the log file about the location of the log message. Where we get this from ? Will we use the magic ? That's definitely one option, but other one is to leverage the Java Exception system, and do the Stack Trace analysis to obtain the origin of the log message. The scenario is quite simple. First we throw a new Exception and surround it with the catch block that will do the Stack Trace analysis:
What's the catch ? Many of you probably noticed that there is a new object created for every log method call - the new Exception needs to be thrown to get the Stack Trace to analyze. This might be definitely problematic inside the tight loop, but there are ways to deal with this. First, you can shortcut the log message origin inspection (for production environment, for example) or use the excessive object allocation (and subsequent garbage collection calls) to your advantage to spot these tight loops with unintended log calls in them (you most likely don't want to have logs in the tight loops anyway). Another alternative is to resort to the original API: it is still there for you to use and there is nothing wrong with it if you know what is the purpose of explicitly provide the log context information. It just feels stupid to me to do so every single time just because the poor designed API asks you to do so.
If you liked the idea of the simplified logging on Android, there is easy way for you to hop the train. Just go to the following address:
https://github.com/actiwerks/logdroid
and either grab the copy of the entire project, or just download the jar file (located at: https://github.com/actiwerks/logdroid/blob/master/library/bin/logdroidlibrary.jar) and include it in your Android project. All you have to do to make the log system to work is to work is to import the correct package:
import objectforms.utils.prn;
Please note that while logdroid is available as the separate open source package in GITHub, it has been originally developed as part of the ObjectForms framework and it still keeps the original package name. Another aspect of this heritage is that prn.log(); call is platform independent and should work anywhere ObjectForms get ported to in the future. In order to fully integrate it with the native Android logging (including correctly filling the TAG argument), you need to connect the two systems at a start of your Android application or any similar appropriate moment. This can be done by calling the following method of the prn class :
public static void setPrinter(LogPrinter myPrinter);
There is implementation of the LogPrinter ready for you, in form of class:
actiwerks.logdroid.LogPlug;
All you need to do in your application is inserting this line of code :
prn.setPrinter(new actiwerks.logdroid.LogPlug());
and you are done. If you fail to provide this connection, the logging still works but it would resort to the platform neutral bottom line, System.out.println(); which in turn would omit the TAG information.
Hope you find the simplification to the default Android logging system useful and become a happy user of logdroid library. It only saves four key strokes at a time, but in the long run we hope it would be well worth the investment.
Tuesday, March 19, 2013
Techniques for approximate string matching
Since we are planning to add fuzzy matching of string (user names) to our "Who's Calling?" Android application, here is a list of tools and algorithms that can be useful for this task.
This list is no way complete, perhaps there will be a pointer to a follow-up article once there is some progress on the implementation of our text matching solution.
Please feel free to add more ideas or pointers in the comments area. Thank you.
- Levenshtein distance we used this years ago in the first Casus prototype. Levenshtein is tricky name, I rememebered it as Levenstein, but as its Levenshtein distance to original name is just one, it was not too difficult to find the real one ;-)
- Approximate String matching
- Somehow related, and very interesting article on writing your own spell checker
This list is no way complete, perhaps there will be a pointer to a follow-up article once there is some progress on the implementation of our text matching solution.
Please feel free to add more ideas or pointers in the comments area. Thank you.
Subscribe to:
Posts (Atom)