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
Aggregator v1.5
Aggregator v1.4
Aggregator v1.2
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
Aggregator v1.0
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
Aggregator v0.8
Aggregator Filters
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.
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.
More filter rules can be added by following the same steps.
To view all filters for a feed you must open the filter manager.
Aggregator v0.7
RON Exchange Rates v3.8
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
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
RON Exchange Rates v3.5
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
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
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
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
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
It gives a better view on how the app would look on a device with this screen size.
Download link: htc-tattoo-skin.zip
Nexus One Skin
RON Exchange Rates v2.2
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
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
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
Compact Android Emulator Skin
Samsung i7500 Skin
The Friends List
- 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 :)
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
HTC Magic Skin
This skin is available for download.
What other better way to demonstrate the skin than using some screenshots?
Emulator screenshot:
Phone buttons: