Reputation:
I am trying to create an android application that can capture image in the background once the service is started . I am able to capture it and save on sdcard but the image captured is bit dark and i am not able to trace the problem. What could be the possibilities?
Captured Image: https://i.sstatic.net/Xsc6Q.jpg
public class MyService extends Service {
Camera mCamera;
public String imageEncodeString,imageName;
public Bitmap bitmap;
public File file;
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if (data != null) {
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
if (bitmap != null) {
imageName = String.valueOf(System.currentTimeMillis() + ".jpg");
File basedir = new File(Environment.getExternalStorageDirectory() + "/dirr");
file = new File(Environment.getExternalStorageDirectory() + "/dirr" + File.separator + imageName);
if (!basedir.isDirectory()) {
basedir.mkdirs();
}
try {
file.createNewFile();
FileOutputStream otstream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG,100,otstream);
byte[] img =new byte[0];
otstream.write(img);
otstream.flush();
otstream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
mCamera.startPreview();
}
}
};
public MyService() {
}
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(MyService.this, "Starting Service...", Toast.LENGTH_SHORT).show();
Log.d("TAG", "======= service in onStartCommand");
if (checkCameraHardware(this)) {
mCamera = getCameraInstance();
if (mCamera != null) {
SurfaceView sv = new SurfaceView(this);
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(1, 1,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSPARENT);
params.alpha = 0;
SurfaceHolder sh = sv.getHolder();
sv.setZOrderOnTop(true);
sh.setFormat(PixelFormat.TRANSPARENT);
sh.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
mCamera.setParameters(parameters);
Camera.Parameters p = mCamera.getParameters();
List<Camera.Size> listSize;
listSize = p.getSupportedPreviewSizes();
Camera.Size mPreviewSize = listSize.get(2);
Log.v("TAG", "preview width = " + mPreviewSize.width
+ " preview height = " + mPreviewSize.height);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
listSize = p.getSupportedPictureSizes();
Camera.Size mPictureSize = listSize.get(2);
Log.v("TAG", "capture width = " + mPictureSize.width
+ " capture height = " + mPictureSize.height);
p.setPictureSize(mPictureSize.width, mPictureSize.height);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
// mCamera.startPreview();
// mCamera.takePicture(null, null, mPictureCallback); // used to takePicture.
// Log.d("TAG", "========= Capturing Started");
// mCamera.stopPreview();
// mCamera.release();
// Log.d("TAG", "========== Capturing finished.");
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
}
});
wm.addView(sv, params);
} else {
Log.d("TAG", "==== get Camera from service failed");
}
}else {
Log.d("TAG", "==== There is no camera hardware on device.");
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.d("TAG", "========= Capturing Started");
mCamera.startPreview();
mCamera.takePicture(null, null, mPictureCallback);
Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
Log.d("TAG", "========== Capturing finished.");
}
}, 5000);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
Toast.makeText(MyService.this, "Service Stopped...", Toast.LENGTH_SHORT).show();
}
public static boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Log.d("TAG", "Open camera failed: " + e);
}
return c;
}
}
Upvotes: 1
Views: 236
Reputation: 57203
I believe that takePicture() should be delayed a bit to let the camera adjust to lighting conditions after the preview starts.
How many hundreds of milliseconds you must wait depends on the device and on the lighting conditions. Unfortunately there is no callback to indicate that exposure/gain tuning is done, unlike focus.
On the second thought, successful onAutoFocus() may be a good indication that the camera is settled. Another option void be to register to onPreviewFrame() callback and check that the brightness of arriving frames becomes stable.
Starting from a service should not change the situation.
Upvotes: 1