Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

package com.tomgibara.android.camera;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;

/**
 * A CameraSource implementation that obtains its bitmaps via an HTTP request
 * to a URL.
 *
 * @author Tom Gibara
 *
 */


public class HttpCamera implements CameraSource {

       
        private static final int CONNECT_TIMEOUT = 1000;
        private static final int SOCKET_TIMEOUT = 1000;
       
        private final String url;
        private final Rect bounds;
        private final boolean preserveAspectRatio;
        private final Paint paint = new Paint();

        public HttpCamera(String url, int width, int height, boolean preserveAspectRatio) {
                this.url = url;
                bounds = new Rect(0, 0, width, height);
                this.preserveAspectRatio = preserveAspectRatio;
               
                paint.setFilterBitmap(true);
                paint.setAntiAlias(true);
        }
       
        @Override
        public int getWidth() {
                return bounds.right;
        }
       
        @Override
        public int getHeight() {
                return bounds.bottom;
        }
       
        @Override
        public boolean open() {
                /* nothing to do */
                return true;
        }

        @Override
        public boolean capture(Canvas canvas) {
                if (canvas == null) throw new IllegalArgumentException("null canvas");
                try {
                        Bitmap bitmap = null;
                        InputStream in = null;
                        int response = -1;
                        try {
                                //we use URLConnection because it's anticipated that it is lighter-weight than HttpClient
                                //NOTE: At this time, neither properly support connect timeouts
                                //as a consequence, this implementation will hang on a failure to connect
                                URL url = new URL(this.url);
                                URLConnection conn = url.openConnection();
                                if (!(conn instanceof HttpURLConnection)) throw new IOException("Not an HTTP connection.");
                                HttpURLConnection httpConn = (HttpURLConnection) conn;
                                httpConn.setAllowUserInteraction(false);
                                httpConn.setConnectTimeout(CONNECT_TIMEOUT);
                                httpConn.setReadTimeout(SOCKET_TIMEOUT);
                                httpConn.setInstanceFollowRedirects(true);
                                httpConn.setRequestMethod("GET");
                                httpConn.connect();
                                response = httpConn.getResponseCode();
                                if (response == HttpURLConnection.HTTP_OK) {
                                        in = httpConn.getInputStream();
                                        bitmap = BitmapFactory.decodeStream(in);
                                }
                        } finally {
                                if (in != null) try {
                                        in.close();
                                } catch (IOException e) {
                                        /* ignore */
                                }
                        }
                       
                        if (bitmap == null) throw new IOException("Response Code: " + response);

                        //render it to canvas, scaling if necessary
                        if (
                                        bounds.right == bitmap.width() &&
                                        bounds.bottom == bitmap.height()) {
                                canvas.drawBitmap(bitmap, 0, 0, null);
                        } else {
                                Rect dest;
                                if (preserveAspectRatio) {
                                        dest = new Rect(bounds);
                                        dest.bottom = bitmap.height() * bounds.right / bitmap.width();
                                        dest.offset(0, (bounds.bottom - dest.bottom)/2);
                                } else {
                                        dest = bounds;
                                }
                                canvas.drawBitmap(bitmap, null, dest, paint);
                        }

                } catch (RuntimeException e) {
                        Log.i(LOG_TAG, "Failed to obtain image over network", e);
                        return false;
                } catch (IOException e) {
                        Log.i(LOG_TAG, "Failed to obtain image over network", e);
                        return false;
                }
                return true;
        }

        @Override
        public void close() {
                /* nothing to do */
        }

}