I have 3 buttons on the UI. On, Off and SOS(flash at repeated intervals). If I press On and then the Off button the flash turns off as expected.But if I press SOS(it flashes as expected at regular intervals) and then Off it refuses to stop flashing. The code is as follows:
SOSbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
SOSon = true;
startSOS();
onSOSPress();
} catch (Exception ex) {
throw ex;
}
}
});
void onSOSPress() {
try {
Flashlight flashlight=new Flashlight();
SOSon = true;
flashlight.Flashthread = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < System.currentTimeMillis(); i++) {
while (!FlashThreadStop) {
if (FlashOn) {
myParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
try {
myCamera.setParameters(myParameters);
}
catch (Exception ex)
{
//logger.log(Level.SEVERE, "an exception was thrown", ex);
}
myCamera.stopPreview();
FlashOn = false;
} else {
TurnOnFlash();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
flashlight.Flashthread.start();
} catch (Exception ex) {
throw ex;
}
}
and the TurnOff mechanism is as follows:
off.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (FlashOn) {
// turn off flash
TurnOffFlash();
}
}
});
private void TurnOffFlash() {
if (FlashOn) {
if (myCamera == null || myParameters == null) {
return;
}
myParameters = myCamera.getParameters();
myParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
myCamera.setParameters(myParameters);
myCamera.stopPreview();
FlashOn = false;
}
}
void endSOS(){
FlashThreadStop=true;
}
void startSOS(){
FlashThreadStop=false;
}
EDIT: The method onSOSPress() has been updated to reflect the working SOS mode(OFF button works now)
Your TurnOffFlash method does not cover flash blinking very well. You are not stopping the thread so it continues flashing back and forth. You need to add one line to cover that part as well:
Flashthread.interrupt();
This way you'll keep your functionality turning off the flash, and if the thread is running the SOS mode, you'll stop it as well.
Side note: You're failing to follow the common Java nomenclature where methods and variables start with a lowercase letter and use camelCase.
Related
I am trying to build a Flashlight app with SOS features. Both features are working individually. But when I want to start the flashlight blinking it blinks but didn't work smoothly. Suppose :
Case 1: If I progress the seek bar flash starts to blinking that's good but if I want to change the seek bar progress during the Flash blinking, progress act like frizzed.
Case 2: during flash blinking, I can't stop the flash immediately.
Case 3: Individually both are working.
I have used threading for blinking the Flashlight. I am giving some code below. My motive is to build a flashlight with an SOS feature.
//When progress seekbar for SOS Flashlight
private void seekbarFunc(int val) {
String myString = "010101010101010101";
long blinkDelay = val + 500; //Delay in ms
new Thread(new Runnable() {
#Override
public void run() {
}
}).start();
for (int i = 0; i < myString.length(); i++) {
if (myString.charAt(i) == '0') {
Utilities.startFlashlight(this, mPreference);
} else {
Utilities.stopFlashlight(this, mPreference);
}
try {
thread.sleep(blinkDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// FlashLlight turned on by this method
private static boolean flashLightOn(Context context) {
try {
if (mCameraManager == null) {
initCameraManagerInstance(context);
}
String cameraId = mCameraManager.getCameraIdList()[0];
mCameraManager.setTorchMode(cameraId, true);
// Sending broadcast to update the UI
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(ACTION_UPDATE_UI));
} catch (CameraAccessException e) {
Log.e(TAG, "flashLightOn(): " + e);
return false;
}
return true;
}
//FlashLight turned off by this method
private static boolean flashLightOff(Context context) {
try {
if (mCameraManager == null) {
initCameraManagerInstance(context);
}
String cameraId = mCameraManager.getCameraIdList()[0];
mCameraManager.setTorchMode(cameraId, false);
// Sending broadcast to update the UI
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(ACTION_UPDATE_UI));
} catch (CameraAccessException e) {
Log.e(TAG, "flashLightOff(): " + e);
return false;
}
return true;
}
I have a project that deals with RFID Cards, After tapping the card on the RF Reader, It records the data and needs to run the RFCard Reader again. But my problem is after I tapped the card, The next card that will be tapped is can't read due to the CallBack(); hasn't run again.
I have tried this, after 3-5 times, the reader has stopped.
class myCallbackThread extends Thread{
#Override
public void run(){
try{
//my code of saving will be here...
myCallbackThread myCallbackThread = new myCallbackThread();
myCallbackThread.start();
}catch (Throwable e){
e.printStackTrace();
}
}
}
It This full code is a CallBack(); function. My problem is how can I Call it again to repeat the process after it has successfully executed?
class CallBackThread extends Thread {
#Override
public void run() {
try {
RFCardInterface.waitForCardPresent(RFCardInterface.CONTACTLESS_CARD_MODE_AUTO, 1, -1);
if (RFCardInterface.isCallBackCalled &&
RFCardInterface.notifyEvent.eventID == RFCardInterface.CONTACTLESS_CARD_EVENT_FOUND_CARD) {
IDCatcher = StringUtility.ByteArrayToString(RFCardInterface.notifyEvent.eventData,
RFCardInterface.notifyEvent.eventData.length);
IDCatcher = IDCatcher.substring(9, 21).replace(" ", "");
Log.e("IDCatcher", IDCatcher);
EventBus.getDefault().post(new EBTest2());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
How can I achieve to make it indefinite?. Thank you
EDIT Added my EBtest2()
#Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onEvent(EBTest2 ebTest2) {
Cursor c = dbhelper.getReadableDatabase().rawQuery("select is_arrived,is_closed from trans_settings order by _id desc limit 1", null);
if (c != null && c.moveToFirst()) {
try {
String is_arrived = c.getString(0);
String is_closed = c.getString(1);
if (is_arrived.equals("0") && is_closed.equals("0")) {
SearchEmp();
} else if (is_arrived.equals("1") && is_closed.equals("0")) {
SearchEmp_isArrived();
} else if (is_arrived.equals("1") && is_closed.equals("1")) {
SearchEmp_isClosed();
}
} catch (Throwable e) {
e.printStackTrace();
}
c.close();
}
}
I have read similar threads and haven't found an answer which would solve my problem.
I am writing an app with 2 different MediaRecorders. One for noise detection and another one for recording. What I want to do is - when the first MediaRecorder detects noise levels above 4.0 (I am using Google's SoundMeter class for detection) it will initiate another MediaRecorder and start recording. If the soundlevels stay below 4.0 for 10 seconds, then stop recording and keep listening. All of this is done in an AsynTask, in an endless while(true) loop, which will be broken, only if a corresponding button is clicked.
The detection is working fine, but the IllegalStateException is thrown when start() is called on the recording MediaRecorder.
Here is the AsyncTask:
private class NoiseDetection extends AsyncTask {
double currentSoundInputLevel;
#Override
protected Object doInBackground(Object[] params) {
int i = 0;
soundMeter = new SoundMeter();
try {
soundMeter.start();
} catch (IOException e) {
Log.e("error", e.getMessage());
}
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("error", e.getMessage());
}
if(isCancelled()){
soundMeter.stop();
if(currentlyRecording) {
soundRecorder.stop();
}
break;
}
currentSoundInputLevel = soundMeter.getAmplitudeEMA();
if(!currentlyRecording && currentSoundInputLevel > 4.0){
soundRecorder = new SoundRecorder();
try {
soundRecorder.start(getFileNameString());
currentlyRecording = true;
} catch (IOException e) {
Log.e("error", e.getMessage());
}
} else if(currentlyRecording && currentSoundInputLevel < 4.0) {
i++;
if(i > 10) {
soundRecorder.stop();
}
}
}
return null;
}
}
And here is the SoundRecorder:
public class SoundRecorder {
private MediaRecorder mRecorder = null;
public void start(String fileName) throws IOException {
if (mRecorder == null) {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mRecorder.setOutputFile(Environment.getExternalStorageDirectory().getPath() + "/" + fileName);
mRecorder.prepare();
mRecorder.start();
}
}
public void stop() {
if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
}
}
The exception is thrown on mRecorder.start();.
I think the problem lies within the idea of doing everything in this while loop, but I haven't come up with a better idea of achieving the forementioned goal.
Also, I have tried different OutputFormats and AudioEncoders without success. (reference to https://stackoverflow.com/a/23065021/1826152)
Another note, which could be of use, is the fact that the file is actually created in the sdcard dir.
The phone I am using for development is a Nexus 5. The permissions in android manifest are the following:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Update:
Right now I have tried to remove the SoundRecorder operations from the while loop by creating a RecordingHandler. The new code for the doInBackground() is as follows:
protected Object doInBackground(Object[] params) {
int i = 0;
soundMeter = new SoundMeter();
RecordingHandler recordingHandler = null;
try {
soundMeter.start();
} catch (IOException e) {
Log.e("error", e.getMessage());
}
while(true){
if(isCancelled()){
soundMeter.stop();
if(currentlyRecording && recordingHandler != null){
recordingHandler.kill();
}
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("error", e.getMessage());
}
if(!currentlyRecording && soundMeter.getAmplitudeEMA() > 4.0){
recordingHandler = new RecordingHandler(deviceId);
currentlyRecording = true;
recordingHandler.run();
}
}
return null;
}
and the RecordingHandler itself is the following:
public class RecordingHandler implements Runnable {
SoundRecorder soundRecorder;
SoundMeter soundMeter;
String deviceID;
boolean isKilled = false;
public RecordingHandler(String deviceID){
this.soundRecorder = new SoundRecorder();
this.soundMeter = new SoundMeter();
this.deviceID = deviceID;
}
#Override
public void run() {
int i = 0;
try {
soundMeter.start();
soundRecorder.start(getFileNameString());
} catch (IOException e) {
Log.e("error", e.getMessage());
}
while(true){
if(isKilled){
break;
}
if(soundMeter.getAmplitudeEMA() < 4.0){
i++;
if(i > 10){
break;
}
} else {
i = 0;
}
}
soundMeter.stop();
soundRecorder.stop();
EavesDrop.currentlyRecording = false;
}
public void kill(){
this.isKilled = true;
}
private String getFileNameString() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
return deviceID + "_" + sdf.format(new Date());
}
}
Now the IllegalStateException is thrown from the Recordinghandler - on the line soundMeter.start();.
Considering that this soundMeter object is basically not handled in a loop anymore, should eliminate the though that the while loop was the culprit. Is there something that I am missing? Could the problem be in having multiple MediaRecorders working at the same time? As you can see, now it is the SoundMeter, not the SoundRecorder which is throwing the exception. Actually - whichever start() call I place first in the RecordingHandler, throws the same IllegalStateException.
The question might be connected to Android: Two instances of Media recorder at same time, which unfortunately has no answers.
Any further help would be greatly appreciated!
Okay, it seems I cracked the problem. The problem seems to be in having multiple instances of MediaRecorder working at the same time. What I did, was that I now don't use separate classes for detection and recording, so that the recorder now does it's own detection.
At first I initiate the inital SoundMeter which listens until it gets input over level 4.0. Then I stop the initial SoundMeter and make a new SoundMeter (with different output directory), which starts recording and records until the levels have been below 4.0 for apprixamtely 10 seconds. Then the second SoundMeter is stopped and the background task can start the initial SoundMeter again.
Here is the code which solved my problem,
AsyncTask:
protected Object doInBackground(Object[] params) {
int i = 0;
soundMeter = new SoundMeter();
RecordingHandler recordingHandler = null;
try {
soundMeter.start("/dev/null");
} catch (IOException e) {
Log.e("error", e.getMessage());
}
while(true){
if(isCancelled()){
soundMeter.stop();
if(currentlyRecording && recordingHandler != null){
recordingHandler.kill();
}
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("error", e.getMessage());
}
if(!currentlyRecording && soundMeter.getAmplitudeEMA() > 4.0){
soundMeter.stop();
recordingHandler = new RecordingHandler(deviceId);
currentlyRecording = true;
recordingHandler.run();
} else if(!currentlyRecording && !soundMeter.isRunning()){
try {
soundMeter.start("/dev/null");
} catch (IOException e) {
Log.e("error", e.getMessage());
}
}
}
return null;
}
}
And the RecordingHandler.run():
#Override
public void run() {
int i = 0;
try {
soundMeter.start(getFileNameString());
} catch (IOException e) {
Log.e("error", e.getMessage());
}
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("error", e.getMessage());
}
if(isKilled){
break;
}
if(soundMeter.getAmplitudeEMA() < 4.0){
i++;
if(i > 10){
break;
}
} else {
i = 0;
}
}
soundMeter.stop();
EavesDrop.currentlyRecording = false;
}
The documentation at http://developer.android.com/reference/android/media/MediaRecorder.html , under the release() method documentation, it talks about multiple instances not being suppported on some devices. So it might be a specific device related problem.
Iam making app for listening .mp3 words in greek language so i have mediaplayer and after lets say 1000ms it should display next word depends on .mp3 file so i have 3 functions play, pause and stop.. I need to pause thread and then continue when it ends. In my thread is not working pause method by calling notify i simply dont know how to lock object before calling notify().. Here is my Code i would be rly glad for every help..
class MyinnerThread implements Runnable {
String name;
Thread tr;
boolean suspendFlag;
int i = 0;
MyinnerThread(String threadname) {
name = threadname;
tr = new Thread(this, name);
suspendFlag = false;
tr.start();
}
public void run() {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
if(i == 0){tv1.setText("trhead1");}
if(i == 1){tv2.setText("trhead2");}
if(i == 2){tv3.setText("trhead3");}
if(i == 3){tv4.setText("trhead4");}
if(i == 4){tv5.setText("trhead5");}
if(i == 5){tv6.setText("trhead6");}
if(i == 6){tv7.setText("trhead7");}
if(i == 7){tv8.setText("trhead8");}
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(this) {
while(suspendFlag) {
try {
tr.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
i++;
}
});
Thread.sleep(200);
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
tr.notify();
}
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.play:
if(mp.isPlaying()){
mp.pause();
play.setBackgroundResource(R.drawable.play);
t.mysuspend();
Toast.makeText(getApplicationContext(), "Pause", Toast.LENGTH_SHORT).show();
}
else if(!mp.isPlaying()){
mp.start();
if(runningThread){
t.myresume();
}
if(!runningThread){
runningThread = true;
t = new MyinnerThread("name");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Toast.makeText(getApplicationContext(), "Play", Toast.LENGTH_SHORT).show();
play.setBackgroundResource(R.drawable.pause);
}
break;
case R.id.stop:
Toast.makeText(getApplicationContext(), "Stop", Toast.LENGTH_SHORT).show();
mp.release();
Thread.currentThread().interrupt();
t = null;
runningThread = false;
setPlayer();
play.setBackgroundResource(R.drawable.play);
break;
}
}
I'm trying to create a speech recognition app where the app recieves voice and sends out stuff. I'd like everything that the onEndOfSpeech method to be called to wait a second and then do the entire voice recognition intent to start over again.
public void onEndOfSpeech() {
Log.d("Speech", "onEndOfSpeech");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
}
Not sure that I am doing this correctly.
Thanks!
This is how it should be
try {
Thread.sleep(3000);
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
} catch (InterruptedException e) {
// it depends on your app logic what to do with InterruptedException, you can process it or rethrow or restore interrupted flag
}
Try this code
protected boolean _active = true;
// time to display the splash screen in ms
protected int _splashTime = 1000;
Thread splashThread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
while(_active && (waited < _splashTime)) {
sleep(100);
if(_active) {
waited += 100;
}
}
} catch(InterruptedException e) {
e.printStackTrace();
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
}