So, I have a boolean called nuanceWaiting it's initially set to true. I immediate run a runnable loop that checks if nuanceWaiting is true or false.
protected void onCreate(Bundle savedInstanceState) {
...
nuanceWaiting = true;
...
}
#Override
protected void onStart() {
....
soundMeterLoop();
}
public void soundMeterLoop() {
soundMeterHandler = new Handler();
soundMeterRunnable = new Runnable() {
#Override
public void run() {
if(nuanceWaiting) {
//do my stuff
amplitude = soundMeter.getAmplitude();
if (amplitude > threshold) {
decibelLevelOutput.setTextColor(Color.RED);
startNuance();
} else {
decibelLevelOutput.setTextColor(Color.BLACK);
}
}
soundMeterHandler.postDelayed(this, 100);
}
};
soundMeterHandler.postDelayed(soundMeterRunnable, 100);
}
public void startNuance() {
nuanceWaiting = false;
nuance.toggleReco();
}
public void stopNuance() {
Log.d("SpeechKit", "stopNuance");
nuanceWaiting = true;
Log.d("SpeechKit", "nuanceWaiting " + nuanceWaiting);
}
Now, for some reason, once I call false, now, nuance.toggleReco() goes to another class and when it's finished, it calls stopNuance();
nuanceWaiting becomes false (showing in the second log), but when I check a log in the runnable, it still says true and never "stays" false when running the runnable again. Any idea as to why it doesn't stick to being false?
Below is what nuance.toggleReco(); does
public void toggleReco() {
Log.d("SpeechKit", "In "+state);
switch (state) {
case IDLE:
recognize();
break;
case LISTENING:
stopRecording();
break;
case PROCESSING:
cancel();
break;
}
}
It's usually in the IDLE state, so I'll follow that method,
private void recognize() {
//Setup our ASR transaction options.
Transaction.Options options = new Transaction.Options();
options.setRecognitionType(RecognitionType.DICTATION);
options.setDetection(DetectionType.Short);
options.setLanguage(new Language("eng-USA"));
options.setEarcons(startEarcon, stopEarcon, errorEarcon, cancelEarcon);
//Start listening
recoTransaction = session.recognize(options, recoListener);
}
private Transaction.Listener recoListener = new Transaction.Listener() {
#Override
public void onStartedRecording(Transaction transaction) {
Log.d("SpeechKit", "onStartedRecording");
//We have started recording the users voice.
//We should update our state and start polling their volume.
state = State.LISTENING;
startAudioLevelPoll();
}
#Override
public void onFinishedRecording(Transaction transaction) {
Log.d("SpeechKit", "onFinishedRecording");
//We have finished recording the users voice.
//We should update our state and stop polling their volume.
state = State.PROCESSING;
stopAudioLevelPoll();
avatar.stopNuance();
}
#Override
public void onRecognition(Transaction transaction, Recognition recognition) {
//We have received a transcription of the users voice from the server.
state = State.IDLE;
Log.d("SpeechKit", "onRecognition: " + recognition.getText());
voiceRecognizeText = recognition.getText();
voiceRecognize = (TextView) activity.findViewById(R.id.voiceRecognize);
voiceRecognize.setText(voiceRecognizeText);
}
#Override
public void onSuccess(Transaction transaction, String s) {
Log.d("SpeechKit", "onSuccess");
//Notification of a successful transaction. Nothing to do here.
}
#Override
public void onError(Transaction transaction, String s, TransactionException e) {
Log.e("SpeechKit", "onError: " + e.getMessage() + ". " + s);
//Something went wrong. Ensure that your credentials are correct.
//The user could also be offline, so be sure to handle this case appropriately.
//We will simply reset to the idle state.
state = State.IDLE;
avatar.stopNuance();
}
};
Related
I have trouble ending an AsyncTask, even though IMHO, I have adhered to the recommended flagging practice. The code below only takes the BackButton into account, but to have a general solution for all kinds of exiting the activity would be best.
I have a MeasurementLoadingsScreen Class which binds a Service like this:
ServiceConnection _connection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
_service = myService.Stub.asInterface(iBinder);
runMeasurementAsyncTask();
}
public void onServiceDisconnected(ComponentName componentName) {
_service = null;
}
};
#Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent();
serviceIntent.setPackage(myService.class.getPackage().getName());
serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_measurement_loadingscreen);
findViewsById();
setDefaultVisibility();
intent = getIntent();
//myStuff
}
The MeasurementLoadingScreen contains an AsyncTask with a WeakReference (or SoftReference, tried both).
private void runMeasurementAsyncTask() {
//myStuff
meTask = new MeasurementTask(this);
meTask.execute();
}
private static class MeasurementTask extends AsyncTask<Integer, Integer, String> {
private WeakReference<MeasurementLoadingScreen> activityReference;
private ServiceHelper serviceHelper;
//myStuff
public static boolean isRunning = false;
MeasurementTask(MeasurementLoadingScreen context) {
activityReference = new WeakReference<>(context);
serviceHelper = new ServiceHelper(context._service);
}
#Override
protected String doInBackground(Integer... params) {
MeasurementLoadingScreen activityReference = this.activityReference.get();
isRunning = true;
//myStuff, it's ok to finish running this before cancelling
if (isCancelled()) {
return "cancelled";
}
// more myStuff
if (isCancelled()) {
return "cancelled";
}
[...]
#Override
protected void onCancelled(){
//myStuff: safely shutdown measurement process, might take a few seconds at worst
meTask.isRunning = false;
if(activityReference.get() != null) {
activityReference.get().finish(); //it does not work without this, either
}
super.onCancelled();
}
When I tap back twice (regardless of specific behaviour), it should (safely) abort the AsyncTask:
#Override
public void onBackPressed()
{
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
if (meTask == null) {
super.onBackPressed();
return;
}
cancelTask();
Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
#Override
protected void onStop() {
super.onStop();
if (_connection != null)
unbindService(_connection);
finish();//
}
#Override
public void onPause() {
int i = 0;
super.onPause();
//poll state of task here
finish();
}
I cannot seem to get the Task to stop running. If I set the meTask =null; in onPause, for example, it will eventually go through onCancelled and then call onStop, ending the service as well. But there is no way of waiting for the onCancelled to do its stuff and notify me with the isRunningflag, getStatus or whatever. The app just freezes however I poll the Task, which stays RUNNING all the time, unless I set it to null (undesirable, of course).
Edit:
I have added a polling attempt that allows the activity to call onPause/onStop eventually, but my main issue is with the polling, I do not ever see a finished/finishing task, even though onCancelled gets called at some point, but only after I set the meTask = null;, it does not continue cancelling normally.
public void onBackPressed() {
int i=0;
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
if (meTask == null) {
super.onBackPressed();
return;
}
cancelTask();
Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
while ((meTask.getStatus()== AsyncTask.Status.RUNNING) && (i < 20000)) {
//waiting etc., checking für isRunning doesn't work either
i++;
}
Log.d(TAG, "meTask " + meTask.getStatus());
meTask = null;
Log.d(TAG, "meTask null after " + i);
super.onBackPressed();
return;
Edit 2:
Content of cancelTask()
private void cancelTask() {
if (meTask != null) {
Log.d(TAG, "Async Task Cancel... ");
meTask.cancel(true);
}
}
Edit 3:
Regardless of where I put the cancel(true), e.g. onPause, onStop, the Task stays alive and only gives me the Log output of
if (isCancelled()) {
Log.d(TAG, "Cancel after XYZ");
return "cancelled";
}
and
#Override
protected void onCancelled() {
super.onCancelled();
isRunning = false;
Log.d(TAG, "...Async Task Cancelled ");
}
at the very end, after onPause, onStop, onDestroy have finished. I am at my wits end. It is not surprising that the Task continues to run for a bit, but it must stop before the service in unbound. How can I wait for the task to finish?
I'm trying to access three sensors simultaneously. I need the accelerometer data to detect if the person is running, walking or standing still and MIC and CAMERAMIC data as input to an adaptive filter.
I tried to use threads, one thread for each sensor, but they don't really work in parallel.
//declaring 3 threads
public class firstMicThread implements Runnable {
public void run() {
isRecording = true;
Log.i("Thread 1 ", "first thread started" + String.valueOf(isRecording));
startRecording(audiosource);
}
}
public class secondMicThread implements Runnable {
public void run() {
isRecording = true;
Log.i("Thread 2 ", "second thread started" + String.valueOf(isRecording));
startRecording(audiosource2);
}
}
public class accelerometerThread implements Runnable {
public void run() {
isRecording = true;
Log.i("Thread 3 ", "acceletometer started " + String.valueOf(isRecording));
// onResume();
sensorManager.registerListener( RecordandStore.this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL );
Log.i("Thread 3 ", "acceletometer listener registered" + String.valueOf(isRecording));
}
}
and
private View.OnClickListener btnClick = new View.OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_startrec: {
if (checkpermissionfromdevice()) {
Log.i("Start click:", "permissions true");
// first mic
Runnable firstmicR = new firstMicThread();
Thread firstmicthread = new Thread( firstmicR);
// second mic
Runnable secondmicR = new secondMicThread();
Thread secondmicthread = new Thread( secondmicR);
// accelerometer
Runnable acceletometerR = new accelerometerThread();
Thread accelerometerthread = new Thread(acceletometerR);
firstmicthread.start();
secondmicthread.start();
accelerometerthread.start();
startrec.setEnabled(false);
stoprec.setEnabled(true);}
else { // if check permissionfordevice == false
requestPermission();
}
break;}
In my application I want use service for get request to server.
I should run this service for always and not stop it!
I write below code in service, but just show for 5 time and when receive to 5 step. then not show Toast!
But I want always getData() and show Toast.
Service class :
public class NotifyService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
new Thread(new Runnable() {
#Override
public void run() {
//Your logic that service will perform will be placed here
//In this example we are just looping and waits for 5000 milliseconds in each loop.
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(5000);
} catch (Exception e) {
}
if (isRunning) {
ExploreSendData sendData = new ExploreSendData();
sendData.setPageIndex(1);
sendData.setPageSize(10);
sendData.setShowFollows(false);
sendData.setShowMovies(true);
sendData.setShowNews(true);
sendData.setShowReplies(false);
sendData.setShowSeries(true);
sendData.setShowSuggestions(false);
InterfaceApi api = ApiClient.getClient().create(InterfaceApi.class);
Call<ExploreResponse> call = api.getExplore(new SharedPrefrencesHandler(NotifyService.this)
.getFromShared(SharedPrefrencesKeys.TOKEN.name()), sendData);
call.enqueue(new Callback<ExploreResponse>() {
#Override
public void onResponse(Call<ExploreResponse> call, Response<ExploreResponse> response) {
if (response.body().getData() != null && response.body().getStatusCode() != 401
&& response.body().getStatusCode() != 402) {
Toast.makeText(NotifyService.this, "Test Show message ever 5second", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ExploreResponse> call, Throwable t) {
}
});
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
I copy this service code from internet, but just show 5times. I want show always.
How can I edit my codes and fix it? Please help me. Thanks
The problem is not in the service, services start and continue living as long as the app is alive and android doesn't kill it. For an infinite loop replace the "for loop" with "While loop". The below loop doesn't end.
while (true) {
......
......
......
}
I want to create a simple app which runs in the background using a service.
Using SpeechRecognizer it would listen for application names, and when it finds existing one it would open it. Also if it does not find coincidence or the result is not clear, it would suggest some options showing them in a list or via voice.
I already know how to use SpeechRecognizer, but what I would need is to set this service to maintain running on background and avoid it from being killed. Could this be done?
In addition to all this, I'd add at least this point:
SpeechRecognizer is better for hands-free user interfaces, since your app actually gets to respond to error conditions like "No matches" and perhaps restart itself. When you use the Intent, the app beeps and shows a dialog that the user must press to continue.
My summary is as follows:
SpeechRecognizer
Show different UI or no UI at all. Do you really want your app's UI to beep? Do you really want your UI to show a dialog when there is an error and wait for user to click?
App can do something else while speech recognition is happening
Can recognize speech while running in the background or from a service
Can Handle errors better
Can access low level speech stuff like the raw audio or the RMS. Analyze that audio or use the loudness to make some kind of flashing light to indicate the app is listening
Intent
Consistent, and easy to use UI for users
Easy to program
This is a work around for android version 4.1.1.
public class MyService extends Service
{
protected AudioManager mAudioManager;
protected SpeechRecognizer mSpeechRecognizer;
protected Intent mSpeechRecognizerIntent;
protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this));
protected boolean mIsListening;
protected volatile boolean mIsCountDownOn;
private boolean mIsStreamSolo;
static final int MSG_RECOGNIZER_START_LISTENING = 1;
static final int MSG_RECOGNIZER_CANCEL = 2;
#Override
public void onCreate()
{
super.onCreate();
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechRecognizer.setRecognitionListener(new SpeechRecognitionListener());
mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
this.getPackageName());
}
protected static class IncomingHandler extends Handler
{
private WeakReference<MyService> mtarget;
IncomingHandler(MyService target)
{
mtarget = new WeakReference<MyService>(target);
}
#Override
public void handleMessage(Message msg)
{
final MyService target = mtarget.get();
switch (msg.what)
{
case MSG_RECOGNIZER_START_LISTENING:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
// turn off beep sound
if (!mIsStreamSolo)
{
mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true);
mIsStreamSolo = true;
}
}
if (!target.mIsListening)
{
target.mSpeechRecognizer.startListening(target.mSpeechRecognizerIntent);
target.mIsListening = true;
//Log.d(TAG, "message start listening"); //$NON-NLS-1$
}
break;
case MSG_RECOGNIZER_CANCEL:
if (mIsStreamSolo)
{
mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, false);
mIsStreamSolo = false;
}
target.mSpeechRecognizer.cancel();
target.mIsListening = false;
//Log.d(TAG, "message canceled recognizer"); //$NON-NLS-1$
break;
}
}
}
// Count down timer for Jelly Bean work around
protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000)
{
#Override
public void onTick(long millisUntilFinished)
{
// TODO Auto-generated method stub
}
#Override
public void onFinish()
{
mIsCountDownOn = false;
Message message = Message.obtain(null, MSG_RECOGNIZER_CANCEL);
try
{
mServerMessenger.send(message);
message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);
mServerMessenger.send(message);
}
catch (RemoteException e)
{
}
}
};
#Override
public void onDestroy()
{
super.onDestroy();
if (mIsCountDownOn)
{
mNoSpeechCountDown.cancel();
}
if (mSpeechRecognizer != null)
{
mSpeechRecognizer.destroy();
}
}
protected class SpeechRecognitionListener implements RecognitionListener
{
#Override
public void onBeginningOfSpeech()
{
// speech input will be processed, so there is no need for count down anymore
if (mIsCountDownOn)
{
mIsCountDownOn = false;
mNoSpeechCountDown.cancel();
}
//Log.d(TAG, "onBeginingOfSpeech"); //$NON-NLS-1$
}
#Override
public void onBufferReceived(byte[] buffer)
{
}
#Override
public void onEndOfSpeech()
{
//Log.d(TAG, "onEndOfSpeech"); //$NON-NLS-1$
}
#Override
public void onError(int error)
{
if (mIsCountDownOn)
{
mIsCountDownOn = false;
mNoSpeechCountDown.cancel();
}
mIsListening = false;
Message message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);
try
{
mServerMessenger.send(message);
}
catch (RemoteException e)
{
}
//Log.d(TAG, "error = " + error); //$NON-NLS-1$
}
#Override
public void onEvent(int eventType, Bundle params)
{
}
#Override
public void onPartialResults(Bundle partialResults)
{
}
#Override
public void onReadyForSpeech(Bundle params)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
mIsCountDownOn = true;
mNoSpeechCountDown.start();
}
Log.d(TAG, "onReadyForSpeech"); //$NON-NLS-1$
}
#Override
public void onResults(Bundle results)
{
//Log.d(TAG, "onResults"); //$NON-NLS-1$
}
#Override
public void onRmsChanged(float rmsdB)
{
}
}
}
As commented, I think that you don't need to use Broadcast Receiver for what you are trying to do. Instead you should define a service to be continuosly listening for speech. You can find a implementation here:
And for that about android killing services, you cannot prevent a service from being killed by the system, even system services can be killed.
Anyway, you can use the Service's startForeground() method:
By default services are background, meaning that if the system needs
to kill them to reclaim more memory (such as to display a large page
in a web browser), they can be killed without too much harm. You can
set this flag if killing your service would be disruptive to the user,
such as if your service is performing background music playback, so
the user would notice if their music stopped playing.
You can see the implementation here.
I am having difficulty figuring out how to resolve this issue, I am not sure if I am not setting up threads correctly or if it is even possible to resolve things properly.
This is an Android app that reads certain strings out as TTS (using the native Android TTS) at certain timings. During this TTS reading, the user should be able to barge-in with instructions such as "Stop" or "Pause." This recognition is done by using the iSpeech API.
Our current solution is to have the TTS running as a Thread that will output the proper strings. Once the user presses a button to begin the voice recognition (using an Intent), the app does voice recognition and handles it perfectly, but then TTS never again outputs anything. Logcat shows the following error:
11-28 02:18:57.072: W/TextToSpeech(16383): speak failed: not bound to TTS engine
I have thought about making the voice recognition a thread of its own that pauses the TTS, but the problem would then be that the timer controlling the TTS would become unsynced with what it should be.
Any advice or help would be appreciated.
Relevant code regarding the thread and the intent are below:
Thread
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Prevent device from sleeping mid build.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_build_order);
mPlayer = MediaPlayer.create(BuildOrderActivity.this, R.raw.bing);
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
tts = new TextToSpeech(BuildOrderActivity.this, new TextToSpeech.OnInitListener() {
#SuppressWarnings("deprecation")
public void onInit(int status) {
if(status != TextToSpeech.ERROR)
{
tts.setLanguage(Locale.US);
tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
public void onUtteranceCompleted(String utteranceId) {
mPlayer.start();
}
});
}
}
});
buttonStart = (Button) findViewById(R.id.buttonStartBuild);
buttonStart.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startBuild = new StartBuildRunnable();
Thread t = new Thread(startBuild);
t.start();
}
});
...//code continues oncreate setup for the view}
public class StartBuildRunnable implements Runnable {
public void run() {
double delay;
buildActions = parseBuildXMLAction();
buildTimes = parseBuildXMLTime();
say("Build has started");
delayForNextAction((getSeconds(buildTimes.get(0)) * 1000));
say(buildActions.get(0));
for (int i = 1; i < buildActions.size(); i++)
{
delay = calcDelayUntilNextAction(buildTimes.get(i - 1), buildTimes.get(i));
delayForNextAction((long) (delay * 1000));
say(buildActions.get(i));
//listViewBuildItems.setSelection(i);
}
say("Build has completed");
}
}
Intent
/**
* Fire an intent to start the speech recognition activity.
* #throws InvalidApiKeyException
*/
private void startRecognition() {
setupFreeFormDictation();
try {
recognizer.startRecord(new SpeechRecognizerEvent() {
#Override
public void onRecordingComplete() {
updateInfoMessage("Recording completed.");
}
#Override
public void onRecognitionComplete(SpeechResult result) {
Log.v(TAG, "Recognition complete");
//TODO: Once something is recognized, tie it to an action and continue recognizing.
// currently recognizes something in the grammar and then stops listening until
// the next button press.
if (result != null) {
Log.d(TAG, "Text Result:" + result.getText());
Log.d(TAG, "Text Conf:" + result.getConfidence());
updateInfoMessage("Result: " + result.getText() + "\n\nconfidence: " + result.getConfidence());
} else
Log.d(TAG, "Result is null...");
}
#Override
public void onRecordingCancelled() {
updateInfoMessage("Recording cancelled.");
}
#Override
public void onError(Exception exception) {
updateInfoMessage("ERROR: " + exception.getMessage());
exception.printStackTrace();
}
});
} catch (BusyException e) {
e.printStackTrace();
} catch (NoNetworkException e) {
e.printStackTrace();
}
}