I dont find an answer on google or i dont get the right words for it.
So the SpeechRecognizer works fine.
But when i hear the beep (i use it without the google dialog) and i say nothing for about 3 seconds or more, its like the recognizer do nothing and fade away, no second beep to hear, no onResult(), no EndofSpeech.
So what happend when the Recognizer is listening and you say nothing? Which method get fired?
EDIT: After all it works, big thanks to OpiateFuchs and his realy good comments and answers. I edit the simplified code that way, that you guys can see how to make it.
onPartialResult() is called often even if you say nothing, but when this happen the partialResult String is empty, so if its empty you know nothing was spoken.
(Idea from OpiateFuchs)
Thats my simplified Code which is important for the Recognizer:
public Constructor (){
speech = SpeechRecognizer.createSpeechRecognizer(context);
speech.setRecognitionListener(this);
recogIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recogIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "de");
speech.startListening();
}
public void startListening(){
speech.startListening(recogIntent);
if(timerRunning==false){
setcdt();
mCountDownTimer.start();
timerRunning=true;
}
}
#Override
public void onReadyForSpeech(Bundle params) {
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onRmsChanged(float rmsdB) {
}
#Override
public void onBufferReceived(byte[] buffer) {
}
#Override
public void onEndOfSpeech() {
Toast.makeText(c, "work", Toast.LENGTH_SHORT);
//too see if its called
}
#Override
public void onError(int error) {
}
#Override
public void onResults(Bundle results) {
ArrayList<String> matches = results
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
Toast.makeText(c, matches.get(0), Toast.LENGTH_LONG).show();
speech.cancel();
analyse(matches.get(0));
m.next(); //calls the Recognizer again
}
#Override
public void onPartialResults(Bundle partialResults) {
ArrayList<String> matches = partialResults
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if(matches.get(0).length() == 0){
m.tv.append("nothing"); //show on textview
}
else{
m.tv.append("cancel timer "); //show on textview
mCountDownTimer.cancel();
hasSpoken = true;
timerRunning = false;
}
}
#Override
public void onEvent(int eventType, Bundle params) {
}
//innerclass
public class FinishSpeechRecognizerTimer extends CountDownTimer {
public FinishSpeechRecognizerTimer(long startTime, long interval){
super(startTime,interval);
}
#Override
public void onFinish(){
timerRunning = false;
if (hasSpoken==false){
m.tv.append("nospeak ");
speech.cancel();
m.tv.append("listen again after no speak ");
startListening();
}
}
#Override
public void onTick(long millisUntilFinish){
}
}
public void setcdt(){
startTime = 5000;
interval = 4000; //want no onTick - interval > startTime
timerRunning = false;
hasSpoken = false;
mCountDownTimer = new FinishSpeechRecognizerTimer(startTime, interval);
}
For this discussion I try to provide an example from scratch which should lead you into the right direction. As said in the comments, it seems that the SpeechRecognition does not stop from itself if nothing is said, so you simply could implement a CountDownTimer for example and finish the SpeechRecognizer after a certain time:
make global SpeechRecognizer (like you have done), boolean and CountdownTimer objects :
private SpeechRecognizer speech;
private boolean hasSpoken=false;
private CountDownTimer mCountDownTimer;
private long startTime = 30000L;
private long interval = 1000L;
private boolean timerRunning = false;
extend the CountDownTimer class:
public class FinishSpeechRecognizerTimer extends CountDownTimer{
public FinishSpeechRecognizerTimer(long startTime, long interval){
super(startTime,interval);
}
#Override
public void onFinish(){
if(hasSpoken==false){
speech.cancel();
}
timerRunning=false;
}
#Override
public void onTick(long millisUntilFinish){
//do whatever you want to do
}
}
initialize
speech = SpeechRecognizer.createSpeechRecognizer(yourContext);
mCountDownTimer = new FinishSpeechRecognizerTimer(startTime, interval);
start it and at the same time start the CountDownTimer:
speech.startListening(recogIntent);
if(timerRunning==false){
mCountDownTimer.start();
timerRunning=true;
}
And as soon as something is spoken, set the boolean value hasSpoken to true and cancel the timer:
#Override
public void onBeginningOfSpeech() {
hasSpoken=true;
mCountDownTimer.cancel();
timerRunning=false;
}
As I said, it´s from scratch, can´t guarantee that this is working. This example starts the CountDownTimer for 30 seconds and checks every second if something is spoken. How long you want to wait is up to you.
EDIT
Turns out that in some cases the onBeginOfSpeech() method is called multiple times without anybody is speaking. For everyone who is interested:
instead of doing that stuff in onBeginOfSpeech(), you can use the method onPartialResult():
#Override
public void onPartialResults(Bundle partialResults) {
ArrayList<String> matches = results
.getStringArrayList(SpeechRecognizer.RESULT_RECOGNITION);
if(matches.size()==0){
hasSpoken=false;
}else{
hasSpoken=true;
mCountDownTimer.cancel();
timerRunning=false;
}
}
Related
When the app launch, I have a button (btn1) and a timer starting (long start = System.nanoTome();).
Now, two things can happen:
either the button is clicked at any time BEFORE the time limit of 1 minute (do some code_A then)
or the timer (long elapsedTime = System.nanoTome() - start;) reaches the time limit of 1 minute (do some code_B then)
I have tried lots of various combinations, but I stuck on the logic with regard to the time dimension and the if/while or whatever loop that would express/trigger BOTH the time condition OR the action condition (button btn1 pressed) in parallel.
Does anybody have an idea? That would be of great help.
You can use the CountDownTimer: https://developer.android.com/reference/android/os/CountDownTimer
CountDownTimer countDownTimer = new CountDownTimer(10000, 1000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
codeB();
}
}.start();
Button button = new Button(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
countDownTimer.cancel();
codeA();
}
});
This will create a timer with the length of 10 seconds and the onTick method is called every 1 second.
new CountDownTimer(timerLength, tickInterval)
To further visualize your question in the comments, whether the timer stops or not:
In this screenshot, I've let the timer run out. The timer was set to 5 seconds and after 5 seconds onFinish() was called, as seen by the message.
In this screenshot, I've cancelled the timer through the onClickListener, as you can see there is no message in the center, thus onFinish() hasn't been called.
You can use CountDownTimer and handle the state there, then invoke the proper method depending on the state:
Kotlin version:
class MyCountdownTimer: CountDownTimer(60000, 1000) {
private var state: CountdownState = CountdownState.IDLE
override fun onFinish() {
state = CountdownState.FINISHED
}
override fun onTick(p0: Long) {
if(state == CountdownState.IDLE) {
state = CountdownState.COUNTING
}
}
fun getState(): CountdownState {
return state
}
}
enum class CountdownState {
IDLE, COUNTING, FINISHED
}
And in your code:
val countdownTimer = MyCountdownTimer()
btn1.setOnClickListener {
countdownTimer.start()
}
btn2.setOnClickListener {
if(countdownTimer.getState() == State.RUNNING) {
callMethodWhenRunning()
} else if (countdownTimer.getState == State.FINISHED) {
callMethodWhenFinished()
}
}
Java version:
import android.os.CountDownTimer;
public class MyCountdownTimer extends CountDownTimer {
private CountdownState state = CountdownState.IDLE;
public MyCountdownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long l) {
if(state == CountdownState.IDLE) {
state = CountdownState.COUNTING;
}
}
#Override
public void onFinish() {
state = CountdownState.FINISHED;
}
public CountdownState getState() {
return state;
}
}
enum CountdownState {
IDLE, COUNTING, FINISHED
}
and usage:
MyCountdownTimer timer = new MyCountdownTimer(60000, 1000);
btn1.setOnClickListener(view -> {
timer.start();
});
btn2.setOnClickListener(view -> {
if(timer.getState() == State.RUNNING) {
callMethodWhenRunning();
} else if (timer.getState == State.FINISHED) {
callMethodWhenFinished();
}
});
I know that there is a lot of examples, but I can't still make it work.
I need to monitor Boolean value, which change to True, when phone is connected to proper wifi.
Wifi connection and check is done in second thread. Maybe there is problem? I've tried many solutions, and can't get it done.
Wrapper class for variable:
import java.util.ArrayList;
import java.util.List;
public class ConnectivityStatus {
private Boolean status = Boolean.FALSE;
private ConnectivityListener listener;
public Boolean getStatus(){
return status;
}
public void setStatus(Boolean status){
this.status = status;
if(status) {
listener.onChange();
}
}
public void addConnectivityListener(ConnectivityListener l) {
this.listener = l;
}
interface ConnectivityListener{
void onChange();
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
...
private ConnectivityStatus mConnectionStatus;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mConnectionStatus = new ConnectivityStatus();
...
connectButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startLoadingScreen();
connectToCamera(mWifiManager);
new Thread(new Runnable() {
public void run() {
long startTime = System.currentTimeMillis();
for(int i = 0; i<=6; i++) {
mConnectionStatus.setStatus(checkWifiSsid(mWifiManager, startTime));
if(mConnectionStatus.getStatus()) {
break;
}
}
}
});
}
});
mConnectionStatus.addConnectivityListener(new ConnectivityStatus.ConnectivityListener() {
#Override
public void onChange(){
openWebView();
}
});
}
I didn't notice earlier but, yes, you're missing something from your threading. You're creating a new thread but you're not telling it to start:
new Thread(new Runnable(){
public void run(){
// Optionally, you can also use log messages for debugging
Log.d("MY_LOG_TAG", "Some message to look for in the log.");
// ...
}
}).start(); // Make sure to tell it to start
i have code block as below shown. for examaple Can i work this code three times?
when i used for loop or other loops. it isnt performed i wanted process.
new CountDownTimer(3000,1000) {
#Override
public void onTick(long l) {
gostertext.setText(""+l/1000);
durumgoster.setText("KOŞ..");
}
#Override
public void onFinish() {
gostertext.setText("KOŞU bitti YÜRÜ");
CountDownTimer counter=new CountDownTimer(3000,1000) {
#Override
public void onTick(long l) {
gostertext.setText(""+l/1000);
durumgoster.setText("YÜRÜ..");
}
#Override
public void onFinish() {
gostertext.setText("bitti");
}
}.start();
}
}.start();
when a counter ended, other counter will start that will perform three times.
i writed code as over shown that is worked but i want to perform three times.
Can we solve this problem?
why not make the loops contents into 1 void,
and call it three times?
You could do something like(untested):
int countCounter = 0;
CountDownTimer mCountDownTimer = new CountDownTimer() {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
if (countCounter < 3){
countCounter++;
// cancel the counter and restart it!
mCountDownTimer.cancel();
mCountDownTimer.start();
}
}
};
Hi i am trying to cancel a countdown timer in On-tick function, It is working fine in lollipop but not working in Kitkat and below. How cancel it from a OnTick() function.
private void startTimer(final int minuti) {
countDownTimer = new CountDownTimer(60 * minuti * 1000 + sec * 1000,
500) {
#Override
public void onTick(long leftTimeInMilliseconds) {
CountDownTimer.cancel();
}
#Override
public void onFinish() {
}
}.start();
}
Somehow if you call countdowntimer.cancel of a CountDownTimer object in its own onTick method it won't work!
The simplest way to solve your problem is defining another CountDownTimer, same as the main one, in order to check the condition to call countdowntimer.cancel. The point is that you are calling objects cancel method from outside of its own onTick method.
Check the example below:
CountDownTimer countdowntimer;
CountDownTimer assist;
long millisuntillfinish = 10000;
int interval = 100;
countdowntimer = new CountDownTimer(millisuntillfinish, interval) {
#Override
public void onTick(long millisUntilFinished) {
// if(true) countdowntimer.cancel(); (doesnt work)
}
#Override
public void onFinish() {
}
};
assist = new CountDownTimer(timertillfinish, timerinterval) {
#Override
public void onTick(long millisUntilFinished) {
if (true) {
countdowntimer.cancel();
}
}
#Override
public void onFinish() {
assist.cancel();
}
};
I know this question is more than 6 years old, but calling super.cancel(); within onTick() did the trick for me.
Leaving this here for the next unfortunate soul looking for an answer to this question.
ie.
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
if(someCondition)
super.cancel();
}
public void onFinish() {
//do something else
}
}.start();
new CountDownTimer(time, 1000) {
public void onTick(long millisUntilFinished) {
if (((millisUntilFinished/1000)%5)==0){ //every 5 sec
if(true)
{
this.cancel();
}
}
}
public void onFinish() {
//do somethhing
}
}.start();
I have been looking around and I have found this post where they call to the cancel() method in the onTick() using an alternative to the Android countDownTimer.
I had also this problem, and I created a global variable of a countDownTimer and I called to the cancel method in the activity when I needed, like myCountDownTimer.cancel().
private CountDownTimer mCountDownTimer;
private CountDownTimer createTimer(){
return new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
//do what you want
}
public void onFinish() {
//do what you want
}
}.start();
}
In your activity call:
mCountDownTimer = this.createTimer();
And if you want to cancel it:
mCountDownTimer.cancel();
I am creating a sound board and after clicking about 30 different sounds it stops working; I believe android is running out of memory. Below is my code. How can I implement .release() so that when the sound is done playing it is released? I don't really care if two things play at the same time; the clips are t0o short for this to be possible. I would just like to get my code set.
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.start();
}
});
I have done a lot of searching around but due to my lack of java/android knowledge I have not been able to get anything to work. Thanks in advance, let me know if anyone needs anymore code.
I left a comment, but I'll post an answer to show what I mean anyway...
The idea is that you have a set number of MediaPlayer instances that you can use. That way you never exceed the maximum number of instances. The array should be the length of the number of concurrent sounds you expect to be able to hear. If the sounds are local files, the length of time it takes to prepare the sounds should be almost negligible, so calling create inside the click handler should not result in terrible performance. Each of your buttons is associated with a particular resource, I suppose, so I set up a helper method to create and play the sounds for each button in the same way.
public class soundPageOne extends Activity {
private MediaPlayer[] mPlayers = new MediaPlayer[2];
private int mNextPlayer = 0;
#Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
Button playSound1 = (Button)this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startSound(R.raw.peter1);
}
});
}
public void onDestroy() {
super.onDestroy(); // <---------------------- This needed to be there
for (int i = 0; i < mPlayers.length; ++i)
if (mPlayers[i] != null)
try {
mPlayers[i].release();
mPlayers[i] = null;
}
catch (Exception ex) {
// handle...
}
}
private void startSound(int id) {
try {
if (mPlayers[mNextPlayer] != null) {
mPlayers[mNextPlayer].release();
mPlayers[mNextPlayer] = null;
}
mPlayers[mNextPlayer] = MediaPlayer.create(this, id);
mPlayers[mNextPlayer].start();
}
catch (Exception ex) {
// handle
}
finally {
++mNextPlayer;
mNextPlayer %= mPlayers.length;
}
}
}
Create a class, say AudioPlayer with a SoundPool variable. Setup a constructor to initialise the AudioPlayer object and create a Play method. SoundPool works better for short sounds played many times and does not require you to release.
public class AudioPlayer {
private SoundPool sPool = new SoundPool(Integer.MAX_VALUE, AudioManager.STREAM_MUSIC, 0);
public AudioPlayer(Context c, int id){
sounds.put("1",sPool.load(c, id, 1));
}
public void play(Context c) {
sPool.play("1", 1, 1, 1, 0, 1f);
}
}
So your class should look like
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final AudioPlayer ap = new AudioPlayer(this, R.raw.sound);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ap.play();
}
});
Could you use a MediaPlayer.OnCompletionListener?
Something like:
public class soundPageOne extends Activity implements MediaPlayer.OnCompletionListener {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
//***set the listener here***
pg1.setOnCompletionListener(this);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.start();
}
});
}
//***this code will be executed once the sound finishes playing***
#Override
public void onCompletion(MediaPlayer mp) {
//log messages, other things can go here
mp.release();
}
Try something like this
Your activity class:
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final AudioPlayer pg1 = new AudioPlayer();
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.play(this, R.raw.sound);
}
});
}
This is another Java Class:
public class AudioPlayer {
private MediaPlayer mPlayer;
public void stop() {
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
public void play(Context c, int sound) {
stop();
mPlayer = MediaPlayer.create(c, sound);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stop();
}
});
mPlayer.start();
}
public boolean isPlaying() {
return mPlayer != null;
}
}