I'm working on an Android app in which the flashlight turns on/off when the device is shaken. I'm stuck on the surface View part. How can I detect motion in the methods that are overridden by SurfaceHolder.callback??
I am successfully able to switch the flashlight on and off without the motion detection, by a button. But I'm having trouble in synchronizing motion detection and surface view.
Here is my code:
public class FlashActivity extends Activity implements SurfaceHolder.Callback {
ImageView image;
TextView text;
int flag = 0, count = 0;
long lastShakeTime = 0;
Timer timer;
public static Camera camera;
private ShakeDetector mShakeDetector;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
Vibrator vibrator;
SurfaceView surfaceView;
SurfaceHolder holder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
text = (TextView) findViewById(R.id.text);
image = (ImageView) findViewById(R.id.flashon);
// ShakeDetector initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
count = 0;
image.setVisibility(View.INVISIBLE);
text.setVisibility(View.VISIBLE);
surfaceView = (SurfaceView) findViewById(R.id.surface);
holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
@Override
public void onShake(int count) {
Log.v("elapsed real time", "" + SystemClock.elapsedRealtime());
Log.v("lastShakeTime", "" + lastShakeTime);
if (SystemClock.elapsedRealtime() - lastShakeTime < 800) {
} else {
handleShakeEvent();
}
lastShakeTime = SystemClock.elapsedRealtime();
}
});
}
public void handleShakeEvent() {
try {
if (getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH)) {
if (camera == null) {
camera = Camera.open();
android.hardware.Camera.Parameters p = camera.getParameters();
p.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
image.setVisibility(View.VISIBLE);
text.setVisibility(View.INVISIBLE);
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(100);
} else if (camera != null) {
android.hardware.Camera.Parameters p = camera.getParameters();
p.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
camera.release();
camera = null;
image.setVisibility(View.INVISIBLE);
text.setVisibility(View.VISIBLE);
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(100);
}
} else {
Toast.makeText(getApplicationContext(), "You do not have a flash!", Toast.LENGTH_LONG).show();
return;
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getBaseContext(),
"Exception", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onResume() {
super.onResume();
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
@Override
public void onBackPressed() {
super.onBackPressed();
mSensorManager.unregisterListener(mShakeDetector);
finish();
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.v("in", "created");
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
if (camera == null) {
try {
camera = Camera.open();
} catch (RuntimeException e) {
System.err.println(e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
param.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_TORCH);
image.setVisibility(View.VISIBLE);
text.setVisibility(View.INVISIBLE);
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(100);
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
System.err.println(e);
return;
}
}
else if(camera!=null){
Camera.Parameters param;
param=camera.getParameters();
param.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
image.setVisibility(View.INVISIBLE);
text.setVisibility(View.VISIBLE);
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(100);
camera.setParameters(param);
camera.stopPreview();
camera.release();
camera=null;
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
Log.v("in", "changed");
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.v("in", "destroyed");
mSensorManager.unregisterListener(mShakeDetector);
camera.stopPreview();
camera.release();
camera = null;
}
}
Thanks in advance.
I solved it myself after hours of trying. :D
I called the method surfaceChanged() in the onShakeListener and moved the handleShakeEvent() to surfaceChanged().