if(!isOn) {
imageButton.setImageResource(R.drawable.on);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
camera.startPreview();
isOn = true;
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
I wanna add a timer to the flashlight app such that it keeps the flashlight on for the selected time
This is the code which works for me.
public void NotifyWithFlash(Context context){
boolean ShouldIGlow = true;
while(ShouldIGlow){
flashON();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
ShouldIGlow = false;
flashOFF();
}
}
}
public void flashON(){
Camera cam = Camera.open();
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
}
public void flashOFF(){
cam.stopPreview();
cam.release();
}
I wanna add a timer to the flashlight app such that it keeps the flashlight on for the selected time so just set timer using Thread whatever you want as Thread.sleep(user decided period); for example Thread.sleep(5000);
You shouldn't use Thread.sleep() because it will block the UI. Instead you have android.os.Handler :
flashOn();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
flashOff();
}
}, 5000); // 5000 ms = 5 sec
Related
Android App crashes after backpress with Handler and Camera
I am trying to use camera for an SOS app , the code runs when we start the sos flash using the button click in order to keep the flash light running , I am using Handler with Post delay
the app crashes when we use backpress to go back to the previous activity
I have tried using handler.removeCallbacks(r); , onbackpress but still the app crashes
this is the code I am trying
public class sos extends Activity {
String myMorseString = "111000111";
int sleepTime;
Camera cam;
Handler handler;
Runnable r;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sos);
ImageButton button = (ImageButton) findViewById(R.id.Start);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startsos();
}
});
}
public void startsos() {
// new Thread() {
handler = new Handler();
r = new Runnable() {
public void run() {
if (myMorseString != null) {
for (int x = 0; x < myMorseString.length(); x++) {
if (myMorseString.charAt(x) == '2') {
cam = Camera.open();
sleepTime = 500;
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
// power off after signal
cam.stopPreview();
cam.release();
cam = null;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
if (myMorseString.charAt(x) == '1') {
cam = Camera.open();
sleepTime = 250;
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
// power off after signal
cam.stopPreview();
cam.release();
cam = null;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (myMorseString.charAt(x) == '0') {
cam = Camera.open();
sleepTime = 250;
Parameters p = cam.getParameters();
cam.setParameters(p);
//cam.startPreview();
cam.stopPreview();
cam.release();
cam = null;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
handler.postDelayed(this, 10000);
}
// }.start();
};
handler.postDelayed(r, 10000);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
public void onBackPressed() {
handler.removeCallbacks(r);
finish();
super.onBackPressed();
}
}
It's most likely crashing because the camera preview isn't being stopped when back is pressed. The Runnable is just being removed from the Handler.
That being said, you're also going to see another problem: creating a Handler from within an onClick() handler isn't creating a new thread. It's still creating a Handler which is bound to your main thread. The onClick() (and any view related callback) is called on the main (UI) thread. So the sleep() calls you are making in the Runnable are happening on your main thread, which is very bad.
I have created a thread in a class, The code is as follows
private void startThread() {
if (t != null) {
t.interrupt();
}
isFlashOn = true;
t = new Thread() {
public void run() {
try {
try {
SurfaceView surfaceView = (SurfaceView) activity
.findViewById(R.id.surfaceViewCam);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
// surfaceHolder.addCallback(this);
camera.setPreviewDisplay(surfaceHolder);
} catch (Exception e) {
e.printStackTrace();
}
camera.startPreview();
for (int i = seekBarManager.preferenceManager
.get_duration(); i > 0 && !this.isInterrupted(); i--) {
isFlashOn = true;
setBlinkToggle();
sleep(seekBarManager.preferenceManager.get_delay());
if(isFlashOn==false){
break;
}
}
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
}
I stop the thread in a method
private void stopThread() {
if (t != null) {
t.interrupt();
//t.
isFlashOn = false;
}
}
The problem I am facing is, The for loop in the thread seems to be running even after the successful call of Interrupt()
Any help here would be greatly appreciated!
Updated Code
t = new Thread() {
public void run() {
Boolean isStop = false;
try {
try {
SurfaceView surfaceView = (SurfaceView) activity
.findViewById(R.id.surfaceViewCam);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
// surfaceHolder.addCallback(this);
camera.setPreviewDisplay(surfaceHolder);
} catch (Exception e) {
e.printStackTrace();
}
camera.startPreview();
for (int i = seekBarManager.preferenceManager
.get_duration(); i > 0 && !isStop; i--) {
isFlashOn = true;
setBlinkToggle();
sleep(seekBarManager.preferenceManager.get_delay());
}
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
} catch (Exception e) {
e.printStackTrace();
isStop=true;
//notify();
return;
}
}
};
Purpose of interrupt():
It just sets the interrupted flag to true. After interrupt() has been called the Thread.currentThread().isInterrupted() starts to return false. And that's all.
Another case is if interrupt() is called while the thread is blocked in an invocation of one of the methods that throw InterruptedException, then that method will return throwing the InterruptedException. And if thread's code just "eats" that exception, then the thread will still continue running.
So the correct approach should be to periodically check the interrupted flag. And if interrupted status is detected then just return ASAP. Another common option is not to use Thread.interrupt() at all, but some custom boolean instead.
See the below link for safe stop of thread:-
http://www.java2s.com/Code/Java/Threads/Thesafewaytostopathread.htm
I have service that make flash blink signals:
public class FlashBlinkService extends Service
{
private static Camera cam = null;
private Handler handler = new Handler();
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
startFlashBlink();
}
//for simulating flash blink
Runnable flashBlinkRunnable = new Runnable()
{
public void run()
{
cam = Camera.open();
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
p.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(p);
cam.stopPreview();
cam.release();
cam = null;
//--->
handler.post(flashBlinkRunnable);
}
};
//start flash blink light
public void startFlashBlink()
{
flashBlinkRunnable.run();
}
//stop flash blink light
public void stopFlashBlink()
{
handler.removeCallbacks(flashBlinkRunnable);
stopCamera(cam);
}
//stop camera
private void stopCamera(Camera cam)
{
if (cam != null)
{
cam.stopPreview();
cam.release();
cam = null;
}
}
#Override
public void onDestroy()
{
super.onDestroy();
handler.removeCallbacks(flashBlinkRunnable);
stopCamera(cam);
}
}
This is the 'fastest' flash blink solution right now for me. Which is the best way to make faster or slower flash blink signals? There is a lots of applications in the market (like some flashlights) that provide this option. Thanks.
I've accomplished this in the following way. The frequency of the strobe (flash blinking) is regulated by the sleepMS variable in the Thread.sleep() function. For example if you want 10 flashes at 10 Hz you would set
sleepMS=(1/10)*50;
flashCount=10;
Or more general:
sleepMS=(1/Hz)*1000/2
Not sure is the best way to accomplish this but it works.
Camera cam;
Parameters params;
private void main(){
cam = Camera.open();
params = cam.getParameters();
cam.setPreviewTexture(new SurfaceTexture(0));
cam.startPreview();
for (int i = 0; i < flashCount; i++) {
flipFlash();
Thread.sleep(sleepMS);
flipFlash();
Thread.sleep(sleepMS);
}
cam.stopPreview();
cam.release();
}
private void flipFlash(){
if (isLighOn) {
params.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(params);
isLighOn = false;
} else{
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(params);
isLighOn = true;
}
}
You can create a new thread and after each turnOn/turnOff sleep the thread as long as you want the pause to be
So, I made a torch app... The normal Torch function is fully working, no problems.
The following explains the below function that can cause possible ANRs
Say, I want to send out an SOS message (morse code) through the blinking flash.
(its 111-000-111)
So it's On-On-On-Off-Off-Off- and repeat.
(Read Slowly)
I "On" it for a little while, then a little flash, "On" again - This is to distinguish two consecutive "On"s ... That's how I get three distinct flashes.
Trouble is, for Time delay, I put the thread to sleep.(This method has worked the best for me)
Here's my sample function , it flashes out SOS:
(I have a seperate button for SOS)
public void sos(View v) {
String myString = "111000111";
for (int x = 0; x < myString.length(); x++) {
if (myString.charAt(x) == '1') {
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
c.setParameters(p);
c.startPreview();
flag = true;
} else {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
c.setParameters(p);
flag = false;
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
c.setParameters(p);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
c.setParameters(p);
}
}
The above flashes out SOS just once.
But while this flashing and blinking is going on , my app is frozen up. The Blinking SOS is perfect. But it doesn't respond to any button clicks or even Back Button to stop it midway.
I reckon this is because the thread(UI) is sleeping hence it doesn't care about what the user is doing)... But the click surely is registered, and if according to android if it isn't looked after in the stipulated period of time (I think a few seconds) ... The app goes ANR.
So, I need brief pauses with intervals defined by me (As above I use 300 milliseconds). But I also want to know how to get the app to simultaneously respond to say Button Clicks, or Back Button Presses so as to avoid ANR's and give the user the ability to shut down the blinking at any time.
How to do this ?
EDIT
Waza_Be's Solution:
Okay so here's my modified function according to Waza_Be. The problem seems to be, it does wait 300 milliseconds(in my case) ...But I have several postDelay functions - So I think it's actually lining up all the functions together, and the waiting period of the 300 milliseconds is somewhat overlapping. After this period ends, all the code runs together at once, making it quite pointless.
When I tried this, the Flash blinks rather swiftly, not with the subtle pauses and blinking effect I want.
public void sos(View v) {
String myString = "111000111";
Handler handler = new Handler();
for (int x = 0; x < myString.length(); x++) {
if (myString.charAt(x) == '1') {
handler.postDelayed(new Runnable() {
public void run() {
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
c.setParameters(p);
c.startPreview();
}
}, 300);
} else {
handler.postDelayed(new Runnable() {
public void run() {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
c.setParameters(p);
}
}, 300);
}
handler.postDelayed(new Runnable() {
public void run() {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
c.setParameters(p);
}
}, 300);
}
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
c.setParameters(p);
}
}
I need separate pauses. Say after or before every TURN_ON or TURN_OFF for the Flash.
In each loop, it should wait individually for each piece of code in the Handler Run().
I personally use Handler postDelayed when I want to "sleep"
// "SLEEP" 2 SECONDS HERE ...
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); // Or watherver you want
c.setParameters(p);
}
}, 2000);
You could also use the sleep method in a thread to avoid blocking the UI thread.
Edit:
This is how you can write a recursive handler:
This will allow you to send all the Morse part on after the other
Handler handler = new Handler();
int i = 0;
Runnable myRunnable = new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
if(i>5)
handler.removeCallback(myRunnable);
else{
i++;
handler.postDelayed(myRunnable, 100); // here is self calling
}
}
};
}
handler.postDelayed(myRunnable, 100);
I solved this a little different using Thread.
The morse code is generated by clicking a button.
OnClickListener goMorse = new OnClickListener() {
#Override
public void onClick(View v) {
new Thread () {
public void run() {
if(myMorseString != null){
for (int x = 0; x < myMorseString.length(); x++) {
if (myMorseString.charAt(x) == '2') {
cam = Camera.open();
sleepTime = 500;
Parameters p = cam.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
// power off after signal
cam.stopPreview();
cam.release();
cam = null;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (myMorseString.charAt(x) == '1') {
cam = Camera.open();
sleepTime = 250;
Parameters p = cam.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
// power off after signal
cam.stopPreview();
cam.release();
cam = null;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (myMorseString.charAt(x) == '0') {
cam = Camera.open();
sleepTime = 250;
Parameters p = cam.getParameters();
cam.setParameters(p);
//cam.startPreview();
cam.stopPreview();
cam.release();
cam = null;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}}}
}.start();
}
};
I am using a thread to run the flashlight and I want to stop that thread after the back is pressed.
I used the following code to start the thread:
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Flashing...");
progressDialog.show();
thread = new Thread(MainActivity.this);
thread.start();
And the thread is doing:
public void run() {
isOn = false;
cam = Camera.open();
p = cam.getParameters();
try {
for (int i = 0; i < pattern.length; i++) {
if (isOn) {
p.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(p);
Thread.sleep(pattern[i]);
isOn = false;
} else {
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
Thread.sleep(pattern[i]);
isOn = true;
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
cam.release();
handlerFinish.sendEmptyMessage(0);
}
private Handler handlerFinish = new Handler() {
#Override
public void handleMessage(Message msg) {
progressDialog.dismiss();
}
};
I have tried this to stop, but there are only the progress dialog is dismissed but the flashlight is still working:
#Override
public void onBackPressed() {
super.onBackPressed();
p.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(p);
isOn = false;
thread.stop();
}
What can I do to achieve my goal (Stop the thread and flashlight after back is pressed)?
try this loop to stop the thread
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}