Android’s event design sucks

11 March 2010 Tags  , ,

While delving further into Android, I’ve been creating a “hello world” type of app – its not as complex as what MahTweetsMobile will be, but it is encompassing a lot of different elements (custom ListAdapter, SQLite for persistent storage, different types of menus, loading external intents, etc).

One “difficult” element has been events. I say “difficult” because by design, its freaking nuts.

Scenario

I’ve got a custom ListViewAdapter, for my custom list elements, where the ListView items include a checkbox. This checkbox is to indicate the status of the items (for reference, its a shopping list app, you tick the checkboxes to show which items you’ve bought while shopping, the items then go grey in colour).

device

I wanted to add a “long press” context menu so that you could easily bring up a menu (with options such as Edit Item or Delete Item)

The Problem

Normally when “attaching” event listeners with ListViews, you use setOnCreateContextMenuListener on the ListView itself. You then override your Activity’s onContextItemSelected, figure out what menu button was pressed as well as what item it was pressed on.

ListView x = (ListView)findViewById(R.id.ListView01);
x.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
{
    public void onCreateContextMenu(ContextMenu contextMenu, View view,
ContextMenuInfo arg2)
    {
        contextMenu.add(0,CMENU_DELETE, 0, "Delete Item");
    }
});

public boolean onContextItemSelected(MenuItem item)
{
    AdapterContextMenuInfo menuInfo =
    (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
    switch (item.getItemId())
    {
        case CMENU_DELETE:
//Use menuInfo.position along with the adapter.getItem
//ie Product p = (Product)adapter.getItem(menuInfo.position);
            return true;
    }

    return true;
}

As you can see, its ugly code, but it works. Sort of. The problem was the checkboxes.

As soon as you add checkboxes to the individual items view, any listener created on the ListView never fires – the CheckBox swallows the event!

The Apparent Solution

Apparently this is a known bug (or more accurately, this is by design!). The solution is to set the event handlers on the rows themselves; inside the custom ListAdapter, when you’re inflating the various UI elements – look at my previous post on Custom ListAdapter, it’s under the getView method – on that “rowLayout” use the same setOnCreateContextMenuListener as the code used on ListView above, except only apply it to the individual row’s.

That would be fine if you didn’t care which item was pressed. That’s right, the cast to AdapterContextMenuInfo of item.getMenuInfo() in your Activity’s (yes, your activity has to override this, nowhere else works. argh!) onContextItemSelected always returns null because item.getMenuInfo() is always null.

The Actual Solution

I have no idea how I stumbled across this solution – I think I was in the process of undo-ing lines of code to try and figure out “where I’d gone wrong”.

Fact: To get the event to fire with checkboxes you need it to be set on the rowLayout.

Fact: To get menuInfo to be anything other than null (ie, tell you where it came from), you need it set on the ListView

Solution? Combine them. Wait, what? Two event listeners to get them to work? Yup.

On the rowLayout, set the listener:

rowLayout.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
{
    public void onCreateContextMenu(ContextMenu contextMenu, View view,

ContextMenuInfo arg2)
        {

        }
});

Notice the lack of code inside the onCreateContextMenu? Well, any ContextMenu items added inside this method won’t have AdapterContextMenuInfo – so don’t set anything, no menus will appear.

Now also set the adapter on the ListView using the code above.

Now it all works. WTF doesn’t begin to describe this.


No Comments
 

Android Dev: Custom ListAdapter

11 March 2010 Tags  ,

Disclaimer: This post presumes you’ve setup the Android SDK and Eclipse. If not, check out the Android Developer Guide

Some of the Android developer documents seem great, but in general there seems to be a lacking of documentation/examples – while the Java language is giving me no problems, how to do things with the Android API can be a bit of a nightmare to figure out.

It is possibly because Android is relatively new or because I’m used to MSDN which is a fantastic resource. Regardless, I started to want to develop MahTweetsMobile for Android and was having difficulty in ‘binding’ a ‘view’ to a list of elements, ala WPF/XAML’s DataTemplates.

It turns out its not as magical as what WPF is and requires manual binding, but its not impossible.

The View

To get a list to display anything other than just a string, you need to define your own view in either XML or code-behind. I find XML to be a little nicer, and its easier to update.

In Eclipse (I’m sure it’ll work in other IDE’s too, but this is what I’m using), you can create a new view by navigating to res –> layout, right clicking on the folder and selecting New –> Other, then from the popup select Android –> Android XML File

image

Make sure in the next dialog you select the Layout resource type, and give the file a name like "tweetview.xml" (all in lower case, as java/ADK will complain otherwise).

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget32"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<TableLayout
android:id="@+id/widget33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TableRow
android:id="@+id/widget35"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageButton
android:id="@+id/imgbtnAvatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</ImageButton>
<LinearLayout
android:id="@+id/widget39"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
>
</TextView>
<TextView
android:id="@+id/txtTweet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
>
</TextView>
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>

The Model

Just a simple class to hold our data,

package mahapps.MahTweets;

import java.util.Date;

public class Tweet {
    public int ID;
    public String Name;
    public String Text;
    public Date Timestamp;

    public int getID()
    {
        return this.ID;
    }

    public String getName()
    {
        return this.Name;
    }

    public String getText()
    {
        return this.Text;
    }

    public Tweet()
    {

    }
}

The Custom ListAdapter

This is the "heavy lifting" code – this is what "binds" a Tweet object to the TweetView.

package mahapps.MahTweets;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import java.util.*;

public class TweetAdapter extends BaseAdapter
{
    private List<Tweet> elements;
    private Context c;

    public TweetAdapter(Context c, List<Tweet> Tweets)
    {
        this.elements = Tweets;
        this.c = c;
    }
    public int getCount() {

        return elements.size();
    }

    public Object getItem(int position) {

        return elements.get(position);
    }

    public long getItemId(int id) {

        return id;
    }

    public void Remove(int id)
    {
        notifyDataSetChanged();
    }
    public View getView(int position, View convertView, ViewGroup parent)
    {

        LinearLayout rowLayout;
        Tweet t = elements.get(position);

        if (convertView == null)
        {
            rowLayout = (LinearLayout)LayoutInflater.from(c).inflate
                      (R.layout.TweetListView, parent, false);
           TextView tv = (TextView)rowLayout.findViewById(R.id.txtName);
           tv.setText(t.getText());

           //...
           //and so on for all the properties/UI elements
           //...

        } else {
            rowLayout = (RelativeLayout)convertView;
        }
        return rowLayout;
    }
}

 

You can then use this in your main Activity:

ListView x = (ListView)findViewById(R.id.ListView01);
x.setAdapter(new TweetAdapter(this, MyListOfTweets));

If you’re using a ListActivity, you’d just set that Activity’s adapter.

Your ListView items should then appear in more detail!

image


1 Comment
 

Geosense For Windows for devs

1 March 2010 Tags  , , , , ,

logo

Now that Rafael Rivera and Long Zheng have launched Geosense For Windows (or you can see Long’s post on it), I can happily brag how MahTweets has supported this since before they started working on it.

Geosense and MahTweets both use the Windows 7 Location and Sensor Platform – Geosense being the provider, MahTweet being the consumer. We supported it in MahTweets to geotag tweets and Flickr photos, in the hope that one day Microsoft or the hardware partners would be kind enough to consider Australia a real country and finally release some relevant hardware to the platform here. So far that hasn’t happened, which is where Geosense steps in.

Geosense with .NET

Geosense by itself doesn’t really do anything terribly exciting to the end user – it’s what Geosense enables for developers that is awesome. Location based services and games are primarily on phones only as it can be a hassle for the user to manually enter their location all the time – now it’s dead easy to bring those services and games to the desktop through rich clients.

To start with, grab the Sensor and Location .NET Interop Sample Library.

Below is an abridged version of the MahTweets GlobalPosition class file (it does some other stuff for other platforms that don’t have the sensor API’s, but that’s just a matter of people manually setting their location).

using Windows7.Location;
public class Location
{
    public String City { get; set; }
    public String Country { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

public static class GlobalPosition
{
    private static LatLongLocationProvider _provider;
    private static CivicAddressLocationProvider _civicprovider;
    private static bool _loadproviderthrowsexception = false;
    private const uint DEFAULT_REPORT_INTERVAL = 0;

    public static Location GetLocation()
    {
        Location l = new Location();

        try
        {
            if (_loadproviderthrowsexception)
            {
                return null;
            }

            if (_provider == null)
            {
                _provider = new LatLongLocationProvider(DEFAULT_REPORT_INTERVAL);
                _civicprovider = new CivicAddressLocationProvider(DEFAULT_REPORT_INTERVAL);
            }
            var y = _civicprovider.GetReport() as CivicAddressLocationReport;

            l.City = y.City;
            l.Country = y.CountryOrRegion;

            var x = _provider.GetReport() as LatLongLocationReport;
            l.Latitude = x.Latitude;
            l.Longitude = x.Longitude;
            return l;
        }
        catch (Exception ex)
        {
            return null;
        }

    }
}

Easy. The code speaks for itself – create a LocationProvider, query it to get the Latitude/Longitude. The rest is up to you.

Bonus Points

And if you’re a Powershell junkie, the following works too

[Reflection.Assembly]::LoadFile("<absolute location to dll>\Windows7.SensorAndLocation.dll")
$provider = new-object Windows7.Location.LatLongLocationProvider(0)
$position = $provider.GetReport()
$position.Latitude
$position.Longitude

1 Comment
 

Android: ListView Divider

26 February 2010 Tags  , ,

Disclaimer: I’m new to Android, I could be doing this all wrong. If I am, please comment and correct me.

Programming for Android is an interesting experience, coming from a .NET/C# background. I’ve done plenty of Java before in Uni and disliked it, but that was before I started playing with WPF.

Like WPF, Android’s UI is created using XML based documents, but unlike WPF, there aren’t any nice WYSIWYG builders. And most of the time it seems you need a combination of code behind and XML to get what you want for the UI, which can get a bit frustrating.

device_border

The divider between the items in this particular app is more annoying than it is useful, so I wanted to get rid of it. I was initially looking for separator or border, but the name is divider, and it has two properties.To set the divider between the ListItems to "nothing", you have two options. The first is in Java,

ListView x = (ListView)findViewById(R.id.ListView01);
x.setDivider(null);
x.setDividerHeight(0);

The alternative is to set it in XML, but in this case its more of a hack than the above of turning it ‘off’.

<ListView
android:id="@+id/ListView01"
android:background="#ffffff"
android:dividerHeight="0px"
android:divider="#ffffff" />

Even though the dividerHeight is set to 0 (0px, 0dp, whatever, the results were the same), a black line was still visible. The best solution is to set the colour (the divider value) to the same as your background. Using a gradient or image as the background? Set it in the code behind.

device_noborder


Comments Off
 

Sour side of Android/Google ID

25 February 2010 Tags  ,

Google products and services range from ‘awesome’ down to ‘wtf’ (*cough*Orkut*cough*), and their single signon/identification system ("Google Account") sits somewhere between the two.

On Android, just about everything is tied to a Google account. No big deal, I use Google Apps 4 Domains (GAFD) and I’ve used an email address associated with that to create a GoogleID which I use for Google Reader and other products.

To be honest, I was a little confused initially when the newly created GAFD account didn’t also create a GoogleID, but no big deal, I created my own. As far as I know, everything has worked – I even have a Google Checkout account. Even on the Android everything was working great, syncing contacts/email/calendar/etc, all was swell – until it got to the Market.

Using a GAFD based GoogleID  doesn’t let you purchase apps. You can see the ‘buy’ button, but when you go to buy, it’ll go through an infinite loop of asking for a Google Account.

Midway through 2009, a Google employee responded to a help thread

At the moment, Google Apps accounts may not be used for Google Checkout transactions, so Android Market requires the additional login to a Gmail account that is used for payments. However, this doesn’t mean that users will need to wipe their phones. The rest of the phone itself is still tied to the primary account that was signed in at start-up; in your case, the Google Apps account.

They acknowledge the problem, and surely would have fixed it by now in 2010, right? Wrong. The user in that particular thread bought a Nexus One through his GAFD based account with Google Checkout, so it’s good enough to buy a phone, but not a $0.99 app? Great.

Sorry to hear you’re having trouble purchasing apps. It sounds as if you’re logged in with a Google Apps account. When prompted to enter the Checkout account, please be sure to enter a non-Google Apps account to ensure that the purchases can go through. Let us know if you’re had success purchasing since your post.

Hopefully this will help somebody else, but the only solution is to also add a @Gmail account. And even then, you better hope your carrier doesn’t block App purchases (like say.. Optus do)


Comments Off
 

Hello, Milestone

22 February 2010 Tags  ,

Again, thanks to Will I’m now on my second Android phone, this time the flagship Android phone from Motorola – the Milestone (the GSM version of the Droid).

The quality of the photos of the device are a little so so – I’m fighting off sinusitis and bronchitis at the moment, so I just don’t care.

IMG_4377 

The Good

I think the design is one of those "love or hate" designs – it has rather striking straight lights and "sharp" corners, unlike most phones these days. It’s weightier than it probably needs to be, but that gives it an incredibly solid feel to it.

There is a lot to like about this phone, however there are two stand out features (for me)

  • I feel the need, the need for..
    Speed. This thing is fast. The difference between the speed of this phone and all others I’ve had/used before is impressive. While ~50mhz slower than the iPhone, or ~450mhz slower than the Nexus One’s 1ghz Snapdragon processor, the Milestone has a dedicated GPU. It gets shit done.

  • The Screen
    The screen specs are 3.7", 854 x 480px, TFT LCD, 16M colours.

    Yes, it drains the battery, but damn it looks good. I was a little concerned thinking that all the text would be tiny compared to the Dream (480 x 320 – same as the iPhone), but for the most part it just makes text so much clearer and easier to read.

    IMG_4376 

    Apparently the Nexus One screen (which has the slightly lower resolution of 800 x 480) is even better than the Milestone, which is scary awesome.

The Bad

Not everything is perfect on the Milestone, however. These complaints however, are (mostly) me nitpicking as much as possible.

  • The Keyboard
    See below in the comparison against the Dream for details, but the keyboard sucks. Still better than onscreen however.

  • MicroSD Slot
    The MicroSD slot is unfortunately impossible to get to without removing the battery. This is annoying because it somewhat defeats the obvious argument against internal-only storage of "you can have multiple SD cards and change whenever you like"

  • The Camera
    Don’t get me wrong, a 5mpx + Dual LED flash is neat. It takes good enough photos and video. For the sensor the size it is, 5mpx is overkill and creates some extra ISO noise but again, the photo quality is good enough.

    The problem I have with the (still) camera is the desire to use the flash in every situation – that is, every time I’ve tried to take a photo, it’ll use the flash if ‘auto-flash’ is enabled.

    Below, on the left is flash disabled, and on the right with auto-flash enabled. The irony is is, apart from the shot without the flash having better/more accurate colours, the flash actually make the image blur!

2010-02-22 15.05.232010-02-22 15.04.57 

Against the HTC Dream

The obvious comparison for me is between the Dream and Milestone, but mostly it should be considered an unfair comparison. For starters, the Dream was released in October 2008 whereas the Droid/Milestone in November 2009, and while the G1 wasn’t considered the lowest end in its day, it was never a real "premium" phone, which the Milestone clearly is.

Specification wise, nearly everything is better – faster CPU, higher res screen, more onboard flash, better camera, better Bluetooth support, the list goes on. However it is interesting to note that the Milestone doesn’t win in all categories.

Keyboard
Like the Dream, the Milestone is a slider with a qwerty keyboard. However unlike the Dream, the Milestones keys don’t have a gap between each key, are far flatter, and have less "travel".
The key advantage physical keyboards have over onscreen keyboards is the tactile response, whether it is being able to tell where one key ends/starts because of the key separation or by having to push the key down (rather than float over it).

IMG_4380

Apart from the less than ideal keys, the keyboard layout itself is a little funny. Instead of a five row key layout, they’ve gone for four which results in requiring alt to be pressed to enter a number. Although not as big a problem as the keys themselves, it is still a little frustrating.

Without a doubt, the Dream’s keyboard is just simply better.

It is interesting that the lower end Motorola Devour coming out seems to have a far better keyboard (Motorola promoting the raised keys)

Hardware Buttons
While the Milestone is not devoid of hardware buttons, Motorola’s choice of input is a little… lacking? Two (fairly standard) buttons are missing ("accept call" and "end call"), and unlike the Dream (and many Blackberrys) the scroller is gone in favour of a D-Pad which is hidden unless you slide out the keyboard.

Build Quality
There is no comparison here, and this is part of what I meant by the Dream not being a premium phone – the Milestone is just so solidly built with far better finish. The best example I can think of is the sliding mechanism – on the Dream it’ll rattle if the phone vibrates (call/notification/etc), whereas the Milestone is just solid.

Android 2.x

Apart from neat hardware, the other thing that the Milestone is rocking is Android 2.0.1, and what a difference it makes. Apart from everything seeming so much smoother and faster, Exchange support is built in! There are lots of improvements, but to be honest, I’ve barely scratched the surface of Android 1.6 let alone 2.0!

Google have a fairly detailed list of highlights for Android 2.0

I think the Contacts API is interesting, it allows multiple data stores for a single contact, so you could sync Facebook contacts to Gmail contacts. The Facebook app doesn’t work 100% for the Milestone (does for Droid/Nexus One) just yet, but it looks interesting. As does the possibility of extending this with Twitter/MahTweets Mobile.


1 Comment
 

Android Convert

19 January 2010 Tags  ,

Thanks to Will, I’ve now got an Android phone. The HTC Dream/Android Developer Phone 1 to be exact.

IMG_4237

I’ve had my HTC p3600i for almost two years now; I wrote that review not long after I bought the device, and it wasn’t long after it that the flaws started to show. As I did mention, browsing was useless with PocketIE, but over time the device just became less and less stable. In the last two or three months, the phone has insisted that its roaming unless I reboot it – then it’ll work for about 15-20minutes.

The developer experience for Windows Mobile 6.0 (and presumably 6.1 & 6.5) was also a nightmare. I once started looking at creating a Twitter client for it, and I discovered that to get TextWrapping on a TextBox (under .NET CF), you had to override the Draw method of the Textbox. Already I’ve created more for Android than I did for Windows Mobile, and it’s still at the proof of concept stage! (More on that in a later post)

I’m really enjoying the relative responsiveness of the Dream/Android, as well as much nicer UI. Having a physical keyboard again is awesome, I don’t think I could go back to an all touchscreen phone. A usable browser is also a nice change – I can finally do net banking on my phone, should I need to.

That’s not to say Android or the Dream are flawless.

  • Battery life sucks,
     
  • I’ve had more than a fair share of various parts of Android (such as the Home screen) lock up,
     
  • Android 1.6 has no Exchange support (although this is in 2/2.1, it’ll be awhile – if ever – before the Dream gets the upgrade because of the relatively small partition for the OS not enough RAM – thanks for the clarification Bck),
     
  • Many applications (including the “Google Experience” apps) default to notifications/always running/syncing requiring disabling the settings.Gmail, despite turned off under Settings –> Data Synchronisation –> Auto-sync (and Auto-sync turned off completely) always seems to sync as soon as Background Data is enabled, so I have to leave that off, which then disables the Market!Disabling Background Data warns/informs that disabling it will save power and data, but some applications require it and still use the connection!
     
  • While the UI is pretty good, a lot of it is incredibly unintuitive. Some of the submenus in Settings have additional menu (activated by pressing the Menu button), but there is no visual indicator nor do all of the submenus respond to it.

Comments Off
 

MahTweets: Columns not saving?

19 January 2010 Tags  ,

With each new version of MahTweets – even the sub-releases – many people are having columns not saving correctly.

Disclaimer: This is entirely my fault.

The Fix

Long story cut short, the quickest way to fix this is to delete all of your columns, recreate them, and then quit. They should then reappear on next launch.

If that doesn’t work, you can remove all of your accounts, columns, etc, and start from scratch, but it could give the same problem. The best way would be to delete your config file and start from scratch. That can currently be found in

C:\Users\<YourUserName>\AppData\Local\Apps\2.0\Data\<SomeHash>\<AnotherHash>\
maht..tion_<YetAnotherHash>\Data\2.7.4.529

Mine is

C:\Users\Paul\AppData\Local\Apps\2.0\Data\5B03WGLL.0H0\ODJ8MMQ8.3WX\
maht..tion_0000000000000000_0002.0007_342b7e02bb86691e\Data\2.7.4.529

Delete the user.config file and it should be fine until the next update. It’s not ideal, I know, but we are working on a solution, which will also result in the config file being moved to another location.

The Explanation

We know what the problem is, sort of. Columns are made up of many “UpdateTypes”, such as “Normal”, “Mentions”, “Direct Messages”. Every one you have selected is written to the settings file on close, under Filters (Filters –> FilterList –> StreamList –> FilterStream). Below is an example

<FilterStream>
    <IsIncluded>Include</IsIncluded>
    <Protocol>statusnet</Protocol>
    <AccountName>aeoth</AccountName>
    <Color>
        <A>0</A>
        <R>0</R>
        <G>0</G>
        <B>0</B>
        <ScA>0</ScA>
        <ScR>0</ScR>
        <ScG>0</ScG>
        <ScB>0</ScB>
    </Color>
    <UpdateTypeString>MahTweets2.IdenticaPlugin.MentionUpdate, MahTweets2.IdenticaPlugin,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</UpdateTypeString>
</FilterStream>

Although it’s a little hard to see, I’ve placed emphasis on the Version number. With each new version, that changes, so currently it will have 2.7.4.529 (for those playing at home, 529 is the Subversion commit number associated with that release). However, if you’ve upgraded from 2.7.3, MahTweets will go looking for that version, and isn’t able to find it.

As I’ve said, we are working on a solution, but its not here just yet.


1 Comment
 

MahTweets 2.7 Released!

16 January 2010 Tags  , ,

On Wednesday night, we pushed out another version of MahTweets, version 2.7. It’s been a long time between releases (3 months!) but a huge amount of work has gone into it.

New Features

  • Autocomplete Everywhere
    In previous versions we didn’t have autocomplete for contact names. Now we do. And its everywhere you can type!
  • Yammer Plugin
    Fairly basic at the moment, but we will get it up to "Twitter level" of support in the next version. Currently you can view/send and downloading attachments.
  • Plurk Plugin

  • Ping.fm Plugin
    No media ‘pings’ yet, but that’ll come soon – still beat Seesmic to it! ;)
  • Bit.ly Plugin
    We couldn’t support bit.ly in previous versions due to how IUrlShortener plugins worked, but now they can store credentials much like any other plugin.
  • Geotagging for Flickr & Twitter (both viewing and sending geotagged tweets)
  • Searching
    We now have the ISearchProvider interface, which lets IMicroblogs (aka, connection plugins like Twitter) provide a way to search.

    At the moment went have "regular" Twitter search and streaming Twitter search. Although not entirely certain, I’m fairly confident to say we’re the first or one of the first full feature Twitter clients with streaming search support!

    Streaming search maintains a constant connection to twitter, but you get results in real time. How fast? In most tests, you get the tweet roughly the same time it appears in the web interface for the person tweeting!

    Down the track we’ll be adding Yammer and Plurk ISearchProviders, perhaps even Facebook.

  • Local Searching
  • Read/Unread tracking
    This is optional, but you can have all updates marked as unread as they come in. Click on the ‘unread’ banner (or really any of update except the text) to mark it read, or the new ‘Mark all read’ button (the big tick on the side)
  • Profile Columns
    Although only supported by the Twitter plugin in this version, MahTweets can now show additional information about a particular contact inside MahTweets, instead of having to go out to the browser.

    We’re looking at making this extensible so ‘information’ can be pulled from places like Twadges/etc, once we find the right API’s.

Improvements

  • Twitter support
    MahTweets now supports more of the recent twitter features such as:
    • geotagging,
    • lists,
    • block&report as spam,
    • "new style" retweets
  • Filtering
    Our filtering was previously pretty good. Now its pretty awesome. Tri-state filtering means you can do nothing, include or exclude contacts or streams ("streams" are types of updates, ‘mentions’ or ‘direct messages’) from a column.
  • UX
    This version started as a big UX/UI overhaul. The key improvements are less WPF blurriness (mostly caused by drop shadows), a "smaller"/less space wasting update template, clearer/nicer looking icons, far more intuitive settings/setup window and a few other niceties.
  • Multi-parent behaviour
    This problem is almost exclusive to MahTweets, and we’ve mostly solved it. Most Twitter clients that support multiple accounts dont support multiple accounts in a single column. Well, since MahTweets does support this, the problem is that what happens when TwitterAccountA and TwitterAccountB are both following TwitterUserC?

    Do you double up the Tweet from C so it appears once for A and once for B? Do you make just a single tweet available to whoever got there first? Or do you make some sort of uber tweet which is for both A and B once they’ve both updated?

    We’ve chosen the latter option, which creates a drop down box when you go to reply, giving you a list of accounts to reply from:

    image

    That part we’ve solved, and it works great. The part we haven’t entirely solved is filtering. If the tweet comes in first from A but is a mention for B, it is marked as a mention for B, but the UI doesn’t reflect this (ie, no colour change, won’t always jump to the right column) until the UI is forced to update. Sometimes this doesn’t happen unless you toggle edit mode on the appropriate columns!

    It’s complex and a unique problem, but we’ll get there eventually.

  • Better memory usage
    WPF can be a bit of a beast to work with for small memory usage, but we’re finally getting it down to a more respectable figure. It’ll vary with how many accounts you have setup, how many columns you have, and if you clear all streams or not on a regular basis, but we’ve seen 5%-50% less memory usage!

There have also been a huge assortment of bugfixes, too many to list.

MahTweets Website

The MahTweets website has also undergone a huge overhaul!

image

Hopefully in the near future we’ll add some videos showing off some of our somewhat more hidden features, as well as fleshing out the Features, Developers and the return of the Community Plugins pages.

Future

So what does the future hold for MahTweets? Apart from a few bug fix releases, we’ll be releasing a MahTweets Developer Toolkit as well as reenabling community plugins – this will all happen under "2.7". For the next major version (2.8), we’ve not nailed down what extra features we want. However, we’ll hope to have

  • Video uploading (Vimeo, Facebook, Flickr, Viddler, YouTube)
  • More plugins for Url shortening and Status Handling
  • Synchronising settings between computers

There is also the strong possibility that we’ll look into creating MahTweets for Android, now that I have a HTC Dream (thanks Will!)


2 Comments
 

Comments disabled…

23 December 2009

Comments are now disabled due to the incredible spam comment increase since upgrading to Wordpress 2.9.

I’ll look at moving to other blog software by the end of the year, and enable comments again.


Comments Off