Latest Tweets

 

The business model Twitter never had

It’s difficult not to interpret the latest Twitter API announcement by Ryan Sarver as anything other than a clear instruction that competition with Twitter’s client applications will not be tolerated. For me, the stand-out quote was:

More specifically, developers ask us if they should build client apps that mimic or reproduce the mainstream Twitter consumer client experience. The answer is no.

I personally think that this public statement has irrevocably set Twitter down an inferior path; what investor will now seriously fund third-party applications that augment Twitter? I’m not saying that this move will necessarily stop Twitter from being a successful company, but I do feel that its scope as a platform has been diminished.

I don’t think it ever needed to take this route. Here’s one business model I would have loved to see Twitter adopt…

  • Extend the Twitter APIs to include adverts with tweets.
  • Leave the display of adverts up to the client applications.
  • Impose terms and conditions on displaying the adverts (eg. that clients cannot include any other adverts or promotions, that they must not mislead users into clicking the ads, etc.)
  • Share the revenue generated from the adverts with the application developers.

This would have required extensive monitoring of third party applications (though ad networks already face similar challenges), but it seems like a ‘maximizing’ strategy to me: third-party clients continue to proliferate, have an incentive to increase user engagement and to generate revenue for Twitter.

Of course, it’s easy to comment from the sidelines.

A poor bit of user interface design in the twitter widget for android in an otherwise a well designed and intuitive application.

What do you think the “Update” button is going to do?

Submit the text in the “What’s Happening?” box?
Refresh the current tweets?
Something else…
Yes, it’s 3.

It can’t be 1. As android developers will understand, you can’t usefully put an editable text view into a widget (the Google Search is not a bona-fide widget). So the designers/developers have followed the pattern of showing the “Create Tweet” activity when the text view is clicked. This works really nicely.

And it isn’t 2 either. Even though the twitter website, and the rest of the android application, refer to the action as “Tweet”, the “Update” button does exactly the same thing here. It duplicates the action of clicking in the textbox. This is wrong on three counts:

The language is inconsistent with the rest of the application, for no benefit.
It reinforces the expectation that the text box can be typed-into, it can’t.
It robs the user of space to perform a useful action, like actually updating the tweet stream
What prompted me to post this is actually a second (and I feel more significant) issue with the app: there is no “About” screen, no information about how to contact the developer, not even any confirmation that it was developed or licenced by twitter.

I would have emailed my observations instead of posting them, but they weren’t courteous enough to provide their contact details.

A poor bit of user interface design in the twitter widget for android in an otherwise a well designed and intuitive application.

What do you think the “Update” button is going to do?

  1. Submit the text in the “What’s Happening?” box?
  2. Refresh the current tweets?
  3. Something else…

Yes, it’s 3.

It can’t be 1. As android developers will understand, you can’t usefully put an editable text view into a widget (the Google Search is not a bona-fide widget). So the designers/developers have followed the pattern of showing the “Create Tweet” activity when the text view is clicked. This works really nicely.

And it isn’t 2 either. Even though the twitter website, and the rest of the android application, refer to the action as “Tweet”, the “Update” button does exactly the same thing here. It duplicates the action of clicking in the textbox. This is wrong on three counts:

  1. The language is inconsistent with the rest of the application, for no benefit.
  2. It reinforces the expectation that the text box can be typed-into, it can’t.
  3. It robs the user of space to perform a useful action, like actually updating the tweet stream

What prompted me to post this is actually a second (and I feel more significant) issue with the app: there is no “About” screen, no information about how to contact the developer, not even any confirmation that it was developed or licenced by twitter.

I would have emailed my observations instead of posting them, but they weren’t courteous enough to provide their contact details.

Uploading Twitter profile images via Android

Last night I decided to knock out a quick app to test how straightforwardly one can upload twitter images. With the exception of one hiccup:

http://code.google.com/p/twitter-api/issues/detail?id=697

it went very smoothly.

Essentially you need to introduce two libraries into your project that are absent from Android:

  • httpmime.jar
  • apache-mime4j.jar

I used versions 4.0-beta2 and 0.5 respectively.

Here’s my very basic implementation:

//sample method for uploading a user profile image to twitter
int uploadImage(InputStream in, String type, String fileName, Credentials credentials) throws IOException {
    try {
        //convert the input stream into a byte array - this is just a convenient way
        InputStreamEntity ise = new InputStreamEntity(in, -1L);
        byte[] bytes = EntityUtils.toByteArray(ise);

        //establish the credentials
        DefaultHttpClient client = new DefaultHttpClient();
        client.getCredentialsProvider().setCredentials(new AuthScope("twitter.com", 80), credentials);

        //create the multipart entity 
        MultipartEntity entity = new MultipartEntity();
        ByteArrayBody body = new ByteArrayBody(bytes, type, fileName);
        entity.addPart("image", body);

        //assign the entity to the request and disable the Expect header
        //see http://code.google.com/p/twitter-api/issues/detail?id=697
        HttpPost request = new HttpPost("http://twitter.com/account/update_profile_image.xml");
        request.setEntity(entity);
        request.getParams().setBooleanParameter( "http.protocol.expect-continue", false ); 

        //execute the request and return the response
        HttpResponse response = null;
        try {
            response = client.execute(request);
        } finally {
            //exhaust the response
            if (response != null) {
                HttpEntity re = response.getEntity();
                if (re != null) re.consumeContent();
            }

        }
        return response.getStatusLine().getStatusCode();
    } finally {
        try {
            in.close();
        } catch (IOException e) {
            /* ignored */
        }
    }
}

I haven’t investigated properly, but disabling the “expect-continue” feature appears to cause the request entity to be read twice. So the method above depends on a helper class that provides a repeatable entity.

private class ByteArrayBody extends AbstractContentBody {

    private final byte[] bytes;
    private final String fileName;

    public ByteArrayBody(byte[] bytes, String mimeType, String fileName) {
        super(mimeType);
        this.bytes = bytes;
        this.fileName = fileName;
    }

    @Override
    public String getFilename() {
        return fileName;
    }

    @Override
    public void writeTo(OutputStream out, int mode) throws IOException, MimeException {
        out.write(bytes);
    }

    @Override
    public String getCharset() {
        return null;
    }

    @Override
    public long getContentLength() {
        return bytes.length;
    }

    @Override
    public String getTransferEncoding() {
        return MIME.ENC_BINARY;
    }

}

The Java code in this post is in the public domain.

Twitter API, what do you Expect?

I’ve bowed to the inevitable and now have a twitter account. Being on the geeky end of the human spectrum, the first thing I wanted to do was write a some Java code that will push new profile images.

I’m running along nicely, and the first problem I hit comes as I finish my coding and start testing. Twitter responds with:

The expectation given in the Expect request-header field could not be met by this server. The client sent Expect: 100-Continue but we only allow the 100-continue expectation

That such a widely used service can’t stick to one of the plainest elements of the HTTP 1.1 specification is depressing.

Comparison of expectation values is case-insensitive for unquoted tokens (including the 100-continue token), and is case-sensitive for quoted-string expectation-extensions.

But what is worse is that the Apache HTTP library I’m using doesn’t allow this header to be amended in any way — it gets magically added at the point at which the request is made so there’s no opportunity to remove it — and something as simple as this multipart image upload becomes a trial…