Showing posts with label Release. Show all posts
Showing posts with label Release. Show all posts

Tuesday, March 5, 2013

Weekend hack: viewing markdown attachments in GMail on Android

Recently I wanted to open a markdown email attachment on my Nexus 4, but after clicking "readme.md" instead of seeing the file contents I saw this message:


I downloaded few apps from Google Play, but the message was still appearing. The same applications could open a local markdown file, so I went back to GMail app to download the attachment, but another unpleasant surprise awaited me:


There is no "overflow" menu on the attachment (see the screenshot below), which means I couldn't access the "Save" option, so I could open it as a local file.


At this point I was:
  1. Pissed off, because, cmon, GMail is probably the most used app working on the mature operating system and I can't download a fucking file with it.
  2. Curious, because it looked liked an interesting issue with GMail app.
The first clue was in the GMail logs in the logcat:
03-04 21:12:50.477: W/Gmail(13823): Unable to find supporting activity. mime-type: application/octet-stream, uri: content://gmail-ls/jerzy.chalupski@gmail.com/messages/121/attachments/0.1/BEST/false, normalized mime-type: application/octet-stream normalized uri: content://gmail-ls/jerzy.chalupski@gmail.com/messages/121/attachments/0.1/BEST/false
Note the Uri: there is no file name and no file extension, and the mime-type is a generic application/octet-stream (most likely because the "md" extension is not present in libcore.net.MimeUtils). The markdown viewers/editors I downloaded probably register intent filters for specific file extensions, so they don't know they could handle this file. It sucks big time, because it means that the applications for viewing files with non-standard extensions would have to register for application/octet-stream mime-type, and even though they handle very specific file types they all appear in the app chooser dialog for many different file types, which defeats the whole purpose of Android Intent system and reduces the UX.

My first idea was to create an "GMail Attachment Forwarder" app which registers for any content from GMail, gets the attachment mail by querying the DISPLAY_NAME column on the Uri supplied by GMail, save this information along with original GMail Uri in public ContentProvider, and start the activity using Uri exposed by my ContentProvider which does contain attachment name. This ContentProvider should also forward any action to original GMail Uri.

Unfortunatly I was foiled by the ContentProvider's permissions systems: the Activity in my app was temporarily granted with the read permissions for GMail's ContentProvider, but this permissions did not extend to my ContentProvider and the app I was forwarding the attachment to failed because of the insufficient permissions.

This approach didn't work, but having a catch-all handler for GMail attachments unlocked the attachment actions. I also noticed that when the attachment is downloaded, the GMail uses a slightly different intent:
03-04 23:05:34.005: I/ActivityManager(526): START u0 {act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/readme-1.md typ=application/octet-stream flg=0x80001 cmp=com.chalup.markdownviewer/.MainActivity} from pid 3063
This led me to plan B: have an app which enables the attachment download and use other apps to open downloaded attachments. I renamed my app to GMail Attachment Unlocker, cleared the manifest and source folder leaving only a single, automatically closing activity:

<application
  android:allowBackup="true"
  android:label="@string/app_name"
  android:theme="@android:style/Theme.NoDisplay" >
  <activity
    android:name="com.chalup.gmailattachmentunlocker.MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
      <action android:name="android.intent.action.VIEW" />

      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />

      <data
        android:host="gmail-ls"
        android:mimeType="*/*"
        android:scheme="content" />
    </intent-filter>
  </activity>
</application>
public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    finish();
  }

}

The full source code is available on my Github (althought there really isn't much more than what is posted here). In the end I also ended up writing my own markdown viewer (source code in another repo on my Github), because none of the apps I have downloaded properly rendered <pre> tags (hint: you have to use WebView.loadDataWithBaseUrl instead of WebView.loadData).

Friday, March 23, 2012

Word Judge for Symbian available in Nokia Store

Today I have finally pushed both versions of Word Judge through Nokia Store QA. The version with an english dictionary was available for over the week now, but I had to submit the polish version few times until it passed the Nokia tests.

Anyways, the applications are available for free in Nokia Store. Here's the link for english version:


And for polish version (might not be available in all countries - I had to add some restrictions to pass QA process):


Stay tuned for posts about development of Symbian version and enjoy your Scrabble games.

Saturday, March 10, 2012

Introducing: Word Judge

I enjoy playing Scrabble and other word games like WordSquared of Word with Friends and I think I'm quite good at them for an amateur - my average score in 2-player Scrabble game is around 330 points. I do not have a tournament aspirations, because memorizing word lists or best stems doesn't fit my definition of fun, but I'm always in for a casual game.

The only thing that bothers me during these casual games are occasional, but unpleasant arguments - how do you spell given word or what is some 3 letter combination an obscure word or gibberish. Polish language have both declension and conjugation with a lot of irregularities, so there are plenty of things to argue about.

Most of the times we sort things out simply by checking the word spelling on the Internet, but there are situations when you can't do that, for example when you're abroad and don't have wi-fi access and roaming data access price is extraorbitant, or you're in the middle of the outback with no connectivity whatsoever. Without that possibility you have to find a compromise, and boy, that's not easy when you challenge someones 7-letter word on two triple-word bonus tiles.

That's why I created Word Judge - an ultimate way to settle all word-related disputes. The application contains full dictionary of valid words and short word list with definitions. Dictionary is shipped with the application, so you don't need internet connectivity to check if the word can be used in a word game. Currently the application is available only for Android devices, but I'm going to release Symbian (and maybe Harmattan?) version soon.



Unlike many other word game helpers, Word Judge doesn't contain anagrammer tool. It's not an oversight, it didn't add it for two reasons. First of all I don't think that such functionality should be bundled with the application, which is basically a dictionary. You use a dictionary to check the spelling, not to cheat. The second reason is more prosaic - I don't like the UI of any anagrammer tools I found. It's usually a jumble of checkboxes and radio buttons and two fields for board and rack tiles. Even if you figure out what all those controls do, these tools don't really solve the problem, which is finding the best move. It's not an easy problem, even if you find a convenient way to import current game state to the application (AR maybe?). It's certainly a good idea for a separate application, but not for a part of a dictionary app.

I released one version of my application for every supported language (currently only English and Polish). I considered setting up a service with downloadable dictionaries, but I decided against it, because it would needlessly complicate the application and I think that using multiple dictionaries is quite rare use case. Let me know if I'm wrong, I might change my mind. Also, if you like the idea of my application and want me to create a Word Judge for your language, send me an email. Unfortunately, since the app is free I cannot offer you anything more than a mention in application description and "About" window.

I was sure from the start that I won't charge money for this app, but I pondered for quite a long time if I should use ads. On one hand they are visually displeasing and take scarce screen real estate. On the other hand, I want to see for myself how much revenue they generate - the testimonies of other developers vary from ecstatic to disappointed. In the end I decided to add a small banner as an experiment.

This post is already getting too long, so let me just mention that in the next week or so I'm going to write about stuff I learned while working on this application. I hope you'll enjoy the reading. Meanwhile, dust of your Scrabble board, download my app and enjoy an argument-free game!

Friday, January 20, 2012

Introducing: Nu, Pogodi!



"Nu, pogodi!" is the first application I've published in Nokia Store (or any other app store, in fact). It's a remake of a classic handheld console game I used to play in my childhood: you had to place a wolf with a basket under one of four roosts to catch the eggs rolling from them. Despite the extreme simplicity and the obvious flaw in the game plot (namely: what the hell does the wolf need the eggs for?) the game was quite addictive and I spent many hours listening to the hypnotizing ticking of the falling eggs (if you played this game you know what I'm talking about).

The handheld console I based my game on is actually a Russian clone of "Egg" game from Nintendo's "Game & Watch" game series. The main difference is the graphics - instead of fox and hen the Russian clone featured the Wolf and the Hare from a "Nu, pogodi!" cartoon - hence the name of the game.


At the beginning of 2011 I wanted to check out the Qt Quick, which was advertised by Nokia as the best thing since sliced bread. I never liked the go-through-a-boring-tutorials way of learning new things, so I started writing UI for a simple game instead. Few weeks later Nokia announced Qt Quick Competition - an event promoting Qt Quick introduced in Qt 4.7. I've entered the competition with the early version of my game under the name "Nu, Pagadi!" (which is, as I learned later, incorrect - apparently in Russian sometimes you write an 'o', but pronounce it as 'a'), which didn't won me anything, but at least I had a motivation to work on the game. In accordance with the competition rules I've published my code under OSS license and forgot about the whole deal.

In November 2011 I've stumbled upon a "Soviet Eggs" game in Nokia Store. It seems that some company forked my competition entry, added a splash screen and the menu and charged 2 euros for it. I've watched the gameplay videos on YouTube, and thought I can do much better version than them. I polished my game, added sound effects, better looking menu and new game mode which resembles the gameplay of original game much more than the one included in the competition entry. All those changes took me about one week worth of evenings and one weekend. Subsequentially I've screwed up testing, published to Nokia Store a game which silently crashed on 90% of the phones, fixed the problem, and then I screwed up again, this time when publishing the update.

Despite the initial issues the game reached top 10 bestseller list in two weeks and stayed there ever since. Try it yourself!