I am writing an Android 1.5 application which starts just after boot-up. This is a Service
and should take a picture without preview. This app will log the ligh
Get this working first before trying to hide the preview.
SurfaceView
(pre-Android-4.0 compatibility) or SurfaceTexture
(Android 4+, can be made transparent)SurfaceView
's SurfaceHolder
(via getHolder()
) to report surfaceCreated()
or the TextureView
to report onSurfaceTextureAvailable
to its SurfaceTextureListener
before setting and initialising the preview.WindowManager
MATCH_PARENT
x MATCH_PARENT
for testing)View.VISIBLE
(which seems to be the default if you don't specify it)FLAG_HARDWARE_ACCELERATED
in the LayoutParams
if it's a TextureView
.takePicture
's JPEG callback since the documentation says the other callbacks aren't supported on all devicessurfaceCreated
/onSurfaceTextureAvailable
doesn't get called, the SurfaceView
/TextureView
probably isn't being displayed.takePicture
fails, first ensure the preview is working correctly. You can remove your takePicture
call and let the preview run to see if it displays on the screen.takePicture
so that the camera has time to adjust its exposure once the preview has started.Make the preview View
1x1 size to minimise its visibility (or try 8x16 for possibly more reliability)
new WindowManager.LayoutParams(1, 1, /*...*/)
Move the preview out of the centre to reduce its noticeability:
new WindowManager.LayoutParams(width, height,
Integer.MIN_VALUE, Integer.MIN_VALUE, /*...*/)
Make the preview transparent (only works for TextureView
)
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
width, height, /*...*/
PixelFormat.TRANSPARENT);
params.alpha = 0;
/** Takes a single photo on service start. */
public class PhotoTakingService extends Service {
@Override
public void onCreate() {
super.onCreate();
takePhoto(this);
}
@SuppressWarnings("deprecation")
private static void takePhoto(final Context context) {
final SurfaceView preview = new SurfaceView(context);
SurfaceHolder holder = preview.getHolder();
// deprecated setting, but required on Android versions prior to 3.0
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new Callback() {
@Override
//The preview must happen at or after this point or takePicture fails
public void surfaceCreated(SurfaceHolder holder) {
showMessage("Surface created");
Camera camera = null;
try {
camera = Camera.open();
showMessage("Opened camera");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
throw new RuntimeException(e);
}
camera.startPreview();
showMessage("Started preview");
camera.takePicture(null, null, new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
showMessage("Took picture");
camera.release();
}
});
} catch (Exception e) {
if (camera != null)
camera.release();
throw new RuntimeException(e);
}
}
@Override public void surfaceDestroyed(SurfaceHolder holder) {}
@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
});
WindowManager wm = (WindowManager)context
.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
1, 1, //Must be at least 1x1
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0,
//Don't know if this is a safe default
PixelFormat.UNKNOWN);
//Don't set the preview visibility to GONE or INVISIBLE
wm.addView(preview, params);
}
private static void showMessage(String message) {
Log.i("Camera", message);
}
@Override public IBinder onBind(Intent intent) { return null; }
}