I was wondering how to make a program pause and wait for an event to finish before starting another event, for example I could have a text to speech that says something and right after that a google voice recognizer should fire, however they both fire at the same time and makes the speech recognizer listen to the text to speech. I tried searching on here about it and found some answers but they were not really clear for me, can anyone help me with it?
here is an example code i tested out :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
tts=new TextToSpeech(getApplicationContext(),
new TextToSpeech.OnInitListener() {
#SuppressWarnings("deprecation")
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
tts.setLanguage(Locale.UK);
tts.speak("Welcome", TextToSpeech.QUEUE_FLUSH, null);
}
}
});
if(!(tts.isSpeaking())){
startVoiceRecognitionActivity();
}
}
private void startVoiceRecognitionActivity()
{
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speak Up");
startActivityForResult(intent, REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK)
{
matches = data.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
if (matches.contains("list")){
Intent gotoList = new Intent(MenuActivity.this, ListActivity.class );
startActivity(gotoList);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
Welcome to the wonderful world of asynchronous events.
In order to do what you want, the approach is not to "wait" (because everything would then freeze), but to "listen".
When something takes long in Android, such as the Text To Speech, you have to listen for a event.
If you look at the docs for the Text To Speech object, you'll find it accepts a listener for different things: http://developer.android.com/reference/android/speech/tts/TextToSpeech.html#setOnUtteranceProgressListener(android.speech.tts.UtteranceProgressListener) and http://developer.android.com/reference/android/speech/tts/UtteranceProgressListener.html
So you'd do (assuming your Text to Speech object is tts):
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
public void onDone(String utteranceId) {
// The text has been read, do your next action
}
public void onError(String utteranceId, int errorCode) {
// Error reading the text with code errorCode, can mean a lot of things
}
public void onStart(String utteranceId) {
// Reading of a sentence has just started. You could for example print it on the screen
}
});
This is called "subscribing to an event", and is asynchronous because your program can do other things and you'll be notified when "something" (what you have subscribed to) happens.
Then for example when you do
tts.speak ("welcome", ....)
And it finishes, the method onDone in your listener will be called. You can start the voice recognizer there.
Related
I am developing an application where I press record button and it will automatically start video recording and stop after given duration. But what I found is just open video recording , I have to manually click record button and to save video, I have to click OK button.
Is there any way to do that automatically?
Here is my code:
public class MainActivity extends AppCompatActivity {
private static int CAMERA_PERMISSION_CODE=100;
private static int VIDEO_RECORD_CODE=101;
public Uri videoPath;
UploadTask uploadTask;
Button record_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
record_btn=findViewById(R.id.record_button);
storageReference=FirebaseStorage.getInstance().getReference();
if (isCameraPresent()){
Log.i("VIDEO_RECORD_TAG","Camera is Detected");
getCameraPermission();
}else{
Log.i("VIDEO_RECORD_TAG","No Camera is detected");
}
record_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
recordVideo();
}
});
}
private boolean isCameraPresent(){
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)){
return true;
}else {
return false;
}
}
private void getCameraPermission(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.CAMERA},CAMERA_PERMISSION_CODE);
}
}
private void recordVideo(){
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 5);
startActivityForResult(intent,VIDEO_RECORD_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==VIDEO_RECORD_CODE){
if (resultCode==RESULT_OK){
assert data != null;
videoPath=data.getData();
Log.i("VIDEO_RECORD_TAG","Video is recorded and available at path" + videoPath);
}
else {
Log.i("VIDEO_RECORD_TAG","Video recording has some error");
}
}
}
You're using an Intent to capture video. What that does is literally ask another app to record video for you. When you're doing that you have to use that app as it is, which requires a button press. If you want to avoid that, you're going to have to directly use the camera yourself and handle the recording.
As an aside- if you're using an Intent to record video, you don't need Camera permission. You do if you're recording it yourself.
I have an PopUpActivity which pops up a window and i'm very satisfied with that.
However, I want to be able to return information from the popup window back to the parent activity, but also be able to call a function on the parent activity once the popup window is closed. Could someone help me?
Here is my code in the PopUpActivity:
public void closePopUpAndSendResultBack(){ // and how can i pass data to the previous activity?
//https://developer.android.com/training/basics/intents/result
Intent data = new Intent();
data.putExtra("data", "yo");
//startActivityForResult(data, 1); // gives me the error : android.content.ActivityNotFoundException: No Activity found to handle Intent { (has extras) }
setResult(Activity.RESULT_OK, data);
finish();
}
and here is my parent(MainActivity) function that I want to get called once the popUpWindow is closed:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
nameTextField.setText(""); // how can i get Yo inside here?
showTheButton(); // and how can this function get called?
}
}
}}
Also, here is how I make that window Pop up from my Mainactivity:
theOkButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent pop_up_that_window = new Intent(MainActivity.this,PopActivity.class);
pop_up_that_window.putExtra("first", "Velkommen du der!");
startActivity(pop_up_that_window);
}
});
}
Could someone help me please?
In MainActivity use:
theOkButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent pop_up_that_window = new Intent(MainActivity.this,PopActivity.class);
pop_up_that_window.putExtra("first", "Velkommen du der!");
MainActivity.this.startActivityForResult(pop_up_that_window, 1);
}
});
And still in MainActivity in onActivityResult() use this code:
String yo = data.getStringExtra("data")
nameTextField.setText(yo);
I have used the following code to get a picture from the gallery in an app on clicking a button. It works fine but I just wanted to know the meaning of the codes used. Could someone help me in it?
private ImageButton mSelectImage;
public static final int GALLERY_REQUEST =1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post);
mSelectImage = (ImageButton)findViewById(R.id.imageSelect);
mSelectImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, GALLERY_REQUEST);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == GALLERY_REQUEST && resultCode == RESULT_OK){
Uri imageUri = data.getData();
mSelectImage.setImageURI(imageUri);
}
}
This is the requestCode. It helps you to identify from which Intent you came back. For example if you have two or more intent for camera request and for the Contact request.Whenever the subsequently called finish and need to pass data back to Acivity, now you need to identify in your onActivityResult from which intent call you are returning from and put your handling logic accordingly.
public static final int CAMERA_REQUEST = 101;
public static final int CONTACT_VIEW = 202;
#Override
public void onCreate(Bundle savedState)
{
super.onCreate(savedState);
// For CameraRequest you would most likely do
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
// For ContactReqeuest you would most likely do
Intent contactIntent = new Intent(ACTION_VIEW, Uri.parse("content://contacts/people/1"));
startActivityForResult(contactIntent, CONTACT_VIEW);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == Activity.RESULT_CANCELED) {
// code to handle cancelled state
}
else if (requestCode == CAMERA_REQUEST) {
// code to handle data from CAMERA_REQUEST
}
else if (requestCode == CONTACT_VIEW) {
// code to handle data from CONTACT_VIEW
}
}
GALLERY_REQUEST is a request code which is used like token, imagine you go into mall with bag, but they can't let you in with the bag so you have to put your bag outside the mall and guy will gives you a token, so when you will come back you give him that token and he will give your bag.
This token is managed just because you are not the only one who came with the bag there may be more, as the rule all person have to put their bag outside mall, but how to identify which bag belongs to which person,they used token.
Just like that request code is used, you may going to several other apps via implicit intent from your activity but when you came back, one method called for all intent: onActivityResult now you have request code to identify that from which activity is user coming from.
I have the following scenario :
I used the Maven repository from Gradle to integrate ZXing into my Android app.
In my scan activity, the code looks like this :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scan_layout);
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES);
integrator.setPrompt(" ");
integrator.setScanningRectangle(700, 700);
integrator.setResultDisplayDuration(0);
integrator.setCameraId(0); // Use a specific camera of the device
integrator.initiateScan();
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
//retrieve scan result
IntentResult scanningResult = null;
scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
//we have a result
String scanContent = scanningResult.getContents();
if(isConnected()) {
requestdata("http://rm360project-001-site1.smarterasp.net/api/endpoint", scanContent);
}else {
Toast.makeText(this, "Internet Connection not available", Toast.LENGTH_LONG).show();
}
} else {
Intent getMainScreen = new Intent(ScanScreen.this, MainActivity.class);//pentru test, de sters
startActivity(getMainScreen);
}
}
The way I want it to work :
1. If I scan a QR code, call the function requestdata
2. If I press back during scan, go to MainActivity
The problem :
Even when I press back on my device, the function requestdata is called, I think because scaningResult is never null. Shouldn't it be null when back is pressed?
Do you have any ideea why this happens?
Thank you!
Don't know if your still interested but...
Simply change this line:
if (scanningResult != null) {
To this:
if (scanningResult != null && resultCode==RESULT_OK) {
For some reason simply scanningResult does not actually return null as suggested by the ZXing team, even when the Intent is canceled.
Good day to everyone!
I need to stop method execution until another activity will end.
At the moment I'm trying to do it in this way:
private boolean isPausedWhileSplash;
public void showSplashWorldChangeAd(String oldWorldName, String newWorldName) {
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
Intent intent = new Intent(this, SplashScreen.class);
intent.putExtra(SplashScreen.MSG_STRING_KEY, oldWorldName + " -> "
+ newWorldName);
intent.putExtra(SplashScreen.OLD_WORLD, oldWorldName);
intent.putExtra(SplashScreen.NEW_WORLD, newWorldName);
startActivityForResult(intent, RESULT_OK);
isPausedWhileSplash = true;
while (isPausedWhileSplash) {
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
isPausedWhileSplash = false;
}
But it's not working.
Can you help me?
Thanks!
UPD: Maybe there is any way to prevent view from drawing? Because all what I need right now is delay calling of methods, which will redraw view of this activity. Now I have the new world drawn before the splash screen, saying about the world change, is shown, which is not looking good.
I'm a little rushed for time so here's a generic answer:
public class MonitorObject{
}
public class MyWaitNotify{
MonitorObject myMonitorObject = new MonitorObject(); //To be used for synch
public void doWait(){
synchronized(myMonitorObject){
try{
myMonitorObject.wait(); // Wait until the notify method is called by another thread
} catch(InterruptedException e){...}
}
}
public void doNotify(){ //Notify waiting threads that they can continue
synchronized(myMonitorObject){
myMonitorObject.notify();
}
}
}
I'll come back and get you a working example this afternoon if you haven't got a solution by then...
This article should get you started
EDIT: This article demonstrates other approaches, all of which should be an improvement on your current solution. It talks you through how to update the UI from events in different threads and the benefits/costs of the various solutions.
I guess you are trying to do something like this:
public void showSplashWorldChangeAd(String oldWorldName, String newWorldName){
/* You have done some initialization work */
startActivityForResult(intent, RESULT_OK);
/* This is what you want to do after the activity returns */
afterActivityReturns();
}
Then why not proceed this way?
public void showSplashWorldChangeAd(String oldWorldName, String newWorldName){
/* You have done some initialization task here*/
startActivityForResult(intent, RESULT_OK);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/* This is what you want to do after the activity finishes */
afterActivityReturns();
}
But if you really want to stop the showSplashWorldChangeAd method for some reason, you need lock and key (as Basic says).