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 */ } }