com.thecorpora.qbo.androidapk.RESTClient.java Source code

Java tutorial

Introduction

Here is the source code for com.thecorpora.qbo.androidapk.RESTClient.java

Source

/*
* Software License Agreement (GPLv2 License)
* 
* Copyright (c) 2011 Thecorpora, S.L.
*
* This program is free software; you can redistribute it and/or 
* modify it under the terms of the GNU General Public License as 
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License 
* along with this program; if not, write to the Free Software 
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
* MA 02110-1301, USA.
*
* Author: Daniel Cuadrado Snchez <daniel.cuadrado@openqbo.com>
*/
package com.thecorpora.qbo.androidapk;

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 java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
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.cookie.Cookie;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

/**
 * 
 * This class is used for the comunication with the Server inside Qbo using HTTP protocol
 * 
 * @author Daniel Cuadrado Sanchez
 *
 */
public class RESTClient {

    private static final String PORT = "7070";

    private String cabecera = "http://", ip = "", port = "",

            URL_MOVE_BODY = "/teleoperation/move", URL_MOVE_HEAD = "/teleoperation/head",
            URL_SPEAK = "/teleoperation/speak", URL_MOUTH = "/teleoperation/changeMouth",

            quality = "50", widthImg = "240", heightImg = "180",

            URL_RIGHT_EYE = "/image/stream?topic=/stereo/right/image_raw&quality=" + quality + "&width=" + widthImg
                    + "&height=" + heightImg,
            URL_LEFT_EYE = "/image/stream?topic=/stereo/left/image_raw&quality=" + quality + "&width=" + widthImg
                    + "&height=" + heightImg,
            URL_MONOCULAR = "/image/stream?topic=/stereo/monocolular/image_raw&quality=" + quality + "&width="
                    + widthImg + "&height=" + heightImg,
            URL_STEREO_SELECTOR = "/image/stream?topic=/stereo/stereo_selector/image_raw&quality=" + quality
                    + "&width=" + widthImg + "&height=" + heightImg,
            URL_DISPARITY = "/image/stream?topic=/stereo/stereo_follower/disparity&quality=" + quality + "&width="
                    + widthImg + "&height=" + heightImg,
            URL_OBJ_TRACKING = "/image/stream?topic=/Qbo/ObjectTraking/Viewer&quality=" + quality + "&width="
                    + widthImg + "&height=" + heightImg,
            URL_FACE_DETECTOR = "/image/stream?topic=/qbo_face_tracking/viewer&quality=" + quality + "&width="
                    + widthImg + "&height=" + heightImg,
            URL_3D = "/image/stream?topic=/stereo_anaglyph&quality=" + quality + "&width=" + widthImg + "&height="
                    + heightImg,

            URL_faceTracking_ON = "/control/face_traking/start",
            URL_faceTracking_OFF = "/control/face_traking/stop", URL_3D_ONOFF = "/teleoperation/activate_3d",

            URL_LOGIN = "/auth/mobile_login",

            URL_IP4SIP = "/teleoperation/mobile_setIpSip", URL_GET_SIP_ID = "/teleoperation/mobile_getUserSipId",
            URL_GET_BOT_SIP_ID = "/teleoperation/mobile_getBotSipId",

            URL_END_CALL = "/teleoperation/mobile_endCall",

            URL_START_SIP_SERVER = "/teleoperation/mobile_startSIPServer",

            URL_STOP_SIP_SERVER = "/teleoperation/mobile_stopSIPServer",

            TAG = "AndroidQbo/REST";

    private Context ctx;

    Cookie cookie = null;

    public RESTClient(String ip, Context ctx) {
        this.ip = ip;
        this.port = PORT;
        this.ctx = ctx;

        //We check whether we have a cookie saved or not.
        String cookieFileName = "cookieFileName";
        SharedPreferences settings = ctx.getSharedPreferences(cookieFileName, 0);
        String cookieString = settings.getString("cookie", null);

        this.setCookie(cookieString);
    }

    /**
     * 
     * Tell the robot the linear and angular speed for its movement
     * 
     * @param x linear speed
     * @param y angular speed
     */
    public void post_moveBody(double x, double y) {
        String[] inputData = { "line", Double.toString(x), "angu", Double.toString(y) };
        REST_post(cabecera + ip + ":" + port + URL_MOVE_BODY, inputData);
    }

    /**
     * Tell the robot the pan and tilt position for its head movement. So far the pan and tilt speed is defined to 300
     * 
     * @param x pan position
     * @param y tilt position
     */
    public void post_moveHead(double x, double y) {
        String[] inputData = { "yaw", Double.toString(x), "pitch", Double.toString(y) };
        REST_post(cabecera + ip + ":" + port + URL_MOVE_HEAD, inputData);
    }

    /**
     * Tell the robot what it is going to say
     * 
     * @param sentence text to speak by the robot
     */
    public void post_say(String sentence) {
        String[] inputData = { "message", sentence };
        REST_post(cabecera + ip + ":" + port + URL_SPEAK, inputData);
    }

    /**
     * Tell the robot which mouth to put
     * 
     * @param mouth number of the mouth
     */
    public void post_mouth(int mouth) {
        String[] inputData = { "mouth", String.valueOf(mouth) };
        REST_post(cabecera + ip + ":" + port + URL_MOUTH, inputData);
    }

    /**
     * Tell the robot to activate the stereoscopy
     * 
     * @param activate a String with "on" to activate or "off" to deactivate
     */
    public void post_activate_3D(String activate) {
        String[] inputData = { "activate", activate };
        REST_post(cabecera + ip + ":" + port + URL_3D_ONOFF, inputData);
    }

    /**
     * 
     * We send the user name and password parameters to the robot.
     * 
     * We will get true if the access is allowed, false otherwise
     * 
     * @param userName user name
     * @param pwd password
     * @param aes_string string to encrypt userName and pwd
     * @return true if the access is allowed, false if not.
     */
    public int post_login(String userName, String pwd, String aes_string) {
        AESCipher aes = new AESCipher();

        byte[] bytesUserName = {};
        byte[] bytesPwd = {};
        try {

            bytesUserName = userName.getBytes("UTF-8");
            userName = aes.encrypt(bytesUserName, aes_string);

            bytesPwd = pwd.getBytes("UTF-8");
            pwd = aes.encrypt(bytesPwd, aes_string);

        } catch (UnsupportedEncodingException uee) {
            uee.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return REST_post(cabecera + ip + ":" + port + URL_LOGIN, userName, pwd);
    }

    /**
     * We give the IP to the robot
     * 
     * @param ip4Linphone The IP given by the user in the Login activity is sent to the robot in order to properly configurate Linphone
     */
    public int post_ip4sip(String ip4Linphone) {
        String[] inputData = { "ip", ip4Linphone };
        return REST_post(cabecera + ip + ":" + port + URL_IP4SIP, inputData);
    }

    /**
     * We get out user name created by the SIP server. 
     */
    public String getSipId() {
        return REST_get(cabecera + ip + ":" + port + URL_GET_SIP_ID);
    }

    /**
     * We get the Linphone bot user name, so we know who we have to call
     */
    public String getBotSipId() {
        return REST_get(cabecera + ip + ":" + port + URL_GET_BOT_SIP_ID);
    }

    /**
     * End call.
     */
    public String endCall() {
        return REST_get(cabecera + ip + ":" + port + URL_END_CALL);
    }

    /**
     * Start SIP Server
     */
    public int startSIPServer() {
        String[] inputData = { "ecoCancelation", "false" };
        return REST_post(cabecera + ip + ":" + port + URL_START_SIP_SERVER, inputData);
    }

    /**
     * Stop SIP Sever
     */
    public int stopSIPServer() {
        return REST_post(cabecera + ip + ":" + port + URL_STOP_SIP_SERVER, null);
    }

    public String getURL_IMG(int imageType) {

        switch (imageType) {
        case 0://left_eye
            return cabecera + ip + ":" + port + URL_LEFT_EYE;

        case 1://right eye      
            return cabecera + ip + ":" + port + URL_RIGHT_EYE;

        case 2://monocular         
            return cabecera + ip + ":" + port + URL_MONOCULAR;

        case 3://object_tracking         
            return cabecera + ip + ":" + port + URL_STEREO_SELECTOR;

        case 4://face_detector
            return cabecera + ip + ":" + port + URL_FACE_DETECTOR;

        case 5://disparity_image         
            return cabecera + ip + ":" + port + URL_DISPARITY;

        case 6://nearest_object_tracking         
            return cabecera + ip + ":" + port + URL_OBJ_TRACKING;

        case 7://three_d         
            return cabecera + ip + ":" + port + URL_3D;

        }
        return "";
    }

    public void stopVideo(String url) {
        url = url.replace("stream", "stop");
        REST_post(url, null);
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public void setCmdPort(String port) {
        this.port = port;
    }

    public void setImgPort(String port) {
        this.port = port;
    }

    public void setImgQuality(String quality) {
        URL_RIGHT_EYE = "/image/stream?topic=/stereo/right/image_raw&quality=" + quality + "&width=" + widthImg
                + "&height=" + heightImg;
        URL_LEFT_EYE = "/image/stream?topic=/stereo/left/image_raw&quality=" + quality + "&width=" + widthImg
                + "&height=" + heightImg;
        URL_MONOCULAR = "/image/stream?topic=/stereo/monocolular/image_raw&quality=" + quality + "&width="
                + widthImg + "&height=" + heightImg;
        URL_STEREO_SELECTOR = "/image/stream?topic=/stereo/stereo_selector/image_raw&quality=" + quality + "&width="
                + widthImg + "&height=" + heightImg;
        URL_DISPARITY = "/image/stream?topic=/stereo/stereo_follower/disparity&quality=" + quality + "&width="
                + widthImg + "&height=" + heightImg;
        URL_OBJ_TRACKING = "/image/stream?topic=/Qbo/ObjectTraking/Viewer&quality=" + quality + "&width=" + widthImg
                + "&height=" + heightImg;
        URL_FACE_DETECTOR = "/image/stream?topic=/qbo_face_tracking/viewer&quality=" + quality + "&width="
                + widthImg + "&height=" + heightImg;
        URL_3D = "/image/stream?topic=/stereo_anaglyph&quality=" + quality + "&width=" + widthImg + "&height="
                + heightImg;
    }

    ////////////////////////////////
    //           REST             //
    ////////////////////////////////
    public int REST_post(String path, String[] data) {
        try {
            if (hasCookie()) {

                HttpParams httpParams = new BasicHttpParams();
                httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
                DefaultHttpClient client = new DefaultHttpClient(httpParams);

                HttpPost post = new HttpPost(path);

                List params = new ArrayList();

                if (data != null) {
                    for (int i = 0; i <= data.length / 2; i = i + 2) {
                        params.add(new BasicNameValuePair(data[i], data[i + 1]));
                    }
                }

                UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params, HTTP.UTF_8);

                post.setEntity(ent);

                //COOKIE
                post.setHeader("Cookie", "session_id=" + cookie.getValue());

                ResponseHandler<String> responseHandler = new BasicResponseHandler();

                String responsePOST = client.execute(post, responseHandler);

            } else {
                Log.e(TAG, " You do not have the proper COOKIE therefor this acction can not be made");
                return -1;
            }

        } catch (Exception e) {
            Log.e(TAG, " Error while making a POST petition " + e);
            return -1;
        }

        return 0;

    }

    //POST to login and get the COOKIE
    private int REST_post(String path, String userName, String password) {
        try {
            HttpParams httpParams = new BasicHttpParams();
            httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

            // Set the timeout in milliseconds until a connection is established.
            // The default value is zero, that means the timeout is not used. 
            int timeoutConnection = 10000;
            HttpConnectionParams.setConnectionTimeout(httpParams, timeoutConnection);
            // Set the default socket timeout (SO_TIMEOUT) 
            // in milliseconds which is the timeout for waiting for data.
            int timeoutSocket = 10000;
            HttpConnectionParams.setSoTimeout(httpParams, timeoutSocket);

            DefaultHttpClient client = new DefaultHttpClient(httpParams);

            HttpPost post = new HttpPost(path);

            List params = new ArrayList();
            params.add(new BasicNameValuePair("username", userName));
            params.add(new BasicNameValuePair("password", password));

            UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params, HTTP.UTF_8);

            post.setEntity(ent);

            HttpResponse responsePOST = client.execute(post);

            HttpEntity resEntity = responsePOST.getEntity();

            String responseText = EntityUtils.toString(resEntity);

            if (responseText.equalsIgnoreCase("error")) {
                return -1;
            }
            ;

            if (resEntity != null) {
                resEntity.consumeContent();
            }

            System.out.println("Post logon cookies:");
            List<Cookie> cookies = client.getCookieStore().getCookies();
            if (cookies.isEmpty()) {
                Log.e(TAG, "No cookies where sent back from server");
                this.setCookie(null);
                return -1;

            } else {
                cookie = cookies.get(0);
                //Save cookie                      
                this.setCookie(cookie.getValue());
                return 0;

            }

        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    /*
     * Source: http://www.androidsnippets.com/retrieve-json-from-a-rest-web-service
     */
    public String REST_get(String url) {

        if (hasCookie()) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);
            httpget.setHeader("Cookie", "session_id=" + cookie.getValue());
            HttpResponse response;

            try {
                response = httpclient.execute(httpget);
                //            Log.i(TAG, "Status:[" + response.getStatusLine().toString() + "]");
                HttpEntity entity = response.getEntity();

                if (entity != null) {

                    InputStream instream = entity.getContent();
                    String result = convertStreamToString(instream);
                    //               Log.i(TAG, "Result of converstion: [" + result + "]");

                    instream.close();
                    return result;
                }
            } catch (ClientProtocolException e) {
                Log.e(TAG, "There was a protocol based error", e);
            } catch (IOException e) {
                Log.e(TAG, "There was an IO Stream related error", e);
            }
            return null;
        } else {
            return null;
        }
    }

    private static String convertStreamToString(InputStream is) {
        /*
         * 
         * Source: http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/
         * 
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    public boolean hasCookie() {
        if (cookie != null)
            return true;
        else
            return false;
    }

    public void setCookie(String value) {
        if (value != null) {
            saveSharePreferenceCookie(value);
            cookie = new BasicClientCookie("user", value);
        } else {
            removeCookie();
        }
    }

    public Cookie getCookie() {
        return cookie;
    }

    public void removeCookie() {
        cookie = null;
        this.saveSharePreferenceCookie(null);
    }

    private void saveSharePreferenceCookie(String value) {
        String cookieFileName = "cookieFileName";
        SharedPreferences settings = ctx.getSharedPreferences(cookieFileName, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("cookie", value);
        editor.commit();
    }
}