android delaying flashlight - android

I made a simple application with 2 buttons to test flashlights.
button1.setOnClickListener...etc
if (cameraObj ==null){ return; }
Camera.Parameters cameraParams =cameraObj.getParameters();
if(cameraParams.getFlashMode() == null) { return;}
cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cameraObj.setParameters(cameraParams);
cameraObj.startPreview();
button2.setOnClick etc...
if(cameraObj==null){ return; }
Camera.Parameters cameraParams = cameraObj.getParameters();
cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cameraObj.setParameters(cameraParams);
cameraObj.stopPreview();
The application was tested on 2 devices: HTC ONE and HTC DESIRE 500
The application works good on both. The problem is: there's a delay on turning on/off the flashlight.
When I press on and off very fast, the flashlight on DESIRE 500 its turning off and on as I press the buttons, but on HTC ONE there is a delay (it looks like you are not allowed to switch that fast the flashlights). What could be the problem?

You can solve this by adding a fixed delay using Hander which will trigger the flash after a delay,
// variable to fix the timeout duration in milliseconds
// 1000 milliseconds = 1 second
double TIME_OUT = 2*1000;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// time has been reached, turn the flash on
if (cameraObj ==null){ return; }
Camera.Parameters cameraParams =cameraObj.getParameters();
if(cameraParams.getFlashMode() == null) { return;}
cameraParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cameraObj.setParameters(cameraParams);
cameraObj.startPreview();
}
}
}, TIME_OUT);

Related

Android camea startPreview() fails when taking multiple pictures

I'm writing an APP for taking multiple pictures by camera. (Like the burst mode in Camera2, but I'm working on older versions.)
It is implemented by takePicture() / onPictureTaken() callback, and work normally on several devices except some performance issues. However I got a RuntimeException of startPreview failed on an HTC Sensation device when trying to start preview for the 2nd picture.
Here is the functions about multiple shot:
final int multishot_count = 3;
....
public void TakePicture()
{
// Invoke multishot from UI when the camera preview is already started.
// startup of multishot task
...
m_take_picture_count = 0;
TakeOnePicture();
}
private void TakeOnePicture()
{
m_camera.takePicture(null, null, new Camera.PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, final Camera camera)
{
m_take_picture_count++;
// feed the JPEG data to a queue and handle it in another thread
synchronized(m_jpeg_data_lock)
{
int data_size = data.length;
ByteBuffer buffer = ByteBuffer.allocateDirect(data_size);
buffer.put(data, 0, data_size);
m_jpeg_data_queue.offer(buffer);
if (m_take_picture_count == multishot_count)
m_is_all_pictures_taken = true;
}
if (m_take_picture_count < multishot_count)
{
m_camera.startPreview();
TakeOnePicture();
}
else
{
// Finalize the multishot task and process the image data
EndTakePictureTask end_take_picture_task = new EndTakePictureTask();
end_take_picture_task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
});
}
After the first picture being taken, the startPreview() function may fail in a rate of 10-20% on the specified device. My APP is always run in foreground and has a visible view to show the preview frames. I also try to bypass the JPEG data without processing it, but the error still occurs.
I found a similar report at here. It seems that the underlying thread for taking picture does not finish its works, but we have no way to check it. So I try to catch the exception from startPreview() and sleep a while:
if (m_take_picture_count < multishot_count)
{
boolean is_try_start_preview = true;
while (is_try_start_preview)
{
try
{
m_camera.startPreview();
is_try_start_preview = false;
}
catch (RuntimeException e)
{
try
{
Thread.sleep(50);
}
catch (InterruptedException e2)
{
e2.printStackTrace();
}
}
}
TakeOnePicture();
}
But once startPreview fails, it will fail forever no matter how many times I sleep.
I also found that you need to call setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) for the surface holder in older Android versions to let startPreview() work correctly. But the device has Android version 4.0.3 and should not require this call. I still try to add it but the issue remains the same. Moreover, the first call of startPreview() works correctly while the second call after onPictureTaken() gets the error. This is different from the issue of missing setType() in older versions.
Finally I use an workaround that may greatly hurt the performance:
if (m_take_picture_count < multishot_count)
{
try
{
m_camera.startPreview();
}
catch (RuntimeException e)
{
// Fail to start preview. Workaround: reopen camera.
RestartCamera();
}
TakeOnePicture();
}
That is, when startPreview() fails, I just close the camera, reopen it with the same settings, then start the preview to take another picture.
I want to know if I miss something about the take picture APIs, and is there a solution better than this brute-force workaround.
Thanks for the suggestion from Alex Cohn, I found a solution. This solution is only tested on the HTC Sensation device, but it has dramatic effect on this device.
I just put a sleep instruction before startPreview() that would be called in onPictureTaken():
try
{
Thread.sleep(20);
}
catch (Exception e)
{
e.printStackTrace();
}
Then I run a test 100 times, where each run takes 3 pictures in succession. With the sleep, I didn't get any error from startPreview() in 100 runs. If There is no sleep, I need to reopen the camera 78 times, and restart the device 8 times in 100 runs.

Doing an Android FPS counter

I'm trying to do an FPS counter for any Android app. That means I don't have the source code for that app (I can't modify it or anything like that, I just have the .apk).
I've researched a lot into this and I've found only one app that does this (it's called Game Bench, you can find it on Google Play), so it is possible somehow. When the app starts, it has a list with all the games on your phone, you choose one and Game Bench automatically starts it and calculates the FPS. I need a similar behaviour.
Now, what I am asking is, if any of you has at least an idea of how I could calculate the FPS of an app (without writing code in it). Doing research I found a few vague ones, like record the screen and calculate FPS of the video, or somehow calculate the FPS using data collected with systrace. But on both these "ideas" there is very few info on the internet.
So please, if you guys have any information about this matter/ ideas/ opinions, I'll be happy to hear them. Thanks!
This is an example of how I would bench FPS using a Surface View.
Look at the Run method to see how the FPS works.
1: We get the time before update and render to the screen.
2: After all work is done we get the time again.
3: 1000 milliseconds is a second and 40 FPS is the norm.
4: elaspedTime = startTime - endTime;
5: So if elaspedTime is under 25 then its at-least doing 40 FPS.
6: If elaspedTime = 5 milliseconds then its doing 1000 / 5 = 200 FPS
7: You can sleep the thread for a couple milliseconds if you are running the updater and renderer on the same thread. That way you're not updating to many times.
8: Hope it helps this class is a basic game class that keeps the game running and 40 fps even if they are running it on a Galaxy S 6. You would want to make your own necessary changes to tweak it more.
public class MySurfaceView extends SurfaceView implements Runnable {
long time = 0, nextGameTick = 0;
SurfaceHolder myHolder;
Thread myThread = null;
boolean myRunning = false;
public MySurfaceView(Context context) {
super(context);
myHolder = getHolder();
}
#Override
public void run() {
while (myRunning) {
nextGameTick = System.currentTimeMillis();
if (!myHolder.getSurface().isValid())
continue;
Update();
Render();
time = nextGameTick - System.currentTimeMillis();
time = (time <= 0) ? 1 : time;
if (time <= 25)
sleepThread(25 - time);
Log.d("FrameRate", String.valueOf(1000 / time));
}
}
public void pause() {
myRunning = false;
while (true) {
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
myThread = null;
}
public void resume() {
myRunning = true;
myThread = new Thread(this);
myThread.start();
}
public void sleepThread(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void Render() {
// TODO Render to Screen
}
private void Update() {
// TODO Update
}
}

Keep Camera Flash On When Screen Off

I have this code to turn camera flash on and off in android:
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
isFlashOn = true;
The problem appear if flash is on and user turn off screen. flash automatically turned off and return on when screen is on.
I need to keep flash on when screen off.
Any idea please?
Here is a link to the problem you're having. "The key is changing the state back to FLASH_MODE_OFF and then back to FLASH_MODE_TORCH."
In the solution, he creates a Timer Task to handle checking if the screen is on or not. He then turns off the flash and then back on.
Down below the linked solution is another solution which added a thread and made it go to sleep for 200 milliseconds before sending the torch command.
So I'd say the solution you're looking for is the combination of both solutions.
#Override
public void onCreate() {
// assume we start with screen on and save that state ;-)
this.pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
screenOn = this.pm.isScreenOn();
// program a timer which checks if the light needs to be re-activated
this.mTimer = new Timer();
this.mTimerTask = new TimerTask() {
public void run() {
// re-activate the LED if screen turned off
if(!pm.isScreenOn() && pm.isScreenOn() != screenOn) {
Log.i("SleepLEDservice", "re-activated the LED");
// really it's NOT ENOUGH to just "turn it on", i double-checked this
setFlashlight(Camera.Parameters.FLASH_MODE_OFF);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
setFlashlight(Camera.Parameters.FLASH_MODE_TORCH);
}
screenOn = pm.isScreenOn();
}
};
}
private void setFlashlight(String newMode) {
try {
this.frontCamPara = this.frontCam.getParameters();
if(this.frontCamPara.getFlashMode() != newMode) {
this.frontCamPara.setFlashMode(newMode);
this.frontCam.setParameters(frontCamPara);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Again, credit should go to #stefanjunker and #BlueJam as their answers are referenced in this.

Better way to make LED light on back-facing camera blink?

I am trying to make the LED light on my back-facing camera blink every N seconds:
private void blink() {
for (int i = 0; i < 5; i++) {
turnOnLedLight();
try {
Thread.sleep(1000); // N = 1 second
}
catch (InterruptedException e) {
Log.e("Test", "Got interrupted.");
}
turnOffLedLight();
}
}
private static Camera camera = null;
private void turnOnLedLight() {
camera = Camera.open();
Parameters p = camera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
}
private void turnOffLedLight() {
camera.stopPreview();
camera.release();
camera = null;
}
The code above works, but is there a better approach besides putting the thread to sleep? The blink method is called in the doInBackground method in an AsyncTask.
Update
I realized that the code above makes the LED light stay on for N seconds. I want to know whether there is a better way to make it stay on for N seconds and stay off for N seconds.
I'd do it in an alarm via alarmManager. You're holding up the AsyncTask thread. As of 3.0, Async tasks all share a thread and are executed round robin. This means in you have any other async tasks, it would be blocked. In addition an Alarm will wake the phone if it goes to sleep, if the phone goes to sleep while you're in your thread the thread will be paused and will be frozen in its current state of blinking until the user wakes it.
I'd also do Camera.open only once, when you first want the camera, and release it when you no longer want it anymore, rather than request it in each turnOnLedLight (causing you to get and release the camera 5 times). Right now if someone changed apps while you were off and opened the camera app, you could be locked out from getting the camera again (and likely crash).
you can use System.currentTimeMillis() if you're trying to make it more accurate,like:
long previousTimeMillis = System.currentTimeMillis();
int i = 0;
while(i < 5){
if(System.currentTimeMillis() - previousTimeMillis >= 1000){
turnOffLedLight();
previousTimeMillis = System.currentTimeMillis();
i++;
}else{
turnOnLedLight();
}
}
and here's what you can do to make led stay on and off for N seconds:
long previousTimeMillis = Sustem.currentTimeMillis();
boolean shouldTurnOnLight = true;
int i = 0;
while(i < 5){
if(System.currentTimeMillis() - previousTimeMillis >= 1000){
if(shouldTurnOnLight){
turnOnLedLight();
shouldTurnOnLight = false;
}else{
turnOffLedLight();
shouldTurnOnLight = true;
}
previousTimeMillis = System.currentTimeMillis();
i++;
}
}
Here's another way to do it if your on/off cycle is symmetrical:
public Boolean ledOn = false;
...
// Change the LED state once a second for 5 minutes:
CountDownTimer cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
ledOn = !ledOn;
if (ledOn)
turnOffLedLight();
else
turnOnLedLight();
}
public void onFinish() {
Log.d(TAG, "LED is on? "+ ledOn.toString());
}
};
...
cdt.start();
...
cdt.cancel();
(Edited to better handle starting/stopping.)

android and camera flash

I want to write application which will be used camera flash. I want the light to blink. For now I have this code:
void ledon() {
cam = Camera.open();
Parameters params = cam.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_ON);
cam.setParameters(params);
cam.startPreview();
cam.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
}
});
}
this part:
cam.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
}
});
I dont know why its necessary but it wont work without it.
This code turn on led and turn off automaticly for about 2 seconds. I want to led will turn on e.g. for 5 sec then 3 sec led off and then again on for 4 seconds. How I can manually set periods of time in which led will be on and off. Is this possible? Thanks for any help.
PS. I have samsung galaxy ace.
it seems like what you want to use is Parameters.FLASH_MODE_TORCH. You set it to TORCH when you want to turn on the flash LED, and then set it to AUTO when you want the torch light to turn off.
Also, check out this SO question Camera.Parameters.FLASH_MODE_TORCH replacement for Android 2.1 as it'll tell you about some issues people have run into with certain devices.
Then, for the timer, you can use an instance of Timer and a subclass of TimerTask to do the trick. Here's an example from code I've written to make sure an Internet query isn't taking too long:
private QueryLyricsTask clt;
private Timer t1;
...
/* Make sure the query doesn't take too long */
try {
t1 = new Timer("monitorTimeout");
t1.schedule(new qlt(), lyricsTimeout * 1000);
} catch (Exception e) {
e.printStackTrace();
}
...
class qlt extends java.util.TimerTask {
#Override
public void run() {
if (clt.getStatus() != Status.FINISHED)
clt.cancel(true);
}
}
To explain these variables, "monitorTimeout" is a tag name to reference the Timer by. "qlt" is the class that runs once Timer t1 has elapsed. "lyricsTimeout" is a numeric value specified by the user in the settings (for timeout in seconds). "clt" is an instance of a class derived from AsyncTask so it will run the query without freezing up my UI. Obviously in your case, you probably wouldn't need an AsyncTask, but perhaps a simple "if" statement in run() to toggle the flash torch based on its current state.
Check out the documentation on the Timer class so you can learn how to make Timers that fire once or multiple times, or at certain times of day.

Categories

Resources