com.sachachua.quantified.client.NetworkUtilities.java Source code

Java tutorial

Introduction

Here is the source code for com.sachachua.quantified.client.NetworkUtilities.java

Source

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 com.sachachua.quantified.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

/**
 * Provides utility methods for communicating with the server.
 */
final public class NetworkUtilities {
    /** The tag used to log to adb console. */
    private static final String TAG = "NetworkUtilities";
    /** POST parameter name for the user's account name */
    public static final String PARAM_USERNAME = "username";
    /** POST parameter name for the user's password */
    public static final String PARAM_PASSWORD = "password";
    /** POST parameter name for the user's authentication token */
    public static final String PARAM_AUTH_TOKEN = "authtoken";
    /** POST parameter name for the client's last-known sync state */
    public static final String PARAM_SYNC_STATE = "syncstate";
    /** Timeout (in ms) we specify for each http request */
    public static final int HTTP_REQUEST_TIMEOUT_MS = 30 * 1000;
    /** Base URL for the v2 Sample Sync Service */
    public static final String BASE_URL = "http://quantifiedawesome.com";
    /** URI for authentication service */
    public static final String AUTH_URI = BASE_URL + "/auth";
    /** URI for sync service */
    public static final String SYNC_CONTACTS_URI = BASE_URL + "/sync";

    private NetworkUtilities() {
    }

    /**
     * Configures the httpClient to connect to the URL provided.
     */
    public static HttpClient getHttpClient() {
        HttpClient httpClient = new DefaultHttpClient();
        final HttpParams params = httpClient.getParams();
        HttpConnectionParams.setConnectionTimeout(params, HTTP_REQUEST_TIMEOUT_MS);
        HttpConnectionParams.setSoTimeout(params, HTTP_REQUEST_TIMEOUT_MS);
        ConnManagerParams.setTimeout(params, HTTP_REQUEST_TIMEOUT_MS);
        return httpClient;
    }

    /**
     * Connects to the SampleSync test server, authenticates the provided
     * username and password.
     *
     * @param username The server account username
     * @param password The server account password
     * @return String The authentication token returned by the server (or null)
     */
    public static String authenticate(String username, String password) {

        final HttpResponse resp;
        final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair(PARAM_USERNAME, username));
        params.add(new BasicNameValuePair(PARAM_PASSWORD, password));
        final HttpEntity entity;
        try {
            entity = new UrlEncodedFormEntity(params);
        } catch (final UnsupportedEncodingException e) {
            // this should never happen.
            throw new IllegalStateException(e);
        }
        Log.i(TAG, "Authenticating to: " + AUTH_URI);
        final HttpPost post = new HttpPost(AUTH_URI);
        post.addHeader(entity.getContentType());
        post.setEntity(entity);
        try {
            resp = getHttpClient().execute(post);
            String authToken = null;
            if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                InputStream istream = (resp.getEntity() != null) ? resp.getEntity().getContent() : null;
                if (istream != null) {
                    BufferedReader ireader = new BufferedReader(new InputStreamReader(istream));
                    authToken = ireader.readLine().trim();
                }
            }
            if ((authToken != null) && (authToken.length() > 0)) {
                Log.v(TAG, "Successful authentication");
                return authToken;
            } else {
                Log.e(TAG, "Error authenticating" + resp.getStatusLine());
                return null;
            }
        } catch (final IOException e) {
            Log.e(TAG, "IOException when getting authtoken", e);
            return null;
        } finally {
            Log.v(TAG, "getAuthtoken completing");
        }
    }

    /**
     * Perform 2-way sync with the server-side contacts. We send a request that
     * includes all the locally-dirty contacts so that the server can process
     * those changes, and we receive (and return) a list of contacts that were
     * updated on the server-side that need to be updated locally.
     *
     * @param account The account being synced
     * @param authtoken The authtoken stored in the AccountManager for this
     *            account
     * @param serverSyncState A token returned from the server on the last sync
     * @param dirtyContacts A list of the contacts to send to the server
     * @return A list of contacts that we need to update locally
     */
    /*public static List<RawContact> syncContacts(
        Account account, String authtoken, long serverSyncState, List<RawContact> dirtyContacts)
        throws JSONException, ParseException, IOException, AuthenticationException {
    // Convert our list of User objects into a list of JSONObject
    List<JSONObject> jsonContacts = new ArrayList<JSONObject>();
    for (RawContact rawContact : dirtyContacts) {
        jsonContacts.add(rawContact.toJSONObject());
    }
        
    // Create a special JSONArray of our JSON contacts
    JSONArray buffer = new JSONArray(jsonContacts);
        
    // Create an array that will hold the server-side contacts
    // that have been changed (returned by the server).
    final ArrayList<RawContact> serverDirtyList = new ArrayList<RawContact>();
        
    // Prepare our POST data
    final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair(PARAM_USERNAME, account.name));
    params.add(new BasicNameValuePair(PARAM_AUTH_TOKEN, authtoken));
    params.add(new BasicNameValuePair(PARAM_CONTACTS_DATA, buffer.toString()));
    if (serverSyncState > 0) {
        params.add(new BasicNameValuePair(PARAM_SYNC_STATE, Long.toString(serverSyncState)));
    }
    Log.i(TAG, params.toString());
    HttpEntity entity = new UrlEncodedFormEntity(params);
        
    // Send the updated friends data to the server
    Log.i(TAG, "Syncing to: " + SYNC_CONTACTS_URI);
    final HttpPost post = new HttpPost(SYNC_CONTACTS_URI);
    post.addHeader(entity.getContentType());
    post.setEntity(entity);
    final HttpResponse resp = getHttpClient().execute(post);
    final String response = EntityUtils.toString(resp.getEntity());
    if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        // Our request to the server was successful - so we assume
        // that they accepted all the changes we sent up, and
        // that the response includes the contacts that we need
        // to update on our side...
        final JSONArray serverContacts = new JSONArray(response);
        Log.d(TAG, response);
        for (int i = 0; i < serverContacts.length(); i++) {
            RawContact rawContact = RawContact.valueOf(serverContacts.getJSONObject(i));
            if (rawContact != null) {
                serverDirtyList.add(rawContact);
            }
        }
    } else {
        if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
            Log.e(TAG, "Authentication exception in sending dirty contacts");
            throw new AuthenticationException();
        } else {
            Log.e(TAG, "Server error in sending dirty contacts: " + resp.getStatusLine());
            throw new IOException();
        }
    }
        
    return serverDirtyList;
    }
        
    /**
     * Download the avatar image from the server.
     *
     * @param avatarUrl the URL pointing to the avatar image
     * @return a byte array with the raw JPEG avatar image
     */
    /*public static byte[] downloadAvatar(final String avatarUrl) {
    // If there is no avatar, we're done
    if (TextUtils.isEmpty(avatarUrl)) {
        return null;
    }
        
    try {
        Log.i(TAG, "Downloading avatar: " + avatarUrl);
        // Request the avatar image from the server, and create a bitmap
        // object from the stream we get back.
        URL url = new URL(avatarUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.connect();
        try {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            final Bitmap avatar = BitmapFactory.decodeStream(connection.getInputStream(),
                    null, options);
        
            // Take the image we received from the server, whatever format it
            // happens to be in, and convert it to a JPEG image. Note: we're
            // not resizing the avatar - we assume that the image we get from
            // the server is a reasonable size...
            Log.i(TAG, "Converting avatar to JPEG");
            ByteArrayOutputStream convertStream = new ByteArrayOutputStream(
                    avatar.getWidth() * avatar.getHeight() * 4);
            avatar.compress(Bitmap.CompressFormat.JPEG, 95, convertStream);
            convertStream.flush();
            convertStream.close();
            // On pre-Honeycomb systems, it's important to call recycle on bitmaps
            avatar.recycle();
            return convertStream.toByteArray();
        } finally {
            connection.disconnect();
        }
    } catch (MalformedURLException muex) {
        // A bad URL - nothing we can really do about it here...
        Log.e(TAG, "Malformed avatar URL: " + avatarUrl);
    } catch (IOException ioex) {
        // If we're unable to download the avatar, it's a bummer but not the
        // end of the world. We'll try to get it next time we sync.
        Log.e(TAG, "Failed to download user avatar: " + avatarUrl);
    }
    return null;
    }
    /**/

    public static String readStringFromURL(String url) {
        //initialize
        InputStream is = null;
        String result = "";

        //http post
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpGet httppost = new HttpGet(url);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();

        } catch (Exception e) {
            Log.e("log_tag", "Error in http connection " + e.toString());
        }

        //convert response to string
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            result = sb.toString();
        } catch (Exception e) {
            Log.e("log_tag", "Error converting result " + e.toString());
        }
        return result;
    }

    // http://mobile.dzone.com/news/android-tutorial-how-parse
    public static JSONObject readJSONfromURL(String url) {
        JSONObject jArray = null;
        //try parse the string to a JSON object
        try {
            String result = readStringFromURL(url);
            jArray = new JSONObject(result);
        } catch (JSONException e) {
            Log.e("log_tag", "Error parsing data " + e.toString());
        }

        return jArray;
    }

    public static JSONArray readJSONArrayfromURL(String url) {
        JSONArray jArray = null;
        //try parse the string to a JSON object
        try {
            String result = readStringFromURL(url);
            jArray = new JSONArray(result);
        } catch (JSONException e) {
            Log.e("log_tag", "Error parsing data " + e.toString());
        }

        return jArray;
    }
}