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.
Perpetum Design Blog
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.
Labels:
Android,
Objectforms
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.
Wednesday, October 3, 2012
Windows Mobile Screenshot
Recently found an image of HTC-made Windows Mobile phone taken at introduction party in London, about a year ago. It is interesting that nothing changed since that time.
Microsoft is still wander around the mobile phone railway station, the last train with substantial target audience might be long gone.
Thursday, February 16, 2012
Sensor Fusion and the sorry state of mobile sensor API
Let's talk sensors in mobile phones and the applications that can utilize them. It is interesting topic for me for a long, long time, but the urge to write down my two cents came after seeing very interesting video on Google Tech Talk Channel, named "Sensor Fusion on Android Devices" by David Sachs of InvenSense (hence the first part of the title of this post). Here is the video, it is worth watching.
If you think about mobile sensor API, your first reaction might be that this is old news. This feature has been introduced to the world when iPhone shipped with accelerometers, further refined when next generation included gyroscope as well, there is a bunch of applications that are controlled by motion sensors both in AppStore or Android Market thus it must be easy to develop such apps, users are happy and everything is alright.
Except none of this is completely true. Accelerometers arrived earlier than iPhone, even with all the years of improvement their input is still unreliable, API usually deals with very raw data, there is no high-level library to detect common motion gestures (famous "shake" gesture being the only exception) or normalized, useful data and as a result the applications using sensors to control them are still limited in scope and hard to use. All of this has been mentioned in the video above. It is really perplexing to see that little effort happened to provide effective, easy-to-use solution ready for mobile developers. This explains the second part of the title. Hope this situation changes, and we'll see true motion control revolution.
Let's have a look at these points one by one :
1) Accelerometers are available long before iPhone ever existed
My first personal encounter with mobile phone with motion sensor arrived in 2004 in form of Nokia 3220 with Xpress-on Fun Shell add-on, where accelerometer was installed. You can see the 3220 phone here. Rather impractical, you had to buy quite expensive accessory, slide it on the device before it was usable...definitely not for the masses. However it was a great platform for experiments and I ported the famous "Homerun" game : it was a lots of fun when controlled by motion sensor. As Nokia pretty much abandoned the technology and never made it integral part of the mainstream phones (at least until iPhone meteor hit the Earth) we put the entire project on hold, but I have soft spot for sensor controlled applications ever since.
2) Sensors are typically dipped in thick layer of mobile marketing sauce
Again, mentioned in the video, it is fascinating to see how many different marketing names the sensors can get really confusing. What 6-axis sensor means really ? Well, we can probably live with one more example of marketing-newspeak, unfortunately it means that inclusion of some of the sensors is still the part of the marketing "shall we add this $1 chip to charge $50 more for this particular device" game. Sad. Motion sensors needs to be absolute standard across all mobile devices. Hope we are getting there, albeit slowly.
3) Raw data are unreliable and hard to work with
It is nice to have access to raw data if you need them, but it is not so nice that quite often this is the only data from sensors that are available, and they need quite a bit of processing before they are any useful. Even if you manage to filter out noise, some sensor data needs to be combined with data from the other sensor to offset errors, and this is exactly what Sensor Fusion is all about. Love that term and hope this will become an integral part of every major mobile OS API. Android platform seems to be heading in the opposite direction. The Orientation Sensor has been deprecated in Froyo, citing :
On the iOS, the data from the sensors seems to be available in processed form, thanks to "Core Motion" framework, that can provide not only separate data from accelerometer, magnetometer and gyroscope, as well as processed data of both accelerometer and gyroscope fused together. There is CMDeviceMotion class that has CMAttitude property which holds information about device motion and attitude, available either in quaternion, rotation matrix or Euler angles form. Seems that iOS currently lacks any support for dedicated linear acceleration sensor, thus such information needs to be extracted from accelerometer and might be inaccurate.
4) Total lack of standardized motion gestures
Already mentioned that shake gesture is probably the only exception. The lack of other, high-level gestures that can be recognized by the phone OS and intercepted by the application developer in easy-to-use way, really limits what might be possible to achieve with sensor controlled applications. We need this to see new stream of applications that can be used even without direct eye interaction.
On iOS, only Shake gesture is currently recognized, an it is mapped to the UIEvent (same event type as other events such as multitouch events), which is rather strange. On Android platform, there is no support for any motion gesture recognition at all.
Edit: Added link to the Samsung proprietary kinetic gestures
Conclusion
Let's hope the set of sensors available on even most basic phones will only grow, and they will become a true standard, such as (multi)touch screen is one now. At the same time, let's hope that quality of the data provided by the sensors will improve, using the techniques mentioned in the video above.
We believe that the last point is the most pressing problem : the lack of set of motion gestures, that are understood by the users on one hand (i.e. the UX across applications and perhaps across platforms is consistent) and they are easy to recognize for the application developers (ideally by calling one line of code).
To facilitate this lengthy and tedious process, we would like to take an active approach. First, we looking for other people, both designers, developers or users, who see the importance of the common motion gesture library - please get in touch. Second, we would like to announce start of active development in this area...there will be a tool, that will help to explain, record and collect motion gestures in order to understand them better and eventually start a web site that will serve as a collection of such gestures. Watch this space for further announcements.
If you think about mobile sensor API, your first reaction might be that this is old news. This feature has been introduced to the world when iPhone shipped with accelerometers, further refined when next generation included gyroscope as well, there is a bunch of applications that are controlled by motion sensors both in AppStore or Android Market thus it must be easy to develop such apps, users are happy and everything is alright.
Except none of this is completely true. Accelerometers arrived earlier than iPhone, even with all the years of improvement their input is still unreliable, API usually deals with very raw data, there is no high-level library to detect common motion gestures (famous "shake" gesture being the only exception) or normalized, useful data and as a result the applications using sensors to control them are still limited in scope and hard to use. All of this has been mentioned in the video above. It is really perplexing to see that little effort happened to provide effective, easy-to-use solution ready for mobile developers. This explains the second part of the title. Hope this situation changes, and we'll see true motion control revolution.
Let's have a look at these points one by one :
1) Accelerometers are available long before iPhone ever existed
My first personal encounter with mobile phone with motion sensor arrived in 2004 in form of Nokia 3220 with Xpress-on Fun Shell add-on, where accelerometer was installed. You can see the 3220 phone here. Rather impractical, you had to buy quite expensive accessory, slide it on the device before it was usable...definitely not for the masses. However it was a great platform for experiments and I ported the famous "Homerun" game : it was a lots of fun when controlled by motion sensor. As Nokia pretty much abandoned the technology and never made it integral part of the mainstream phones (at least until iPhone meteor hit the Earth) we put the entire project on hold, but I have soft spot for sensor controlled applications ever since.
2) Sensors are typically dipped in thick layer of mobile marketing sauce
Again, mentioned in the video, it is fascinating to see how many different marketing names the sensors can get really confusing. What 6-axis sensor means really ? Well, we can probably live with one more example of marketing-newspeak, unfortunately it means that inclusion of some of the sensors is still the part of the marketing "shall we add this $1 chip to charge $50 more for this particular device" game. Sad. Motion sensors needs to be absolute standard across all mobile devices. Hope we are getting there, albeit slowly.
3) Raw data are unreliable and hard to work with
It is nice to have access to raw data if you need them, but it is not so nice that quite often this is the only data from sensors that are available, and they need quite a bit of processing before they are any useful. Even if you manage to filter out noise, some sensor data needs to be combined with data from the other sensor to offset errors, and this is exactly what Sensor Fusion is all about. Love that term and hope this will become an integral part of every major mobile OS API. Android platform seems to be heading in the opposite direction. The Orientation Sensor has been deprecated in Froyo, citing :
heavy processing that is involved, the accuracy and precision of the orientation sensor is diminished (specifically, this sensor is only reliable when the roll component is 0)as the reason for the move. Now you need to do a bit of computation on your behalf. There is arbitrary Rotation Matrix available and it is possible to get orientation relative to such a matrix. However, it is not specified, if the values from various sensors are corrected in any way...seems they are not. Anyone has any experience with this ? Seems it is still quite easy to get data, that are totally wrong, especially from the magnetometer.
On the iOS, the data from the sensors seems to be available in processed form, thanks to "Core Motion" framework, that can provide not only separate data from accelerometer, magnetometer and gyroscope, as well as processed data of both accelerometer and gyroscope fused together. There is CMDeviceMotion class that has CMAttitude property which holds information about device motion and attitude, available either in quaternion, rotation matrix or Euler angles form. Seems that iOS currently lacks any support for dedicated linear acceleration sensor, thus such information needs to be extracted from accelerometer and might be inaccurate.
4) Total lack of standardized motion gestures
Already mentioned that shake gesture is probably the only exception. The lack of other, high-level gestures that can be recognized by the phone OS and intercepted by the application developer in easy-to-use way, really limits what might be possible to achieve with sensor controlled applications. We need this to see new stream of applications that can be used even without direct eye interaction.
On iOS, only Shake gesture is currently recognized, an it is mapped to the UIEvent (same event type as other events such as multitouch events), which is rather strange. On Android platform, there is no support for any motion gesture recognition at all.
Edit: Added link to the Samsung proprietary kinetic gestures
Conclusion
Let's hope the set of sensors available on even most basic phones will only grow, and they will become a true standard, such as (multi)touch screen is one now. At the same time, let's hope that quality of the data provided by the sensors will improve, using the techniques mentioned in the video above.
We believe that the last point is the most pressing problem : the lack of set of motion gestures, that are understood by the users on one hand (i.e. the UX across applications and perhaps across platforms is consistent) and they are easy to recognize for the application developers (ideally by calling one line of code).
To facilitate this lengthy and tedious process, we would like to take an active approach. First, we looking for other people, both designers, developers or users, who see the importance of the common motion gesture library - please get in touch. Second, we would like to announce start of active development in this area...there will be a tool, that will help to explain, record and collect motion gestures in order to understand them better and eventually start a web site that will serve as a collection of such gestures. Watch this space for further announcements.
Monday, August 8, 2011
The Strange Case of Dr. Action and Mr. Bar
Lately, I've been trying to finally update the behavior of the ObjectForms Demo application on the Honeycomb tablet and one of the missing pieces was support for the ActionBar, the new feature of Honeycomb. Well, not that so new feature. ActionBar was promoted by Google engineers (such as this one) even before Honeycomb was published.
As many other app developers, ObjectForms tried to be a good Android citizen and followed the Google provided advice, so there is a custom implementation of the ActionBar related functionality for a quite some time and I thought since I crafted my interface to look similar to actual Honeycomb API so I thought this will be piece of cake.
With some awkward reflection and dynamic invocation code (I wanted the same codebase to work on pre-Honeycomb as well) I was set to go. To my surprise, I the ActionBar was not showing up on the Motorola Xoom device no matter how hard I tried. The ActionBar was not there and this call :
was returning no value.
Neither ActionBar documentation nor the ActionBar developer Guide gave any relevant answers. I learned some interesting aspects about the ActionBar design.
First, documentation says that if the ActionBar is visible or not, is controlled by the changes of (!!!!) visual theme ! WOW, that's example of very bad engineering. Sure I did try to apply the correct theme, but it made no difference.
Second thing that I found very unusual was the fact that ActionBar, although very visual component itself, able to contain other visual components (tabs, custom components etc.) is not part of the visual hierarchy and is not descendant of View class, but rather just plain Object. It made no sense to me.
I was ready to find some workaround. Let's keep my original, custom ActionBar, and just put the button that would show the menu - once you declare in the Android manifest that you target Honeycomb device the "compatibility" menu (located in the bar on the bottom of the screen, next to the "Back" and "Home" buttons) is gone and you can only access it from the ActionBar (in the top right corner). But to my great surprise, the method :
was doing nothing, although it worked perfectly well on the Gingerbread and earlier Android devices. Hm.
Typically, I would explore the Android source code to see what might be the reason for that unusual behavior, but Honeycomb is not quite open source ;-( so I was out of luck there. Seems I hit the wall.
The next effort was to understand what the hell this visual theme actually does to hide the ActionBar. Problem was, that content of the theme is not public either. But trying to search for any clues, I got to this page that helped me to solve the entire mystery. Yeah, title might be that important attribute. As I had my own implementation of ActionBar on the top, I wanted to maximize the available space and asked the window manager to hide a title for me. With single line of code commented out :
And the magic is gone and Honeycomb ActionBar is there. It is really just a glorified title bar, so it must be visible in Honeycomb to behave correctly. This little fact is mentioned in the Android Honeycomb documentation, so this is my first take-away for people trying to cope with the same problem :
Since I believe most developers face the similar scenario I had, they have their own implementation of the ActionBar for Gingerbread and as the result they had a window without the title, the solution Google has for the Honeycomb is extremely unintuitive. Glad I found a solution.
Not only this, but to my surprise I found that openOptionsMenu() started to work as well. That's amazing !
But I was still not done. As you can see from the picture above, the first version had both native Honeycomb ActionBar and the custom Gingerbread one.
I wanted to reorganize my code to be more reusable and in middle of this I realized the ActionBar is gone again, the getActionBar() is returning nothing again. But I was able to track my changes, so it didn't take long to figure out what is problem this time. I tried to create my visual hierarchy first and expected that getActionBar() will tell me if I have native HoneyComb ActionBar or not. But this method is useless, as it assumes setContentView(view) has already been called. Since I was just constructing that view, this was not the case. Of course, this is another quite important aspect never mentioned in the documentation.
Hey Google, if your code requires the contract, and you are not able to enforce it by API design, please do us a favor and let us know about the contract !
So this is my second take-away as the case gets some clarification :
Just to make the story complete, I wanted to have the look of the native ActionBar to be similar to previous version, and wanted to replace the logo with one that doesn't look as been a part of the button. I was not shocked to learn that customization is possible only in form of replacing the XML attribute "logo" with a custom value, and there is no corresponding Java API for that. It is still not clear to me why ActionBar is not descendant of View and why it is so difficult to deal with it, but apart of that, all the mystery has been solved.
As you can see, I decided to solve this customization problem by hiding the native ActionBar and rely on the fact that menu button in the top right corner works as expected. In this context, perhaps you'd think that I could save a lot of hassle and skip the ActionBar completely. There is one important aspect, which is the third and final take-away from this post :
Hope you find the information mentioned in this post useful and hopefully they can save you some head-scratching time I had recently.
As many other app developers, ObjectForms tried to be a good Android citizen and followed the Google provided advice, so there is a custom implementation of the ActionBar related functionality for a quite some time and I thought since I crafted my interface to look similar to actual Honeycomb API so I thought this will be piece of cake.
With some awkward reflection and dynamic invocation code (I wanted the same codebase to work on pre-Honeycomb as well) I was set to go. To my surprise, I the ActionBar was not showing up on the Motorola Xoom device no matter how hard I tried. The ActionBar was not there and this call :
public ActionBar getActionBar() of the class Activity (see the API)
was returning no value.
Neither ActionBar documentation nor the ActionBar developer Guide gave any relevant answers. I learned some interesting aspects about the ActionBar design.
First, documentation says that if the ActionBar is visible or not, is controlled by the changes of (!!!!) visual theme ! WOW, that's example of very bad engineering. Sure I did try to apply the correct theme, but it made no difference.
Second thing that I found very unusual was the fact that ActionBar, although very visual component itself, able to contain other visual components (tabs, custom components etc.) is not part of the visual hierarchy and is not descendant of View class, but rather just plain Object. It made no sense to me.
I was ready to find some workaround. Let's keep my original, custom ActionBar, and just put the button that would show the menu - once you declare in the Android manifest that you target Honeycomb device the "compatibility" menu (located in the bar on the bottom of the screen, next to the "Back" and "Home" buttons) is gone and you can only access it from the ActionBar (in the top right corner). But to my great surprise, the method :
public void openOptionsMenu() of class Activity (see the API)
was doing nothing, although it worked perfectly well on the Gingerbread and earlier Android devices. Hm.
Typically, I would explore the Android source code to see what might be the reason for that unusual behavior, but Honeycomb is not quite open source ;-( so I was out of luck there. Seems I hit the wall.
The next effort was to understand what the hell this visual theme actually does to hide the ActionBar. Problem was, that content of the theme is not public either. But trying to search for any clues, I got to this page that helped me to solve the entire mystery. Yeah, title might be that important attribute. As I had my own implementation of ActionBar on the top, I wanted to maximize the available space and asked the window manager to hide a title for me. With single line of code commented out :
if(android.os.Build.VERSION.SDK_INT < 11) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
And the magic is gone and Honeycomb ActionBar is there. It is really just a glorified title bar, so it must be visible in Honeycomb to behave correctly. This little fact is mentioned in the Android Honeycomb documentation, so this is my first take-away for people trying to cope with the same problem :
Make sure that title of window is visible if you want to show the Honeycomb ActionBar !
Since I believe most developers face the similar scenario I had, they have their own implementation of the ActionBar for Gingerbread and as the result they had a window without the title, the solution Google has for the Honeycomb is extremely unintuitive. Glad I found a solution.
Not only this, but to my surprise I found that openOptionsMenu() started to work as well. That's amazing !
But I was still not done. As you can see from the picture above, the first version had both native Honeycomb ActionBar and the custom Gingerbread one.
I wanted to reorganize my code to be more reusable and in middle of this I realized the ActionBar is gone again, the getActionBar() is returning nothing again. But I was able to track my changes, so it didn't take long to figure out what is problem this time. I tried to create my visual hierarchy first and expected that getActionBar() will tell me if I have native HoneyComb ActionBar or not. But this method is useless, as it assumes setContentView(view) has already been called. Since I was just constructing that view, this was not the case. Of course, this is another quite important aspect never mentioned in the documentation.
Hey Google, if your code requires the contract, and you are not able to enforce it by API design, please do us a favor and let us know about the contract !
So this is my second take-away as the case gets some clarification :
Make sure the setContentView(view) has been already called for your Activity, otherwise getActionBar() will return null.
Just to make the story complete, I wanted to have the look of the native ActionBar to be similar to previous version, and wanted to replace the logo with one that doesn't look as been a part of the button. I was not shocked to learn that customization is possible only in form of replacing the XML attribute "logo" with a custom value, and there is no corresponding Java API for that. It is still not clear to me why ActionBar is not descendant of View and why it is so difficult to deal with it, but apart of that, all the mystery has been solved.
As you can see, I decided to solve this customization problem by hiding the native ActionBar and rely on the fact that menu button in the top right corner works as expected. In this context, perhaps you'd think that I could save a lot of hassle and skip the ActionBar completely. There is one important aspect, which is the third and final take-away from this post :
If you target Honeycomb in the manifest, you need native ActionBar to be at least hidden, otherwise there is no way to show the option menus.
Hope you find the information mentioned in this post useful and hopefully they can save you some head-scratching time I had recently.
Tuesday, June 14, 2011
Android vs. iOS Battery-related Myths
Apple just recently introduced the new version of its mobile operating system, iOS 5. Among many enhancements that were announced, the ones that caused the most attention are definitely the new notification system and introduction of more powerful (and more complex) lock screen. Especially the notification centre resembles the system used by Android for several years (some call it a blatant rip-off) and lock screen is now also closer to what can be found on many other "smartphones".
These new features fueled somewhat dying discussions about possible introduction of still-missing "widgets" to enhance spartan Springboard home screen of iOS and the evergreen debate concerning the differences of implementation of the multitasking and the its availability for the third party developers.
The old demon of presumed better energy efficiency of the iOS implementation got a sprinkle of the fresh water and it become a popular argument of the iOS supporters once again, so perhaps it is good time to have a closer look at many myths that surround the multitasking implementation in the respective operating systems.
Let's kick-off with the facts. Both iOS and Android are (relatively) modern OS, based on strong, battle tested cores (BSD Unix in the iOS case, mobile optimized Linux version for Android) running on modern, powerful hardware, that makes any form of multitasking perfectly possible. Both OS are built around multitasking and it is used by the System software.
Both systems are heavily optimized for the mobile usage. Not only the power consumption is of a big importance, there is strong focus on availability of the system resources in case of urgent need : if there is a immediate demand for the uninterrupted processor power, such as in the case of the incoming call (which is top priority to be handled without interference from whatever tasks that may be keeping the CPU busy). Both systems are very able in that regard and the entire OS metaphor is build around idea that app might exit expeditiously - in both cases there are very few states, there are no dialogs that expect the user to explicitly confirm to complete the current action, there is no "Quit" command in the menu etc.
iOS metaphor was initially designed to be very simple. There was no sense of multitasking at all, this was only introduced later, and in quite a limited form for the third party software running on iOS. Apple hype machine tried to sell this as paramount feature as being super power efficient. Developers are irresponsible idiots, the system needs to make sure no resources are wasted so only a very special, limited form of background activity is permitted for third party, was iOS mantra and at the same time Apple tried to depict their rival as total battery hog driven by many apps that all arrogantly eat precious juice of the pesky green bot machines even if there is no real need to do so. We are so much better designed system, was the conclusion of iOS supporters.
Wait...it is not that apps on Android live happily in the background and all they do is ruin the battery life. As mentioned earlier, both platforms apps are designed to be ready to die at any given moment. That moment usually comes right when the user navigates away from the given application to another one. It is usually suspended, or straight killed. The happy live in the backyard bush is only granted to special code on Android too, known as services. There are rules for them too and service is not automatically granted unlimited resource access. However Android gives developers more freedom to suck the battery, based on idea that perhaps there are situations where user really wants to use apps that do some intensive tasks in the background for a limited period of time and are OK with the reduced battery life. If they fathom that their device run on single charge is too short, Android gives them ways to track the offending piece of code quickly and take action (uninstalling, one-starring, even mailing the developer until order is restored).
But that "we are more efficient" illusion of iOS is not something its fans want to cede easy. The stronghold argument of the power consumption superiority remains the home screen and widgets. New lock screen of iOS 5 might be seen as precursor of third party widgets coming soon. "Never, widgets are just catastrophe, ever updating on the background". This is just another myth. Lets have a look at the following :
How Android can be more power efficient, despite widgets and more relaxed rules for services ?
"Impossible, we are the best" is the short answer from the iOS camp. Well perhaps not really. Let's go for more arguments. "iOS is build around notifications, your application get will start once there are new data for it, no need to poll the server. iOS rocks !"
This is true. It is also true that very same system is available on the Android too, no need to poll the server either. But wait, there is actually more. Android is build about idea of small pieces of code, Activites, that constantly share information through the mechanism called Intents. OS provide a wide array of such data on its own, through system called Event Broadcast.
"Ha ! Another battery life trap ! Android developers constantly run some code, while the iOS is quietly conserving power". Well not quite like that. Sure, if you execute some code in Broadcast filter, this means extra consumption, but this code is super light. On the other hand, it gives the developer information, that is not available to third party software on iOS and must be obtained by - guess what - polling. If your application wants to do something special if some event just happened, it can, just running that little snippet of code. Say there is some other application trying to get the latest GPS location - listen for this type of event and your application can get the the most accurate location info for free. Another example : your application needs to send some stuff to the server. Again, if time of delivery is not that critical, wait for some other application to establish the network connection (which is expensive operation in terms of battery life) and take opportunity to bundle some data while radio is on. This is how a lot of battery life can be saved.
The best proof this is a viable concept is the fact that Apple is introducing similar concept in the latest iterations of iOS and developers can register at the NSNotificationCenter, however it is still quite limited in comparison to Android system-wide mechanism.
We, developers at Perpetum Design are super serious about the quality of our apps, and the impact the application has on the battery life of the device is an integral part of our design decisions. There were multiple cases when we were able to convince our customers to tackle the problem differently just because of the battery life concerns.
We believe most of developers think that way, thus more flexibility you have as the developer, the better for the entire ecosystem. Fortunately, the OS vendors seems to understand this too, and iOS and Android are looking more and more similar in that regard.
Hope this article helped to get light on some of those myths that surround differences between mobile platforms and their battery life related architecture and performance.
These new features fueled somewhat dying discussions about possible introduction of still-missing "widgets" to enhance spartan Springboard home screen of iOS and the evergreen debate concerning the differences of implementation of the multitasking and the its availability for the third party developers.
The old demon of presumed better energy efficiency of the iOS implementation got a sprinkle of the fresh water and it become a popular argument of the iOS supporters once again, so perhaps it is good time to have a closer look at many myths that surround the multitasking implementation in the respective operating systems.
Let's kick-off with the facts. Both iOS and Android are (relatively) modern OS, based on strong, battle tested cores (BSD Unix in the iOS case, mobile optimized Linux version for Android) running on modern, powerful hardware, that makes any form of multitasking perfectly possible. Both OS are built around multitasking and it is used by the System software.
Both systems are heavily optimized for the mobile usage. Not only the power consumption is of a big importance, there is strong focus on availability of the system resources in case of urgent need : if there is a immediate demand for the uninterrupted processor power, such as in the case of the incoming call (which is top priority to be handled without interference from whatever tasks that may be keeping the CPU busy). Both systems are very able in that regard and the entire OS metaphor is build around idea that app might exit expeditiously - in both cases there are very few states, there are no dialogs that expect the user to explicitly confirm to complete the current action, there is no "Quit" command in the menu etc.
iOS metaphor was initially designed to be very simple. There was no sense of multitasking at all, this was only introduced later, and in quite a limited form for the third party software running on iOS. Apple hype machine tried to sell this as paramount feature as being super power efficient. Developers are irresponsible idiots, the system needs to make sure no resources are wasted so only a very special, limited form of background activity is permitted for third party, was iOS mantra and at the same time Apple tried to depict their rival as total battery hog driven by many apps that all arrogantly eat precious juice of the pesky green bot machines even if there is no real need to do so. We are so much better designed system, was the conclusion of iOS supporters.
Wait...it is not that apps on Android live happily in the background and all they do is ruin the battery life. As mentioned earlier, both platforms apps are designed to be ready to die at any given moment. That moment usually comes right when the user navigates away from the given application to another one. It is usually suspended, or straight killed. The happy live in the backyard bush is only granted to special code on Android too, known as services. There are rules for them too and service is not automatically granted unlimited resource access. However Android gives developers more freedom to suck the battery, based on idea that perhaps there are situations where user really wants to use apps that do some intensive tasks in the background for a limited period of time and are OK with the reduced battery life. If they fathom that their device run on single charge is too short, Android gives them ways to track the offending piece of code quickly and take action (uninstalling, one-starring, even mailing the developer until order is restored).
Android service lifecycle
But that "we are more efficient" illusion of iOS is not something its fans want to cede easy. The stronghold argument of the power consumption superiority remains the home screen and widgets. New lock screen of iOS 5 might be seen as precursor of third party widgets coming soon. "Never, widgets are just catastrophe, ever updating on the background". This is just another myth. Lets have a look at the following :
How Android can be more power efficient, despite widgets and more relaxed rules for services ?
"Impossible, we are the best" is the short answer from the iOS camp. Well perhaps not really. Let's go for more arguments. "iOS is build around notifications, your application get will start once there are new data for it, no need to poll the server. iOS rocks !"
This is true. It is also true that very same system is available on the Android too, no need to poll the server either. But wait, there is actually more. Android is build about idea of small pieces of code, Activites, that constantly share information through the mechanism called Intents. OS provide a wide array of such data on its own, through system called Event Broadcast.
"Ha ! Another battery life trap ! Android developers constantly run some code, while the iOS is quietly conserving power". Well not quite like that. Sure, if you execute some code in Broadcast filter, this means extra consumption, but this code is super light. On the other hand, it gives the developer information, that is not available to third party software on iOS and must be obtained by - guess what - polling. If your application wants to do something special if some event just happened, it can, just running that little snippet of code. Say there is some other application trying to get the latest GPS location - listen for this type of event and your application can get the the most accurate location info for free. Another example : your application needs to send some stuff to the server. Again, if time of delivery is not that critical, wait for some other application to establish the network connection (which is expensive operation in terms of battery life) and take opportunity to bundle some data while radio is on. This is how a lot of battery life can be saved.
Android battery profiler reveals most juice is lost thanks to display. If you want to save power, don't use the damn device !
The best proof this is a viable concept is the fact that Apple is introducing similar concept in the latest iterations of iOS and developers can register at the NSNotificationCenter, however it is still quite limited in comparison to Android system-wide mechanism.
We, developers at Perpetum Design are super serious about the quality of our apps, and the impact the application has on the battery life of the device is an integral part of our design decisions. There were multiple cases when we were able to convince our customers to tackle the problem differently just because of the battery life concerns.
We believe most of developers think that way, thus more flexibility you have as the developer, the better for the entire ecosystem. Fortunately, the OS vendors seems to understand this too, and iOS and Android are looking more and more similar in that regard.
Hope this article helped to get light on some of those myths that surround differences between mobile platforms and their battery life related architecture and performance.
Subscribe to:
Posts (Atom)





