Skip to content

Instantly share code, notes, and snippets.

@alexrainman
Last active March 16, 2022 12:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alexrainman/33379b672be8f5877c5d to your computer and use it in GitHub Desktop.
Save alexrainman/33379b672be8f5877c5d to your computer and use it in GitHub Desktop.
Xamarin Android light sensor class (easy portable to Java)
using System;
using Android.Graphics;
using Android.Hardware;
using Android.Media;
using Java.IO;
using YourNamespace.Utils;
namespace YourNamespace
{
public class LightMeter: Java.Lang.Object, Android.Hardware.Camera.IPictureCallback, Android.Hardware.Camera.IPreviewCallback
{
/*
* You can estimate the reflected light by taking a picture with your camera, and glancing at the exposure at given settings.
* If the exposure is decent, look at the meter settings: your used ISO, aperture, and shutter speed.
* Once you have a reading, you can do two conversions to reach the approximate LUX value.
* First, you need to convert to an EV (Exposure Value), then to LUX.
*/
int cameraId;
Android.Hardware.Camera camera;
string PICTURE_FILENAME = "";
public void Start() {
try{
cameraId = findFrontFacingCamera();
if (camera == null) {
camera = Android.Hardware.Camera.Open(cameraId);
Android.Hardware.Camera.Parameters p = camera.GetParameters();
p.PictureFormat = ImageFormatType.Jpeg;
p.Set("ISO", 100);
camera.SetParameters(p);
camera.Lock();
SurfaceTexture surfaceTexture = new SurfaceTexture(10);
camera.SetPreviewTexture(surfaceTexture);
camera.StartPreview();
}
}
catch(IOException e){
}
}
public void Stop() {
try {
if (camera != null) {
camera.StopPreview ();
camera.SetPreviewDisplay (null);
camera.SetPreviewCallback (null);
camera.Unlock ();
camera.Release ();
camera = null;
}
} catch (IOException ex) {
}
}
int findFrontFacingCamera() {
Android.Hardware.Camera.CameraInfo camInfo = new Android.Hardware.Camera.CameraInfo ();
for (int i = 0; i < Android.Hardware.Camera.NumberOfCameras; i++) {
Android.Hardware.Camera.GetCameraInfo (i, camInfo);
if (camInfo.Facing == CameraFacing.Front){
try {
return i;
} catch (Exception e) {
// log or something
}
}
}
return -1;
}
public void TakePicture(){
if (camera != null) {
camera.TakePicture (null, this, this);
}
}
public double GetLux(){
/* Illuminance Surfaces illuminated by:
*
* 0.0001 lux Moonless, overcast night sky (starlight)[3]
* 0.002 lux Moonless clear night sky with airglow[3]
* 0.27–1.0 lux Full moon on a clear night[3][4]
* 3.4 lux Dark limit of civil twilight under a clear sky[5]
* 50 lux Family living room lights (Australia, 1998)[6]
* 80 lux Office building hallway/toilet lighting[7][8]
* 100 lux Very dark overcast day[3]
* 320–500 lux Office lighting[9][10][11]
* 400 lux Sunrise or sunset on a clear day.
* 1000 lux Overcast day;[3] typical TV studio lighting
* 10000–25000 lux Full daylight (not direct sun)[3]
* 32000–100000 lux Direct sunlight
*/
ExifInterface exif = null;
if (!PICTURE_FILENAME.Equals("")){
try {
File dataDir = Android.OS.Environment.ExternalStorageDirectory;
exif = new ExifInterface(dataDir + "/" + PICTURE_FILENAME);
} catch (IOException ex) {
}
}
if (exif != null) {
PICTURE_FILENAME = "";
// (Exposure Value) EV = log2 N2 / t
/* where:
* N is the relative aperture (f-number)
* t is the exposure time (“shutter speed”) in seconds
*/
double f_number = double.Parse(exif.GetAttribute (ExifInterface.TagAperture));
double shutter_speed = double.Parse(exif.GetAttribute (ExifInterface.TagExposureTime));
double EV = Math.Log ((f_number * f_number) / shutter_speed);
// 0 EV = 2.5 lux
// (Illuminance) E = 2.5 * 2^EV
return 2.5 * Math.Pow(2,EV);
}
return -1;
}
void Android.Hardware.Camera.IPictureCallback.OnPictureTaken(byte[] data, Android.Hardware.Camera camera)
{
FileOutputStream outStream = null;
File dataDir = Android.OS.Environment.ExternalStorageDirectory;
if (data != null) {
try{
PICTURE_FILENAME = Utils.CurrentTimeMillis() + ".jpg";
outStream = new FileOutputStream(dataDir + "/" + PICTURE_FILENAME);
outStream.Write(data);
outStream.Close();
}catch(FileNotFoundException e){
System.Console.Out.WriteLine (e.Message);
}catch(IOException ie){
System.Console.Out.WriteLine (ie.Message);
}
}
}
void Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(byte[] b, Android.Hardware.Camera c)
{
}
}
}
// HOW TO USE
LightMeter cSensor;
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
cSensor = new LightMeter ();
}
protected override void OnResume ()
{
base.OnResume ();
cSensor.Start();
// after start the sensor you have two methods:
// cSensor.TakePicture() take a picture with the front camera to be used as source for ExifScan
// cSensor.GetLux() get Lux (illuminance) value
}
protected override void OnPause ()
{
base.OnPause ();
cSensor.Stop();
}
// Utils class
using System;
namespace YourNamespace
{
public class Utils
{
public static long CurrentTimeMillis(){
return (long)(DateTime.Now - new DateTime (1970, 1, 1)).TotalMilliseconds;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment