org.pixmob.feedme.net.NetworkClient.java Source code

Java tutorial

Introduction

Here is the source code for org.pixmob.feedme.net.NetworkClient.java

Source

/*
 * Copyright (C) 2011 Pixmob (http://github.com/pixmob)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.pixmob.feedme.net;

import static org.pixmob.feedme.Constants.SHARED_PREFERENCES;
import static org.pixmob.feedme.Constants.SP_KEY_AUTH_TOKEN;
import static org.pixmob.feedme.Constants.SP_KEY_NUMBER_OF_ITEMS;
import static org.pixmob.feedme.Constants.TAG;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.pixmob.feedme.feature.Features;
import org.pixmob.feedme.feature.SharedPreferencesSaverFeature;

import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Build;
import android.util.Log;

/**
 * Execute network requests.
 * @author Pixmob
 */
public class NetworkClient {
    private static final String SP_KEY_CONTINUATION = "continuation";
    private static String userAgent;
    private static String clientId;
    private final DefaultHttpClient client;
    private final SharedPreferences prefs;
    private final SharedPreferences.Editor prefsEditor;
    private final EntriesParser parser;

    public NetworkClient(final Context context) {
        if (userAgent == null) {
            userAgent = generateUserAgent(context);
        }
        if (clientId == null) {
            clientId = generateClientId(context);
        }

        client = SSLEnabledHttpClient.newInstance(userAgent);
        prefs = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
        prefsEditor = prefs.edit();

        parser = new EntriesParser();
    }

    /**
     * Generate an Http User-Agent.
     */
    private static final String generateUserAgent(Context context) {
        String applicationVersion = null;
        try {
            applicationVersion = context.getPackageManager().getPackageInfo(context.getPackageName(),
                    0).versionName;
        } catch (NameNotFoundException e) {
            applicationVersion = "0.0.0";
        }
        return context.getApplicationInfo().name + "/" + applicationVersion + " (" + Build.MANUFACTURER + " "
                + Build.MODEL + " with Android " + Build.VERSION.RELEASE + "/" + Build.VERSION.SDK_INT + ")";
    }

    /**
     * Generate a Google Reader client ID.
     */
    private static final String generateClientId(Context context) {
        String applicationVersion = null;
        try {
            applicationVersion = context.getPackageManager().getPackageInfo(context.getPackageName(),
                    0).versionName;
        } catch (NameNotFoundException e) {
            applicationVersion = "0.0.0";
        }
        return Uri.encode("feedme_" + applicationVersion);
    }

    private String getAuthToken() {
        return prefs.getString(SP_KEY_AUTH_TOKEN, null);
    }

    public void close() {
        client.getConnectionManager().shutdown();
    }

    private void prepareRequest(HttpUriRequest req) throws NetworkClientException {
        final String authToken = getAuthToken();
        if (authToken == null) {
            throw new NetworkClientException("Missing authentication token", req.getURI().toString());
        }
        req.setHeader("Authorization", "GoogleLogin auth=" + authToken);
    }

    private String createServiceUri(String uri, Map<String, String> parameters) {
        final StringBuilder buf = new StringBuilder("http://www.google.com/reader");
        if (!uri.startsWith("/")) {
            buf.append('/');
        }
        buf.append(uri).append("?c=").append(clientId);

        if (parameters != null) {
            for (final Map.Entry<String, String> e : parameters.entrySet()) {
                buf.append('&').append(e.getKey()).append("=").append(e.getValue());
            }
        }
        return buf.toString();
    }

    public void downloadUnreadEntries(List<ContentValues> entries) throws IOException {
        final Map<String, String> params = new HashMap<String, String>(4);
        params.put("client", clientId);
        params.put("n", prefs.getString(SP_KEY_NUMBER_OF_ITEMS, "50"));
        params.put("ck", String.valueOf(System.currentTimeMillis()));

        final String continuation = prefs.getString(SP_KEY_CONTINUATION, null);
        if (continuation != null) {
            params.put("c", continuation);
        }

        final HttpGet req = new HttpGet(createServiceUri("/atom/user/-/state/com.google/reading-list", params));
        prepareRequest(req);

        Log.i(TAG, "Sending request for downloading entries: " + req.getURI().toASCIIString());

        final EntriesParser.Results parseResults = new EntriesParser.Results();
        parseResults.entries = entries;

        HttpResponse resp = null;
        FileOutputStream output = null;
        int statusCode = 0;
        try {
            resp = client.execute(req);
            final StatusLine statusLine = resp.getStatusLine();
            statusCode = statusLine.getStatusCode();

            Log.i(TAG, "Entries download status code: " + statusCode);

            if (statusCode != 200) {
                throw new IOException("Entries download error");
            }

            final HttpEntity entity = resp.getEntity();
            final InputStream input = entity.getContent();
            parser.parse(input, EntityUtils.getContentCharSet(entity), parseResults);

            prefsEditor.putString(SP_KEY_CONTINUATION, parseResults.continuation);
            Features.getFeature(SharedPreferencesSaverFeature.class).save(prefsEditor);
        } catch (IOException e) {
            throw new NetworkClientException("Failed to get unread entries", req.getURI().toString(), statusCode,
                    e);
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException ignore) {
                }
            }
            closeResources(req, resp);
        }
    }

    private static void closeResources(HttpUriRequest req, HttpResponse resp) {
        try {
            req.abort();
        } catch (UnsupportedOperationException ignore) {
        }
        final HttpEntity entity = resp != null ? resp.getEntity() : null;
        if (entity != null) {
            try {
                entity.consumeContent();
            } catch (IOException ignore) {
            }
        }
    }
}