Change Proximity Sensor Events by Using Camera

This post is about how to capture pictures using camera with sensor event updates (Proximity Sensor). This is about the simplest implementation of device camera in integration to a particular type of sensor (Proximity sensor here).

This post is also defines how to create and set a transparent theme to the main activity ready to capture pictures on change of proximity sensor state. It also defines how to create a preview for camera resource occupying no space on the activity’s layout.

Utility:

1. Since following Camera activity has a transparent theme with no preview so that user touching the phone won’t know that a camera application is in foreground ready to take pictures if device is touched over its proximity sensor.

HiddenCameraActivity.java

/**
* This is an activity with transparent theme implementing a simple Camera app
* with no preview clicking pictures using front camera whoever touches the
* device over its proximity sensor.
*/
public class HiddenCameraActivity extends Activity {
/**
* Frame layout which holds the camera preview.
*/
private FrameLayout mPreviewLayout = null;
/**
* Reference to Camera instance
*/
private Camera mCamera = null;
/**
* Reference to Camera Preview
*/
private CameraPreview mPreview = null;
/**
* Reference to SensorManager that provides a list of sensors available in
* device.
*/
private SensorManager mSensorManager = null;
/**
* Reference to Proximity Sensor
*/
private Sensor mProximSensor = null;
/**
* boolean that marks the successful creation of one image before starting
* the next
*/
private boolean isPicDone = false;
/**
* Constant defining image type
*/
private static final int MEDIA_TYPE_IMAGE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auth_succ);
mPreviewLayout = (FrameLayout) findViewById(R.id.camera_preview);
initializeCamera();
}
/**
* This method checks for the front camera and in case of availability
* initializes it, also instantiates CameraPreview using camera instance and
* adds to the Preview layout
*/
private void initializeCamera() {
if (checkCameraHardware()) {
for (int camNo = 0; camNo < Camera.getNumberOfCameras(); camNo++) {
CameraInfo camInfo = new CameraInfo();
Camera.getCameraInfo(camNo, camInfo);
if (camInfo.facing == (Camera.CameraInfo.CAMERA_FACING_FRONT)) {
if (mCamera == null)
mCamera = Camera.open(camNo);
else {
mCamera.release();
mCamera = Camera.open(camNo);
}
mPreview = new CameraPreview(this, mCamera);
mPreviewLayout.addView(mPreview);
}
}
}
}
/**
* This methods checks for the support camera hardware
*
* @return true/false based upon the availability of camera
*/
private boolean checkCameraHardware() {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA))
return true;
else
return false;
}
@Override
protected void onResume() {
// Initializing and registering Location Providers for change in
// proximity sensor events.
registerProximitySensor();
super.onResume();
}
/**
* This callback allows registration to Sensor service for listening changes
* in Proximity Sensor event.
*/
public void registerProximitySensor() {
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
List<Sensor> sensorList = mSensorManager
.getSensorList(Sensor.TYPE_PROXIMITY);
if (sensorList != null && sensorList.size() > 0) {
mProximSensor = sensorList.get(0);
mSensorManager.registerListener(mProximSensorListener,
mProximSensor, SensorManager.SENSOR_DELAY_UI);
} else {
Toast.makeText(this, "Sensor not found.", Toast.LENGTH_SHORT)
.show();
finish();
}
}
/**
* Interface implemented for receiving notifications from the SensorManager
* when proximity sensor values have changed
*/
private SensorEventListener mProximSensorListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if (!isPicDone) {
isPicDone = true;
takePicture();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
/**
* This method is used to take pictures
*/
private void takePicture() {
mCamera.takePicture(null, null, mPicture);
}
/**
* Callback interface used to supply image data from a photo capture.
*/
public PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File file = getOutputMediaFile(MEDIA_TYPE_IMAGE);
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
isPicDone = false;
}
};
/**
* This method checks and creates for the file reference to be used to write
* the captured image data.
*
* @param type
* integer type of media
* @return reference to File object
*/
private static File getOutputMediaFile(int type) {
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"ProxPics");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs())
return null;
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile = null;
if (type == MEDIA_TYPE_IMAGE)
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "SNAP_" + timeStamp + ".jpg");
return mediaFile;
}
@Override
protected void onPause() {
// Unregistering the sensor
unRegisterProximitySensor();
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
super.onPause();
}
/**
* method to unregsiter sensor service.
*/
public void unRegisterProximitySensor() {
if (mProximSensor != null)
mSensorManager.unregisterListener(mProximSensorListener,
mProximSensor);
}
}

CameraPreview.java

/**
* This is class provides the preview to the app whose size (width, height) we
* will be setting to (1,1) which means no preview at all. It also implements
* interface that provides information about when surface is created, changed or
* destroyed.
*/
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
Camera.Parameters params = mCamera.getParameters();
// Setting size to (1,1) to make no preview visible on activity's
// layout.
params.setPreviewSize(1, 1);
mCamera.setParameters(params);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}

To make our app appear transparent we need to create a style in styles.xml and set it for theme attribute in application tag in manifest.

<style name="TransparentTheme" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>

Since, it’s just a simple app, a lot of modifications and extensions can be made to it.

Possible Extensions:

1. Can listen to GPS and edit the GPS related Exif Tag values.
2. Can upload the saved images from the SD card to the server.

 

Written By: Ravi Kumar, Android Developer, Mindfire Solutions

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s