Android Java: Speech Recognition App crashes whenever there are no results - java

I am developing an Android app that uses the Google speech recognition api. For some reason, when I start up the app (via USB debugging on my Android phone), starting the listening process works just fine, and the app works smoothly if I do actually say something after clicking the button to make the app start listening for audio. However, if I click the button to start listening, and then I don't say anything, then the app crashes for some reason. In other words, if the speech recognition gets no results, then the app just crashes. Does anyone have any idea as to why?
Below is an excerpt of my code. (Yes, I did account for the permissions. I just didn't include that code in the excerpt below).
I have tried putting try catch blocks in various places to see if I could catch the error that causes the crash, but it has yet to work. Furthermore, while there is an onResults method, there does not seem to be an onNoResults method.
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
recognitionListener = new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle params) {
// Called when the speech recognition process is ready to begin
}
#Override
public void onBeginningOfSpeech() {
// Called when the user begins speaking
}
#Override
public void onRmsChanged(float rmsdB) {
// Called when the volume of the spoken input changes
}
#Override
public void onBufferReceived(byte[] buffer) {
// Called when the app receives a buffer of audio data
}
#Override
public void onEndOfSpeech() {
// Called when the user stops speaking
}
#Override
public void onError(int error) {
// Called when an error occurs during the speech recognition process
TextView textView = findViewById(R.id.errors);
textView.setText(error);
}
#Override
public void onResults(Bundle results) {
// Called when the speech recognition process has completed and the results are available
List<String> resultList = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if (resultList != null && resultList.size() > 0) {
// Display the first result in the text field
TextView textView = findViewById(R.id.spokenWords);
textView.setText(resultList.get(0));
}
//speechRecognizer.startListening(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH));
}
#Override
public void onPartialResults(Bundle partialResults) {
// Called when the app receives partial results of the speech recognition process
}
#Override
public void onEvent(int eventType, Bundle params) {
// Called when the app receives other events from the speech recognition process
}
};
speechRecognizer.setRecognitionListener(recognitionListener);
Button startSpeech = findViewById(R.id.startSpeech);
startSpeech.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TextView textView = findViewById(R.id.spokenWords);
textView.setText("Listening");
speechRecognizer.startListening(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH));
}
});

Related

Android Java, onResume override

I am only starting with Java/Android and trying to implement custom SDK.
I am making Capacitor plugin for android, but for now trying to do Android side logic.
I have method that I want to be able to execute on demand AndroidConfigManager.stopDetection(getActivity()); which enables/disables NFC read.
so If I execute AndroidConfigManager.stopDetection(getActivity()); I get NFC Detection Enabled in log and all is good.
However that executes every time app goes to background and resumes after. I've tried to override onPause and onResume but the way I have it doesn't seem to be doing anything.
I can't figure out how to suppress it
public class ExamplePlugin extends Plugin implements IDetectCardCallback, IITSOFrameworkCallback, ITransactionControllerCallback {
private Application app;
private Context context;
public void echo(PluginCall call) {
String value = call.getString("value");
app = getActivity().getApplication();
context = getContext();
AndroidConfigManager.initialise(app);
AndroidConfigManager.stopDetection(getActivity());
}
#Override
public void onResume(){
super.onResume();
AndroidConfigManager.stopDetection(getActivity());
// ITSOFramework.getInstance().detectCard(this, false);
}
#Override
public void onPause(){
super.onPause();
// ITSOFramework.getInstance().detectCard(null, false);
}
}

View freezes when returning to OnResume on Android 6.0 Tab

This issue occurs only on Android 6.0 Tablet.
I use fileObserver to get the saved Image Path and display that image in my app and Firebase ML kit to check the readability of the text present in that image.
I first open the third party app to capture image for my app and as soon as I click a picture, a background thread is spawned and a progress bar with text messaage is shown in the UI.
Once firebase ML kit finishes it's job, the result whether the document is readable or not is then saved in an object.
Now as soon as I close the third party app and return to my app(onResume()), the code executes to set the image on ImageView and hide progressbar, but UI is freezed with progress bar and the UI updates only when I click anywhere on the screen.
public class DocFragment extends Fragment{
private FileObserver observer = new FileObserver(LENS_DIR_PATH) {
#Override
public void onEvent(int event, #Nullable String path) {
if (event == CLOSE_WRITE) {
String attachedImagePath = LENS_DIR_PATH + path;
// Log.v(TAG, "File was saved: " + LENS_DIR_PATH + path);
processDoc(attachedImagePath);
}
}
};
#Override
public void onStop() {
super.onStop();
observer.startWatching();
}
#Override
public void onResume() {
super.onResume();
observer.stopWatching();
}
}
class DocProvider {
fun processDoc(path: String) {
Executors.newSingleThreadExecutor().execute {
semaphore.acquire()
activity.runOnUiThread {
showProgressBar()
}
}
// Image processing and updating the result after showing Progress Bar
updateResult()
}
private fun updateResult() {
docResult.updateResult()
semaphore.release()
}
}

Terminating Android Timer if user doesn't use the App(Prevent running in the background)

I have a Timer in my App that infinitely runs an Animation. like this:
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//Running Animation Code
}
});
}
}, 1000, 1000);
Now I realized that this code runs even if user click Back Button of android. if fact it runs in the background and it seems uses a lot of memory.
I need this code run ONLY if user in the app. In fact when user click on Back Button, this Timer goes to end and if user clicks on Home Button, after a while that user doesn't use the App, terminates this Timer.
What I need is to prevent using memory. Because i realized if this codes runs a while, App freezes! I need a normal behavior.
If your Activity is the last element in the BackStack, then it will be put in the background as if you pressed the Home button.
As such, the onPause() method is triggered.
You can thus cancel your animation there.
#Override protected void onPause() {
this.timer.cancel();
}
You should as well start your animation in the onResume() method.
Note that onResume() is also called right after onCreate(); so it's even suitable to start the animation from a cold app start.
#Override protected void onResume() {
this.timer.scheduleAtFixedRate(...);
}
onPause() will be also called if you start another Application from your app (e.g: a Ringtone Picker). In the same way, when you head back to your app, onResume() will be triggered.
There is no need to add the same line of code in onBackPressed().
Also, what's the point in stopping the animation in onStop() or onDestroy()?
Do it in onPause() already. When your are app goes into the background, the animation will already be canceled and won't be using as much memory.
Don't know why I see such complicated answers.
You can do it like this, in onBackPressed() or onDestroy(), whatever suits you.
if (t != null) {
t.cancel();
}
If you need, you can start timer in onResume() and cancel it in onStop(), it entirely depend on you requirement.
If a caller wants to terminate a timer's task execution thread
rapidly, the caller should invoke the timer's cancel method. - Android Timer documentation
You should also see purge and
How to stop the Timer in android?
Disclaimer: This might not be the 100% best way to do this and it might be considered bad practice by some.
I have used the below code in a production app and it works. I have however edited it (removed app specific references and code) into a basic sample that should give you a very good start.
The static mIsAppVisible variable can be called anywhere (via your App class) in your app to check if code should run based on the condition that the app needs to be in focus/visible.
You can also check mIsAppInBackground in your activities that extend ParentActivity to see if the app is actually interactive, etc.
public class App extends Application {
public static boolean mIsAppVisible = false;
...
}
Create a "Parent" activity class, that all your other activities extend.
public class ParentActivity extends Activity {
public static boolean mIsBackPressed = false;
public static boolean mIsAppInBackground = false;
private static boolean mIsWindowFocused = false;
public boolean mFailed = false;
private boolean mWasScreenOn = true;
#Override
protected void onStart() {
applicationWillEnterForeground();
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
applicationDidEnterBackground();
}
#Override
public void finish() {
super.finish();
// If something calls "finish()" it needs to behave similarly to
// pressing the back button to "close" an activity.
mIsBackPressed = true;
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
mIsWindowFocused = hasFocus;
if (mIsBackPressed && !hasFocus) {
mIsBackPressed = false;
mIsWindowFocused = true;
}
if (!mIsWindowFocused && mFailed)
applicationDidEnterBackground();
if (isScreenOn() && App.mIsAppVisible && hasFocus) {
// App is back in focus. Do something here...
// this can occur when the notification shade is
// pulled down and hidden again, for example.
}
super.onWindowFocusChanged(hasFocus);
}
#Override
public void onResume() {
super.onResume();
if (!mWasScreenOn && mIsWindowFocused)
onWindowFocusChanged(true);
}
#Override
public void onBackPressed() {
// this is for any "sub" activities that you might have
if (!(this instanceof MainActivity))
mIsBackPressed = true;
if (isTaskRoot()) {
// If we are "closing" the app
App.mIsAppVisible = false;
super.onBackPressed();
} else
super.onBackPressed();
}
private void applicationWillEnterForeground() {
if (mIsAppInBackground) {
mIsAppInBackground = false;
App.mIsAppVisible = true;
// App is back in foreground. Do something here...
// this happens when the app was backgrounded and is
// now returning
} else
mFailed = false;
}
private void applicationDidEnterBackground() {
if (!mIsWindowFocused || !isScreenOn()) {
mIsAppInBackground = true;
App.mIsAppVisible = false;
mFailed = false;
// App is not in focus. Do something here...
} else if (!mFailed)
mFailed = true;
}
private boolean isScreenOn() {
boolean screenState = false;
try {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
screenState = powerManager.isInteractive();
} catch (Exception e) {
Log.e(TAG, "isScreenOn", e);
}
mWasScreenOn = screenState;
return screenState;
}
}
For your use you might want to create a method in your activity (code snippet assumes MainActivity) that handles the animation to call the t.cancel(); method that penguin suggested. You could then in the ParentActivity.applicationDidEnterBackground() method add the following:
if (this instanceof MainActivity) {
((MainActivity) this).cancelTimer();
}
Or you could add the timer to the ParentActivity class and then not need the instanceof check or the extra method.

WearableListenerService only handles onMessageReceived() on second try

I've got a simple Android Wear demo to illustrate the Message API. I'm capturing input on a watch and passing it off to a handheld device for cloud processing, so the following class that extends WearableListenerService is running on a phone:
public class ListenerService extends WearableListenerService {
private static final String MESSAGE_PATH = "/handle-inbound-message";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
if(messageEvent.getPath().equals(MESSAGE_PATH)) {
updateData(new String(messageEvent.getData()));
}
}
private void updateData(final String volume) {
new Thread(new Runnable() {
#Override
public void run() {
// do neat stuff with the inbound data
}
}).start();
}
}
...and the wearable code generating the message, by way of clicking a button on the wearable app, is like so:
private void sendToHandheld(final byte[] volume) {
if(nodeId != null) {
new Thread(new Runnable() {
#Override
public void run() {
client.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
Wearable.MessageApi.sendMessage(client, nodeId, MESSAGE_PATH, volume);
client.disconnect();
}
}).start();
}
}
The code works fine...except for the fact that I have to click the button twice in the wearable app to get onMessageReceived() to fire. The app starts up, but doesn't get the message the first time...with the app still open, I click the button again and it fires perfectly. Can anyone see where I might have made a mistake?
(Also, I'm seeing a lot of code demos a repos where people don't call super.onMessageReceived().)
OK, I think I solved the issue - I commented-out the line in onMessageReceived() where the superclass is called...and that fixed it.
SUCCESS!

Opens hundreds of tabs on single ad-click

listener = new RevMobAdsListener() {
#Override
public void onRevMobAdClicked() {
Log.i("[RevMob]", "Advertisement Clicked!");
revmob.openAdLink(application, APPLICATION_ID, this);
return;
}
#Override
public void onRevMobAdDismiss() {
Log.i("[RevMob]", "Advertisement Closed!");
fullscreenAd.hide();
}
#Override
public void onRevMobAdDisplayed() {
Log.i("[RevMob]", "Advertisement Displayed!");
}
#Override
public void onRevMobAdNotReceived(String message) {
Log.i("[RevMob]", "No Advertisement Available!");
}
#Override
public void onRevMobAdReceived() {
Log.i("[RevMob]", "Advertisement Pulled from network!");
}
#Override
public void onRevMobSessionIsStarted() {}
#Override
public void onRevMobSessionNotStarted(String arg0) {}
};
So what the problem is, is that once I click on the advertisement it continuously opens tabs in my browser.
LogCat spams the following debug messages. (In order)
Advertisment Pulled from network!
Advertisement Displayed!
Reporting impression using testing mode: with_ads
Advertisement Clicked!
^The above is apmmed on repeat, everytime it opens a new tab
Look at your first listener (onRevMobAdClicked): when you click the first ad, this listener is called, and it calls an adlink.
By default (from RevMob SDK), when called (openAdLink), the link calls automatically onRevMobAdReceived, onRevMobAdDisplayed and onRevMobAdClicked listeners.
Then, this adlink is opened and it fires this same listener (onRevMobAdClicked), calling again the adlink, which will fire the listener, which will call again the adlink, ..........
You have to change the way you call the link.
Also, you don't need to call fullscreen.hide() in onRevMobAdDismiss. When the fullscreen is dismissed by the user, this event is fired.
Hope that helps!

Categories

Resources