WillerZ/snique-client-android — pull request #1 by abirkill (2012-06-04 03:43:47+00:00)
Title: Updates to improve compatibility and reliability

I tried this on my Android devices and a few emulator images I have set up. It would generally work OK on the emulator for versions of Android >2.2 and <4.0. I couldn't get it to work on either of my physical devices.

As such, I've made some changes to fix the issues I was seeing. In the order of which I discovered them:

1. CacheManager.getCacheFile(url) was not correctly returning the HTML source code on Android 4.0 on either the emulator or my Android 4.0 phone. The data it was returning appeared to be corrupted -- this may be a character encoding issue, however, I don't believe so as the data appeared to vary per execution.

As the CacheManager is deprecated, I re-wrote the code significantly to avoid using it to retrieve the source HTML. Instead, on the initial request to load the page, I instead download the HTML source via TCP/IP, and then pipe this output both to the WebView and to the decoding algorithm.

As Android 4.0 prevents (by default) performing network activities on the UI thread, I also moved the workload of this, as well as the decoding, to a separate thread. As the work was no longer associated with the WebView, I also moved the code into the main Activity source.

Finally, I am intercepting in the WebView any links that the user may click on, and sending them through the same processing, to ensure that the decoding will always occur.

2. CacheManager.getCacheFile(imgUrl) appears to work correctly on all versions of Android, however, I discovered that my physical devices did not always appear to have all images stored in the cache. On the emulator, the cache hit-rate is generally 100%, whereas on my phone and tablet, I was seeing a hit-rate of closer to 70-80%, with a subset of images not being found in the cache. This prevented successful decoding.

To resolve this, and also to avoid the dependence on a deprecated API, the code will now check if the image can be found in the cache, and if not, it will download the headers (only) of the image via TCP/IP.

This is not ideal as it means that we may effectively download some image headers twice, once to display it in the WebView, and once if they are then not found in the cache. However, I have not been able to determine a method to prevent this, and this solution works reliably.

3. Android 2.2 and possibly early versions of 2.3 appear to have an issue in their usage of Matcher.find(). After calling Matcher.find(int) with a starting offset, calling Matcher.find() subsequently should continue to search through the input data from the position of the last match. However, it appears that this does not occur, and while Matcher.find(int) does find the first match after the offset supplied, the first subsequent call to Matcher.find() starts at the beginning of the input data. Subsequent calls will continue through the data set, but this means that the data is incorrectly sorted, and will also pick up unwanted src elements.

To resolve this, I have altered it so that we call String.substring on the source data to prior to passing it to the Matcher, preventing the need to pass in an offset.

4. It was not obvious to me on the first execution of the application as to whether a message had been decoded, and if so, what it was. By putting the message in the activity title, it appeared initially as if this was the title of the webpage. I have left this behaviour unchanged, however, I have also added a Toast that appears on screen when a message is decoded, as a simple measure to make the application more user-friendly.

To conclude, I have tested these changes on both my Android devices and a variety of Android emulators from 2.2 to 4.0 and believe that it works correctly on all of them.