Aggregator v2.1

Two requested features landed in this new release:

  • The ability to use the volume buttons to navigate between items
  • The possibility to control the feed items limit per feed



Aggregator v2.0

From now on Aggregator can crunch also Atom feeds! Starting with this release any feed (RSS/Atom) should be supported.


The most requested feature was finally added to Aggregator: import. Feeds can be imported from Google Reader OPML files and Aggregator's own OPML files. The import can be partial in that you can select what feeds will be imported. To make selection easier, one can invert the selection using the provided menu option.


Aggregator can now export its own feeds too. The export can be done to an existing file (*.xml or *.opml) or to a newly created file.


To make the application more appealing I also added the feed's icon to the title bar.


NOTE: With great power comes great responsibility. Importing feeds from Google Reader is a nice thing to have, but use it wisely! With each new feed which is updated regularly in the background, the phone's battery will last less.


Aggregator v1.6

Version 1.6 brings colors to your Unread items screen.
The Feed preferences screen has a new option: Item color. Use it to set custom colors for your feeds.


Aggregator v1.5

Version 1.5 brings feed item sharing and weekly feed update interval.


Aggregator v1.4

What's new?
  • Improved HTTPS support: added option to declare a secure feed as trusted, if there are problems with the security certificates
  • Improved feed auto-discovery: faster discovery with less memory usage
  • Smaller package size
  • Fixed "New Feed" activity behavior on device rotation



Aggregator v1.2

Prior to this version, if you had many feed items (2000+ in my case), the item lists required some time for loading the content before appearing on the screen.
Now the activities appear instant and while the content is still loading a progress view is displayed. Also, to improve the loading time, the storage has been redesigned.

So this release is about speed and responsiveness!

Important: If you upgrade from a prior version, the first run can take some time while upgrading the storage. It all depends on how many feed items you have.


Aggregator v1.1

New features:
  • New 'Unread items' activity
  • Configurable notification sound


Feedback is always welcomed!

Aggregator v1.0

Version 1.0 is finally out!

The embedded viewer suffered the most important changes since version 0.9:
  • the item title and date are embedded now at the top of the item content
  • navigation buttons have been included for walking the feed up and down
  • the item read state is represented by a toggle button


Since this application has to refresh its database at scheduled times, it comes in handy to have a way to see if the selected update interval is optimal.
For this case, the feed update monitor can be helpful. If activated, you get a clickable history graph of the last feed updates at the top of the items list.



Feedback is always welcomed!

Aggregator v0.9

New features:
  • improved feed auto discovery (using TagSoup)
  • compression support for HTTP requests
  • notification and feed items limit preferences
  • menu option to show read items for a feed

Aggregator v0.8

New features:
  • feeds auto discovery
  • new option to open feed items directly in the browser
  • shorter connection timeouts for background updates
  • redesigned feed properties activity
  • simpler error messages

Aggregator Filters

One of Aggregator's main features is the ability to filter feed items.

Feed filters allow you to read only the feed items that you are interested in.

You can change the feed filter mode using the <Filter Mode> menu option.
change filter mode
Feed filters are a set of rules that are applied on each feed item. You can use feed filters to show or hide feed items.
From the example above, to hide all the movie trailer items, you select <Show unmatched items> option and create a filter by long pressing any movie trailer item.
create filter
More filter rules can be added by following the same steps.

To view all filters for a feed you must open the filter manager.
open filter manager

Aggregator v0.7

Aggregator is a feed aggregator with filtering support.

Version 0.7 brings:
  • RSS 2.0 support
  • Background feed updates
  • Feed filters
  • Android 1.6+ support

RON Exchange Rates v3.8

At last, the application has been translated to Romanian. :-)
The currencies have translations for German and French too, but I still need to ask my friends for help with the rest of the application.

Other notable changes to the application:
  • updated the tabs to look better on Gingerbread
  • fixed application crash when the user clicked the history while still loading

RON Exchange Rates v3.7

These days I had some free time to work on my hobby application again.

Thanks to the new error reporting feature in the Android Market, I got the chance to fix 3 bugs. Although the error console doesn't give as much information I would like to have about the devices on which the error occurred it is still a very welcomed feature. Thanks Google!

Besides bug fixes, I decided to reenable the landscape mode for the currencies lists and converter. This should be a good thing especially for the users that are interested in acquiring a device like Acer beTouch E130.

Under the hood now the application makes use now of compression for loading the rates from the server to minimize the time the radio is used. This is a hint I learned from the Google IO Android sessions that should improve battery life.

For the next release I'm thinking on adding some translations. Currently only English is supported, but I'm planning to add Romanian and German. I also accept other language suggestions.

That's all for now.

RON Exchange Rates v3.6

While using the converter I found out that having the favorites on top of the currencies picker improves the usability.

The widgets got some attention too:
  • new look
  • values for HUF, JPY and KRW are now divided by 100


RON Exchange Rates v3.5

This version changes the way the users get notified about application updates.
From now on, if a new version is available, the user will be presented with a notification in the status bar. If this is too noisy, it can be deactivated from within the application preferences.

The decision was made based on the poor update rate from the last release which fixed a severe bug.
There are two other reasons:
  • there are many users that use very old versions
  • I met some users that don't know how to update the application

The application has now a little over 1000 active users!
Thanks guys!

RON Exchange Rates v3.4

This version fixes a very severe bug that made the application use a lot of CPU even if the user didn't use it.


For the developers interested in how I found it:

The Battery use tool from Android 1.6 reported my application as having the CPU total around 13 minutes, which is a huge amount for an application that usually does only one update over a day, and that update is done in under one seconds.
First thing I did was to inspect the logcat. After staring at my process, for a very long while, I noticed that the GC was invoked every 4 minutes and reported collecting 13k objects. That was odd.
Next thing, I fired the DDMS tool and used the Allocation Tracker to collect data for one minute. It turned out the I had a message dispatcher that was not stopped after the activity was paused. Bam!


Thanks DDMS, you saved important battery life! :-)

RON Exchange Rates v3.3

This version fixes a bug that made the application update the rates two times in case of manual refresh or in case of device reboot.

Besides the bugfix there's also a small enhancement. The application now listens to connectivity changes only if an update failed because there was no connectivity. This feature was introduced to improve the battery life, since less executed tasks means longer battery life.

The update is available on the Market.

RON Exchange Rates v3.2

After I read the comments where the users complained about the missing values in the new history activity, I had no other choice but to add them back.
So this new version is about the history values:
  • use the touchscreen, the DPAD or the trackball to walk through the history values
  • min and max values are now placed at the bottom of the screen
  • mean (average) and median values are also visible for the users that need them

Go and grab it from the Market using this link.

RON Exchange Rates v3.0

After almost 4 months, a new update is available on the market (install link).
The new version has a brand new user interface with a bunch of new features:
  • tabbed interface
  • detailed currency names
  • favorite currencies
  • redesigned history activity
  • redesigned converter activity
  • configurable default actions for lists and widgets

The product page was updated too.

This time I asked a friend to help me with the user interface and the website. Without his help these wouldn't have looked this good. Thanks Mr. Designer! ;-)

HTC Tattoo Skin

I use this skin to test my apps with it.
It gives a better view on how the app would look on a device with this screen size.

Download link: htc-tattoo-skin.zip
htc-tattoo-screenshot

Nexus One Skin

A friend of mine asked for this one.
Feel free to download it: nexus-one-skin.zip
nexus-one

RON Exchange Rates v2.2

A new update is available on the market (install link).
This version comes with:
  • support for different screen resolutions (Donut)
  • removed error notifications caused by a missing internet connection
  • history caching

Send SMS using an Intent

I know this is a common topic but this solution actually worked for me.
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.putExtra("address", "XXXXXXXXXX"); // phone number
    intent.putExtra("sms_body", "..."); // message
    intent.setType("vnd.android-dir/mms-sms");
    startActivity(intent);
It's a nice thing when you have access to source code. I'm talking about the Mms.app in this case. ;-)

RON Exchange Rates v2.1

Initially I thought I would be the only user for this application. It turns out that I was wrong. And because of this I just had to improve it.

Some of the highlights of this new version:
  • enhanced client-server transport
  • first-time-use downloads the currency list faster
  • the update is always done in the background
  • history activity with progress monitor
  • new feature: currency converter based on the current values

If you are interested in the RON currency give it a try: install link

RON Exchange Rates

My first free application: RON Exchange Rates

Compact Android Emulator Skin

Since I don't have two displays I find it hard to monitor the logs or debug the application while using the emulator. The reason for this is that the emulator skins require too much display space. I created an emulator skin that is just a little taller than the HVGA resolution. If you have the same problem you can use this skin too: download

Samsung i7500 Skin

Now I'm not sure for which phone should I wait! :D Feel free to download the skin: download

The Friends List

Sometimes you need to manage a list of friends inside your Android application. In my case the friends list is a list of contacts entries. Using a contacts entry as a friend is a good idea for your application because:
  • the user has to use a well known activity (the Edit Contact activity) to edit the friend's contact details
  • you don't have to write the code for that part :)
I use a table called friends that is kept in-sync with content://contacts/people so that it always contains an entry for each contact.
public final class FriendsColumns implements BaseColumns {
  public static final String PERSON_ID = "person";
  public static final String IS_FRIEND = "is_friend";

  // cached details from contacts
  public static final String DISPLAY_NAME = "display_name";

  // additional application-related columns
}
The column is_friend is a boolean column that marks the contact as a friend. The column display_name is filled with the contact's display name while synchronizing the table. It's purpose is only to remove the need for additional queries while rendering the list activity. For synchronization I created service that runs in a background thread and makes use of the CursorJoiner class.
  Cursor peopleCursor = contentResolver.query(Contacts.People.CONTENT_URI,
      new String[] {Contacts.People._ID, Contacts.People.DISPLAY_NAME},
      null,
      null,
      Contacts.People._ID);
  Cursor friendsCursor = contentResolver.query(Friends.CONTENT_URI,
      new String[] {Friends._ID, Friends.PERSON_ID, Friends.DISPLAY_NAME},
      null,
      null,
      Friends.PERSON_ID);

  CursorJoiner joiner = new CursorJoiner(peopleCursor,
      new String[] {Contacts.People._ID},
      friendsCursor,
      new String[] {Friends.PERSON_ID});
  Uri friendUri;
  for (CursorJoiner.Result result : joiner) {
    switch (result) {
    case LEFT:
      ContentValues insertValues = new ContentValues();
      insertValues.put(Friends.PERSON_ID, peopleCursor.getLong(0));
      insertValues.put(Friends.IS_FRIEND, 0); // false
      insertValues.put(Friends.DISPLAY_NAME, peopleCursor.getString(1));
      contentResolver.insert(Friends.CONTENT_URI, insertValues);
      break;
    case RIGHT:
      friendUri = ContentUris.withAppendedId(Friends.CONTENT_URI,
          friendsCursor.getLong(0));
      contentResolver.delete(friendUri, null, null);
      break;
    case BOTH:
      ContentValues updateValues = new ContentValues();
      updateValues.put(Friends.DISPLAY_NAME, peopleCursor.getString(1));
      friendUri = ContentUris.withAppendedId(Friends.CONTENT_URI,
          friendsCursor.getLong(0));
      contentResolver.update(friendUri, updateValues, null, null);
      break;
    }
  }
            
  friendsCursor.close();
  peopleCursor.close();
The synchronization service is started when the friends list activity is created and when the contents of content://contacts/people changed.
public void onCreate(Bundle savedInstanceState) {
  // ...

  synchronizeFriendsWithContacts();
  ContentObserver contentObserver = new ContentObserver(null) {
    @Override
    public void onChange(boolean selfChange) {
      synchronizeFriendsWithContacts();
    }
  }
  getContentResolver().registerContentObserver(Contacts.People.CONTENT_URI,
      true,
      contentObserver);

  // ...
}

private void synchronizeFriendsWithContacts() {
  startService(new Intent(this, FriendsSynchronizer.class));
}
By using this approach I achieved:
  • great performance in rendering the list activity, because of the local copies from contacts
  • when adding a new friend to the list I already have a list of remaining contacts, by using is_friend as false
  • removing a friend from the list is done by just setting is_friend to false
  • when the user removes a contact the friends list is automaticaly cleaned too
  • I don't need to write a new activity that edits the friend's contact details :)

Black Magic Skin

After some Gimp-ing I managed to make also a black skin. You can download this one too. Mandatory screenshot:

HTC Magic Skin

This will be my next phone... Because I like it so much, I created this android skin to feel much better while developing on the emulator.

This skin is available for download.

What other better way to demonstrate the skin than using some screenshots?

Emulator screenshot:



Phone buttons: