Stop method execution until another activity finished - java

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).

Related

Android onActivityResult() not firing

I am aware of the plenty of questions similar to this one, yet none of the solutions mentioned there work for me, and I'm not quite sure why.
I have the following setup:
Launching from MainActivity.java:
Button b = findViewById(R.id.btn_b);
b.setOnClickListener(new View.onClickListener() {
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, Activity2.class);
startActivityForResult(intent, 0);
}
});
Returning values from Activity2.java:
#Override
public onBackPressed() {
System.out.println("Here"); // this can be seen in the logcat
Intent retIntent = new Intent();
// putExtra some return values
setResult(RESULT_OK, retIntent);
finish();
}
Receiving data back at MainActivity.java:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
System.out.println("Returning"); // this doesn't fire at all
if (data != null) { // I know there will be no other activities, and I want to act on whatever result I get
// extract and do something with data
}
}
I really don't understand what is going on here. Can someone please help explain, and how it can be fixed? I'll be happy to provide more information if needed.
Thank you for your time.
change this line in your MainActivity.java to
startActivityForResult(intent, 1);
and then in the method onBackPressed() call the method setResult like this
setResult(RESULT_OK);
then in the onActivityResult method write this condition.
if (resultCode == Activity.RESULT_OK) {//place your logic here}
Please let me know if this worked for you.

Why doesn't startActivityForResult() lead to onActivityResult() execution?

Still trying to make my screen record app. I keep on working with MediaRecorder, as I was told some time ago, so I got stuck with another problem.
I just need to initialize a MediaProjection object to make my code work, that's what I do in onActivityResult(), as it's written in this guide:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
screenRecorder.setMediaProject(mediaProjection);
}
}
The setMediaProjection() looks like
public void setMediaProject(MediaProjection project) {
mediaProjection = project;
}
, so it shouldnt't cause any trouble.
And that's how I try to call onActivityResult():
/* start transmission */
if(screenRecorder.isRunning()) {
screenRecorder.stopRecord();
} else {
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
}
The fun and crazy thing is that when I first launched the debug, it worked! After startActivityForResult() I got to onActivityResult() and initialized mediaProjection: my phone showed me a dialog window whether I allow to capture the screen or not, so I allowed that and got a special symbol (smth like screen with displayed waves) at my status bar.
But a few moments later I found an issue when stopping the record and restarted the debug session to trace it more exactly. After that onActivityResult() is just ignored: startActivityForResult() is called, the dialog window is shown, but after allowing the record onActivityResult() is completely skipped and mediaProjection is null. The restarting and re-installing the apk with the same code didn't fix anything.
Thank you very much for any suggestions.
Your onActivityResult only does something when the result code is OK, try this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
screenRecorder.setMediaProject(mediaProjection);
} else {
//TODO: Do something
Toast.makeText(getBaseContext(), "Result code is not RESULT_OK, ", Toast.LENGTH_LONG).show();
}
There was a very simple solution. I just initialized the record service that put null into mediaRecorder's mediaProjection, so after that I was unable to re-initialize it. Putting intent which called onActivivtyResult() into activity's onCreate() before starting the service fixed that.
I got same problem. This could bu about threading. In my project I started an activity and opening activity try to start chrome intent. Chrome is opening in debug mode but not opened real mode.
I added a delay when opening chrome
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
startAuth();
}
}, 100);

Meaning of a code related to GALLERY_REQUEST

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.

android waiting on something

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.

Why onActivityResult() is blocked by worker thread?

I'm a newbie in multithreading, and can't understand why onActivityResult() is never called in my code.
I need to pause a thread until my needed variable is changed. I call java function ShowFileDialog() from cocos2d-x using jni, and it's called from a thread other than UI thread. Then I start activity to pick an image from gallery, and all this is done on UI thread. After that I need to wait until filePath variable is changed, and when it will happen - return filePath string to cocos2d-x.
This is my code:
private static MyActivity thisActivity;
private static String filePath;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
thisActivity = this;
}
public static String ShowFileDialog() {
filePath = new String();
thisActivity.runOnUiThread(new Runnable() {
public void run() {
Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.setType("image/*");
thisActivity.startActivityForResult(photoPickerIntent, 1);
}
});
synchronized(filePath)
{
try {
filePath.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return filePath;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
...
filePath.notifyAll();
}
Activity from Intent is started, but onActivityResult() is never called. I can't understand why it happens - does it mean that UI thread is somehow blocked?
filePath.wait() blocks your GLThread in GLSurfaceView because Cocos2d-x mainloop was called from the GLThread. And calling startActivityForResult() will cause to call onPause() of the current active Activity, it's Cocos2dxActivity. Cocos2dxActivity.onPause() will call GLSurfaceView.onPause(). GLSurfaceView.onPause() will call sGLThreadManager.wait(). But the GLThread was blocked by your code. Thus the deadlock will occur.
I recommend you to use callback mechanism instead of just waiting on GLThread. In this case, you might be able to use this CCImagePicker.
https://github.com/stubma/cocos2dx-better/blob/master/cocos2dx-better/java/org/cocos2dx/lib/CCImagePicker.java
https://github.com/stubma/cocos2dx-better/blob/master/cocos2dx-better/java/org/cocos2dx/lib/ImagePickerActivity.java

Categories

Resources