06 December, 2010

Сокращаем ссылки на андроиде

Вступление
Встала передо мной задача - сокращать ссылки перед тем, как отправлять их в Twitter. Для решения этой задачи я решил использовать bit.ly, благо, их API внятный и простой.
Программируем!
Решение нарисовалось в виде следующего класса:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;


/**
 * Helper class to work with bitly.
 *
 * @author Oleg Atamanenko
 * @since 06-Dec-2010 12:49:36
 */
public class Bitly {

    private static final String TAG = "Bitly";

    private static final String SHORTEN = "/v3/shorten";
    private static final String API_URL = "api.bit.ly";
    private static final String RESPONSE_FORMAT = "json";

    private String username;
    private String apiKey;


    public Bitly(String username, String apiKey) {
        this.username = username;
        this.apiKey = apiKey;
    }

    public String shorten(String longUrl) throws BitlyException {
        DefaultHttpClient httpClient = new DefaultHttpClient();

        try {
            List params = new ArrayList();
            params.add(new BasicNameValuePair("login", username));
            params.add(new BasicNameValuePair("apiKey", apiKey));
            params.add(new BasicNameValuePair("longUrl", longUrl));
            params.add(new BasicNameValuePair("format", RESPONSE_FORMAT));


            URI uri = URIUtils.createURI("http", API_URL, -1, SHORTEN, URLEncodedUtils.format(params, "UTF-8"), null);
            HttpGet request = new HttpGet(uri);

            Log.d(TAG, "Sending request: " + request.getURI());

            HttpResponse httpResponse = httpClient.execute(request);

            HttpEntity httpEntity = httpResponse.getEntity();
            String response = EntityUtils.toString(httpEntity);
            Log.i(TAG, "Bitly response is: " + response);
            httpResponse.getEntity().consumeContent();

            JSONObject jsonResponse = new JSONObject(response);

            checkForExceptions(jsonResponse);

            JSONObject data = jsonResponse.getJSONObject("data");
            return data.getString("url");

        } catch (ClientProtocolException e) {
            throw new BitlyException(e);
        } catch (IOException e) {
            throw new BitlyException(e);
        } catch (JSONException e) {
            throw new BitlyException(e);
        } catch (URISyntaxException e) {
            throw new BitlyException(e);
        }
    }

    private void checkForExceptions(JSONObject jsonResponse) throws JSONException, BitlyException {
        int statusCode = jsonResponse.getInt("status_code");
        if (statusCode != 200) {
            String message = jsonResponse.getString("status_txt");
            throw new BitlyException(message);
        }
    }

}
Конструктор класс принимает на вход следующие параметры: Полная документация к Bit.ly API расположена на отдельном проекте в Google Code
Использование
Единственный метод, реализованный сейчас - это метод shorten(). На вход требуется подать полную ссылку longUrl, на выходе получается укороченная версия ссылки, либо кидается исключение с сообщением от bit.ly API.
Пример вызова
Bitly bitly = new Bitly(BITLY_USERNAME, BITLY_API_KEY);
String shortLink = bitly.shorten(link);

Дальнейшие улучшения
Если перед вами стоит задача быстренько сократить ссылку - то вышеприведённого кода достаточно. Но если вам нужно полноценное решение, со всеми возможностями bit.ly - то посмотрите в сторону bitlyj. Правда, я не уверен, что оно взведётся под андроидом.