Unable to kill a Thread in Android - android

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

Related

Android App crashes after backpress with Handler and Camera

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.

Video Recording using GLSurfaceview in android

I'm trying to record video by using GLSurfaceview in android. But every time when i tap to record, it gives me null pointer exception onPause.
here is my code to record video
mCamera = new CameraLoader();
buttonn_capture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try{
if (recording) {
mediaRecorder.stop(); // stop the recording
recording = false;
} else {
// Release Camera before MediaRecorder start
mCamera.releaseCamera();
if (!prepareMediaRecorder()) {
finish();
}
try {
mediaRecorder.prepare();
} catch (IllegalStateException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaRecorder.start();
recording = true;
// myButton.setText("Cancel");
}
}catch(Exception ex){
Toast.makeText(getApplicationContext(), "Please tap and hold to record!",
Toast.LENGTH_LONG).show();
reload();
}
}
});
private boolean prepareMediaRecorder() {
mCamera.mCameraInstance.unlock();
mediaRecorder.setCamera(mCamera.mCameraInstance);
// Step 2: Set sources
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
"MusicDubs");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
}
timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
.format(new Date());
CameraInfo caminfo = new CameraInfo();
mCamera.mCameraInstance.getCameraInfo(0, caminfo);
if (caminfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
mediaRecorder.setProfile(CamcorderProfile.get(0,
CamcorderProfile.QUALITY_HIGH));
mediaRecorder
.setOrientationHint(270);
} else if (caminfo.facing == CameraInfo.CAMERA_FACING_BACK) {
mediaRecorder.setProfile(CamcorderProfile.get(0,
CamcorderProfile.QUALITY_HIGH));
mediaRecorder
.setOrientationHint(270);
mediaRecorder.setOrientationHint(90);
}
//mediaRecorder.setCaptureRate(20);
mediaRecorder.setVideoFrameRate(120);
mediaRecorder.setOutputFile(mediaStorageDir.getPath() + "/"
+ "_" + timeStamp + ".mp4");
// Step 5: Set the preview output
mediaRecorder.setPreviewDisplay(glSurfaceView.getHolder()
.getSurface());
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
// releaseMediaPlayer();
return false;
} catch (IOException e) {
releaseMediaRecorder();
// releaseMediaPlayer();
return false;
}
return true;
}
private void releaseMediaRecorder() {
if (mediaRecorder != null) {
mediaRecorder.reset(); // clear recorder configuration
mediaRecorder.release(); // release the recorder object
mediaRecorder = null;
mCamera.mCameraInstance.lock(); // lock camera for later use
}
}
on Activity pause and resume i added that code
#Override
protected void onResume() {
super.onResume();
mCamera.onResume();
}
#Override
protected void onPause() {
mCamera.onPause();
super.onPause();
}
here is my camera class to load camera
private class CameraLoader {
private int mCurrentCameraId = 0;
private Camera mCameraInstance;
public void onResume() {
setUpCamera(mCurrentCameraId);
}
public void onPause() {
releaseCamera();
}
public void switchCamera() {
releaseCamera();
mCurrentCameraId = (mCurrentCameraId + 1) % mCameraHelper.getNumberOfCameras();
setUpCamera(mCurrentCameraId);
}
private void setUpCamera(final int id) {
mCameraInstance = getCameraInstance(id);
Parameters parameters = mCameraInstance.getParameters();
// TODO adjust by getting supportedPreviewSizes and then choosing
// the best one for screen size (best fill screen)
if (parameters.getSupportedFocusModes().contains(
Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCameraInstance.setParameters(parameters);
int orientation = mCameraHelper.getCameraDisplayOrientation(
ActivityCamera.this, mCurrentCameraId);
CameraInfo2 cameraInfo = new CameraInfo2();
mCameraHelper.getCameraInfo(mCurrentCameraId, cameraInfo);
boolean flipHorizontal = cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT;
mGPUImage.setUpCamera(mCameraInstance, orientation, flipHorizontal, false);
}
/** A safe way to get an instance of the Camera object. */
private Camera getCameraInstance(final int id) {
Camera c = null;
try {
c = mCameraHelper.openCamera(id);
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
private void releaseCamera() {
mCameraInstance.setPreviewCallback(null);
mCameraInstance.release();
mCameraInstance = null;
}
}
Its behavior is very strange, I didn't get why it is giving me null pointer exception onPause because there is no point of getting camera null there. please tell me where i'm doing wrong. Any help would be much appreciated. Thank you :)

A delay of a Few seconds when trying to power on Led flash

Im trying to power on the led flash, but the led flash powers on after a delay of a few seconds.
I have a built in torch in my phone, and when I click it it the flash turns on immediately.
Whats the problem here?
Heres my code:
private void processOnClick() {
if (manuName.contains("motorola")) {
DroidLED led;
try {
led = new DroidLED();
led.enable(true);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
if (mCamera == null) {
try {
mCamera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
mCamera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
if (mCamera != null) {
final Parameters params = mCamera.getParameters();
List<String> flashModes = params.getSupportedFlashModes();
if (flashModes == null) {
return;
} else {
if (count == 0) {
params.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.startPreview();
}
String flashMode = params.getFlashMode();
if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);
} else {
// Toast.makeText(this,
// "Flash mode (torch) not supported",Toast.LENGTH_LONG).show();
params.setFlashMode(Parameters.FLASH_MODE_ON);
mCamera.setParameters(params);
try {
mCamera.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
count = 1;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
if (mCamera == null) {
return;
}
}
private void processOffClick() {
if (manuName.contains("motorola")) {
DroidLED led;
try {
led = new DroidLED();
led.enable(false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
}
}
DroidLED class:
import java.lang.reflect.Method;
import android.os.IBinder;
class DroidLED {
private Object svc = null;
private Method getFlashlightEnabled = null;
private Method setFlashlightEnabled = null;
#SuppressWarnings("unchecked")
public DroidLED() throws Exception {
try {
// call ServiceManager.getService("hardware") to get an IBinder for the service.
// this appears to be totally undocumented and not exposed in the SDK whatsoever.
Class sm = Class.forName("android.os.ServiceManager");
Object hwBinder = sm.getMethod("getService", String.class).invoke(null, "hardware");
// get the hardware service stub. this seems to just get us one step closer to the proxy
Class hwsstub = Class.forName("android.os.IHardwareService$Stub");
Method asInterface = hwsstub.getMethod("asInterface", android.os.IBinder.class);
svc = asInterface.invoke(null, (IBinder) hwBinder);
// grab the class (android.os.IHardwareService$Stub$Proxy) so we can reflect on its methods
Class proxy = svc.getClass();
// save methods
getFlashlightEnabled = proxy.getMethod("getFlashlightEnabled");
setFlashlightEnabled = proxy.getMethod("setFlashlightEnabled", boolean.class);
}
catch(Exception e) {
throw new Exception("LED could not be initialized");
}
}
public boolean isEnabled() {
try {
return getFlashlightEnabled.invoke(svc).equals(true);
}
catch(Exception e) {
return false;
}
}
public void enable(boolean tf) {
try {
setFlashlightEnabled.invoke(svc, tf);
}
catch(Exception e) {}
}
}
I took this code from some answer around stackoverflow.
Thanks for your assistance!
Do you get high latencies with the motorola?
It's just a guess, but the DroidLED constructor calls expensive system initializations.
Couldn't you do this?
public class MyWidgetClickHandler {
private DroidLED = null;
public MyWidgetClickHandler(string ManuName) {
// This is slow. It will run once at initialization.
if (ManuName != null && ManuName.toLowerCase().contains("motorola"))
DroidLED = new DroidLED();
}
public void processOnClick() {
if (DroidLED != null)
DroidLED.enable(true);
else
; // ... TODO
}
public void processOffClick() {
if (DroidLED != null)
DroidLED.enable(false);
else
; // ... TODO
}
}
There could be so much more. For example you could create a LED interface with enable and isEnabled, and have two implementations for it. One would be DroidLED and the other the CommonCameraLED.
With this it looks like this:
public class LEDFactory {
public static LED createLED(string ManuName) {
if (ManuName != null && ManuName.toLowerCase().contains("motorola"))
return new DroidLED();
else
return new CommonCameraLED();
}
}
public class MyWidgetClickHandler {
private LED myLed = null;
public MyWidgetClickHandler(string ManuName) {
myLed = LEDFactory.createLED(ManuName);
}
public void processOnClick() {
myLed.enable(true);
// NOTHING TO DO
}
public void processOffClick() {
myLed.enable(false);
// NOTHING TO DO
}
}
You could also create a Thread for initialization so that phone won't start slow.
I just came across the same problem and found a solution, but i made my tests using a Samsung Galaxy S2. This code should work on every device.
Profiling each one of the functions, i found that some calls necessary to setup the camera, sumed up to 500ms in delay, making a strobe effect impossible.
My solution was to move all those functions to a separate function i call when i want to get the camera, and reduce the "turn on" code just to the call to Camera.setParameters(). By doing this, the delay came down to only 4ms.
For example (reduced code just to to prove the point):
// First get the camera for your app (Keep this variables as class
members so the live between functions)
private void acquireCamera()
{
try
{
// Get camera
cam = Camera.open();
// This is not on your code but you should do it for compatibility
mSurfaceTexture = new SurfaceTexture(0);
cam.setPreviewTexture(mSurfaceTexture);
cam.startPreview();
camParams = cam.getParameters();
}
catch(IOException e)
{ /*...*/ }
}
// Then turn on / off as many times you want.
private void setTorch(boolean on)
{
camParams.setFlashMode(on? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(camParams);
}
// Finally release the camera when you`re done
private void releaseCamera
{
camParams = null;
cam.stopPreview();
mSurfaceTexture = null;
cam.release();
}

How to keep flash on when activity goes to background

I am developing a very simple flashlight application, while I have successfully achieved what I was looking for, I would like to perform it that way I want it to. Currently my flashlight remains on while my activity is active, as soon as I hit the home button to minimize the activity flashlight turns off. I want the flashlight to stay on and turn off only when I click the turn off button in my activity.
I also want something like that if the flashlight is active and user hits the home button to minimize the activity, Turn Off button to be displayed in the notification bar.
Please guide me.
Please try to use bellow code.
public class CustomFlashLight {
private static CustomFlashLight instance;
private static Camera mCamera;
public static CustomFlashLight getInstance() {
if (null == instance) {
instance = new CustomFlashLight();
}
return instance;
}
public static boolean checkFlashAvailaibility(Context context) {
boolean flag = false;
try {
flag = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH);
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
public static boolean turnOnLight() {
boolean flag = false;
try {
mCamera = Camera.open();
if (mCamera != null) {
Parameters params = mCamera.getParameters();
if (Build.MODEL.equals("GT-P1000")) {
params.setFlashMode(Parameters.FLASH_MODE_ON);
} else {
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
}
mCamera.setParameters(params);
mCamera.startPreview();
mCamera.autoFocus(new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
}
});
flag = true;
} else {
flag = false;
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
public static boolean turnOffLight() {
boolean flag = false;
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
flag = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
}
Got solution.
#Override
public void onBackPressed() {
super.onBackPressed();
params = camera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
isFlashOn = false;
if (camera!= null) {
camera.release();
camera= null;
}
Log.d("Camera","Back Pressed");
}
And removed all the code from onStop() and onPause() method.

Stop the flashlight after pressing back

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
}
}

Categories

Resources