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.
Related
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);
I have this code, it works well if I use lights(); once
but if I use it multiple times like lights();lights();lights();... not so much. when the app run they seems to run all at the same time
public void lights() {
try {if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){
cam = Camera.open();
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();}
} catch (Exception e) {e.printStackTrace();}
}
}
mHandler.postDelayed(new Runnable() {public void run() {stop();}
}, 1000);
}
public void stop(){
try {if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH))
{cam.stopPreview();cam.release();cam = null;}} catch (Exception e) {e.printStackTrace();}
}
How can I make the handlers to wait one after another? To wait for the first one to finish. I want to make an alarm but if I use ThreadSleep(); too much my app crash, probably thinks the UI is unresponsive
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.)
I have an android application with QR Code scan. Everything works fine until I installed GMD Hide Bar.
The screen will turn completely black after I successfully scan QR Code. But my app continues to run in black screen since I can hear the sound. I have to click the power button on my device twice (to turn off the screen once and turn it on again), then I can see the screen again.
Since they works individually so I'm not sure what cause this. Here is the code when the QR Code scanner scans a code and quit, for which is the moment when the screen turns black.
private final Handler mUnityHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
try {
Class<UnityPlayer> c = com.unity3d.player.UnityPlayer.class;
Method method = c.getMethod("UnitySendMessage", new Class[] { String.class, String.class, String.class });
method.invoke(null, "CodeScannerBridge", "onScannerMessage", mDataStr); // reveiver null
// because
// UnitySendMessage
// is
// static
} catch (NoSuchMethodException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
finish();
}
Any idea?
EDIT It doesnt happen 100% of the time, but often. And I have another function:
mHandler.postDelayed(new Runnable() {
public void run() {
finish();
}
}, 10000);
I tested for this. It will turn black screen sometimes too.
I am able to pause/resume my game by making my game thread(which holds/synchronized with surfaceview) wait/notifyAll. This all runs well using the in game pause button.
However, when I click home/back button I am able to pause my game, but when I resumes my game by clicking on its icon, I receive non responsive game screen back to me.
I have put logs on OnResume() method but nothing gets printed in LogCat!
If I click on my game screen I get error dialog to "Force Close" or "Wait" on my game activity.
Why I am getting this non responsive screen as if my application Hangged after pause ?
How can I handle physical buttons in same way as inGame pause/resume button ?
here is my logcat view of the operation. you can see onResume sop not getting printed similar to onPause.
EDIT : Code called by my pause/resume button and by onPause/onResume functions
where "this" is thread class itself
protected void setPause(){
synchronized (this) {
isPaused = true;
}
}
protected void setResume(){
synchronized (this) {
isPaused = false;
this.notifyAll();
}
}
Game Loop Code :
synchronized (this) {
while (running) {
if (isPaused) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Canvas c = null;
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS
- (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
This how I am calling it from surface view :
public void surfaceCreated(SurfaceHolder holder) {
// start the game loop
System.out.println("Starting Game Loop #########");
if(isPaused){
System.out.println("GamePaused");
gameLoopThread.setResume();
}
else{
System.out.println("Game Starting");
gameLoopThread.setRunning(true);
}
gameLoopThread.start();
}
EDIT 2:
If I Pause my game using pause button and let my phone get locked automatically... after resuming I am able to play normally with out any issue.
As per logs I see surface destroyed is not getting called in this case.
After onResume, your SurfaceView is created again, but it lost all the data it had before (all info needed for onDraw). you have to save the data in surfaceDestroyed or before, and reload it in the onCreate of your surfaceview