Thursday, September 25, 2014

Introducing Messages for Android

We are pleased to announce our latest application, Messages for Android. Messages allow you to see consolidated view of all your messages (both emails and SMS, with more message types possibly added in the future release), which comes handy if you have multiple e-mail accounts and you are tired of the necessity to switch among them in the GMail client.

Why another e-mail client ?


The main reason for us to create Messages is the fact that e-mail database is currently not accessible for third parties on Android through any API, while Google never gave any official comment to this omission, my guess is that they would cite security reasons for this decision, clearly you don't want to give access to your emails to some rogue application on your Android device. It goes along the lines of a popular request of fine-grained access to Android permissions which seems never be treated seriously by Android team despite it is highly demanded by the community for multiple years.
To get around this limitation, we created Messages. You need to download it from the Google Play:

https://play.google.com/store/apps/details?id=actiwerks.messages

Current status : Please note that Messages Application is currently in beta, if you are interested to be a part of our tester community, please let us know.

install it on your device, sign into any of your e-mail accounts (using standard IMAP/POP3 protocols/credentials) and your e-mails are accessible through Messages application, both from the UI and through API available for third party applications.

We are very serious about the security of your data, and thus we designed a mechanism that protects your e-mails from being abused, yet is very simple to use by any application, as we don't want to limit the Messages to be used only in our own applications, such as Who's Calling?, it is open to anybody willing to implement the communication & security protocol.

Here you find the description to the Messages API and how to use it.

To access the messages provided by the Messages application, you need to use ContentProvider, which is standard way to access data from the remote application by the third party on Android. While Android provides a way to secure the access by third party as outlined here, it is bit to wide, can easily be overlooked when installing application (especially if such an application has a long list of permissions) and can't be revoked from within Messages. We came up with a different way to secure the access to the Messages ContentProvider.

In order to access the provider you need to specify the following base URI :

content://actiwerks.messages/

In fact, this URI won't return any content. You need to append it with your own secure hash first :

content://actiwerks.messages/your_secure_hash_here/

Where you can get the secure hash from ? It is easy, just ask Messages application for one. This is done by sending it a request connect Intent :

actiwerks.messages.action.GRANT_ACCESS

Here is an example of the code that creates and sends such an intent :

Intent intent = new Intent("actiwerks.messages.action.GRANT_ACCESS");
intent.putExtra("appId", getActivity().getPackageName());
startActivity(intent); 

The Messages application react to this request by displaying the dialog to the user, notifying that your application just asked for permission to access the data of the Messages application.



Since the application needs to provide its package info that is both verified by the PackageManager and used for the callback to your application, user knows which application is asking for access to data an can either grant or reject it. In case of granting the access privileges, they can be revoked at any time by accessing the dialog within the Messages application.

Once the user does either grants or reject the request for the access to the ContentProvider data, the Messages application sends back another Intent carrying the information about result, and in case of the successful approval by the user, the data of the security hash for the application :

actiwerks.messages.action.ACTION_ACCESS_RESULT

Your application should define a broadcast filter to be able to intercept and get the data from the reply Intent:

<receiver
     android:name=".receiver.MessagesAccessResultReceiver_"
     android:exported="true" >
            <intent-filter>
                <action android:name="actiwerks.messages.action.ACTION_ACCESS_RESULT" />
            </intent-filter>
</receiver>

If the request to get access to was successful, the Intent contains extra String data with a key "hash". To get this data, do the following call :

String returnedHash = intentFromMessages.getStringExtra("hash");

If the returned value is non null, your access has been granted and you can use this hash in constructing the content provider URI and you will be able to get the data from the ContentProvider.

Here is a diagram of the entire workflow :



The description of the intents involved in this process are also available in the popular intent registry OpenIntents :

http://www.openintents.org/en/node/953

Working with the content provider


Assuming you were able to get the correct hash to access messages data, here is the explanation of the commands you can get from the Messages content provider. Data are accessed using REST notation.

content://actiwerks.messages/your_secure_hash_here/command/command_details

The basic commands that can be used are :

accounts
mail/account_name
sms

First command will list the names of all available e-mail accounts that were added by the user to the Messages application. You can access any of the accounts by specifying that account name after the /mail part. Using /sms will provide the access to list of SMS as an e-mail pseudo-account.

For each account there might be more specific criteria included.

in
out
read
unread
count


Using these subcommands will give you access to in-coming messages, out-coming messages, already read messages, new (unread messages). If you specify /count as the part of the URI, instead of the list of messages, the content provider will return a number, representing the count of the messages matching your criteria.

If you add any other string except of these "reserved" commands it will try to search for user name containing this string (it can be in the recipient as well as "Carbon copy" a "Blind carbon copy" fields)

Returned value from the content provider is a standard Cursor object, you can inspect its column dynamically to get idea of the data provided in each specific scenario.

We will provide more information about dealing with the returned data from the Messages application in the followup post.

Conclusion


Hope you liked the outlined security framework over the standard Android Content Provider, we believe such revocable, "at the time of service usage" scenario, similar to what iOS users are familiar with offers significant advantages over the traditional Android permission based static system. Our solution is also a proof that there is no need for any special support from the Android OS to make a more granular, lifecycle controlled security solution happen, and we are definitely interested to hear your feedback.

Please note that Messages Application is currently in beta, if you are interested to be a part of our tester community, please let us know.

Saturday, June 15, 2013

Android Library as a .JAR file and accessing the resources in it

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.

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.

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.


  1. 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 ;-) 
  2. Approximate String matching 
  3. 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 :
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 :

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.