I'm trying to ask the user if he wants to retry a login process if the initial one has failed.
I do this using an AlertDialog. The problem is i'm going around in a circle. Let me explain:
I have the login method named Login which I call from the main activity. If this fails, I open an AlertDialog. The response from AlertDialog comes on the main thread. How do I make the AlertDialog dissapear before I call Login again?
Now I have something like this onCreate->Login->AlertDialog->ResponseHandler->Login. If I do this, the AlertDialog will never close because everything happens on the same thread.
Is there a way to send the response from the AlertDialog to the activity in a asynchronous way?
You can declare a Handler object as an anonymous inner class in your activity and on its reference call the sendEmptyMessage(0). in the handlerMessage() of the handler instance just dismiss the AlertDialog.
Here is a tutorial link which will help you more http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html
Related
After user logged in successfully, there will be another api call to get the user information.
But before the response I will close the activity and start the home activity.
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
//save token
// call REST service to get user info and update the user records on DB.
// update the notification token info
//go to home page
Intent intent = new Intent(SigninActivity.this, HomeActivity.class);
startActivity(intent);
finish();
}
How can I make the call REST calls outside the activity. So App can handle the onReponse even after I close the Activity.
In General How can we call the API to do the background activity (eg: update database.) without any interaction . (response doesn't depend on activity)
The easiest solution would be to use static method. You can call those methods from anywhere.
If you want to update UI elements inside that method, pass the UI elements as parameters to the static method.
You could run a service(async) in the background minimize the first app and onResponse kill the first app and start the 2nd. And just access the data from the first.
There are two ways of doing this
Calling the user information API from the home activity (This is what I prefer).
While logging in, start a Service which makes the user information API call. Since Services are independent of UI and can run in the background starting the home activity and stopping the current one doesn't have any effect on the service. Once you get the response in the Service, create a broadcast(Or use EventBus) to send the response to home activity.
I need to have a sort of "blocked alert" that can't be dismissed by the user until some event occurs. So, I created the alert and removed all the buttons from it:
Alert waitingAlert = new Alert(Alert.AlertType.INFORMATION);
waitingAlert.setTitle("Proposta Inviata");
waitingAlert.getButtonTypes().setAll();
waitingAlert.setHeaderText("La proposta รจ stata inviata a " + trade.getPlayer2Name());
waitingAlert.showAndWait();
Then, I need to dismiss it when a particular event occurs. I just tried doing it this way:
waitingAlert.close();
But it doesn't work.
Edit
The panel is shown when an user wants to send a request to another user in the network that needs to be accepted or refused. The principle is that the UI gets blocked until the other user says if he has accepted or refused the request. The request is send through a remote method invokation through a ring network. When I receive the response I want to close dismiss the panel.
To have a dialog that can't be dismissed by the user, but wait on a process, you will need to use dialog.show() as noted by James_D.
However, without buttons, the dialog actually will not close and you need to force it.
//for example
dialog.getButtonTypes().add(ButtonType.CANCEL);
dialog.hide();
dialog.getButtonTypes().remove(ButtonType.CANCEL);
This will allow you to close a dialog which has no buttons.
I have this method which basically waits for items in the singleton queue to become empty, there is a background service which is running and the service stops once it removes all items in the queue and process each one by one. This code runs in the main thread, what will happen when I call wait here? will the alert dialog still be showing and blocking the user from performing any other action?
void waitForService() {
openConnectionToUploadQueue();
if(answersQueue.getCount(objInterviewQuestion.getQid()) <= 0){
answersQueue.close();
return;
}
if(!answersQueue.isInterviewUploadServiceRunning()) {
answersQueue.startInterviewUploadService();
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getString(R.string.auto_submit_alert_title));
builder.setCancelable(false);
builder.setMessage(R.string.uploading_pending_answers);
AlertDialog waitForServiceDialog = builder.create();
waitForServiceDialog.show();
while (answersQueue.getCount(objInterviewQuestion.getQid()) > 0) {
// do nothing and keep loop running till answersQueue is empty
}
waitForServiceDialog.dismiss();
}
You should never block UI Thread. When you hold UI Thread for too long, this is when the system will show a dialog saying XXX is not responding and ask user to kill your application.
Instead, you should use a callback style call, and when the service is up, and you receive the method call from callback, you dismiss the dialog.
Edit:
As discussed, you would need to implement BroadcastReceiver
Here is a demo project of mine for something else, you can use it as a sample on how to create and use BroadcastReceiver.
https://github.com/cyfung/ActivityRecognitionSample
I'm developing an android app which I want to check if there's internet connection, if it's not the case display a warning message, and when there's internet connection again load a certain url.
It can be said that both displaying the message and checking there's internet connection work... but no separately.
I mean I have the following code:
if (!checkConnectivity())
{
browser.stopLoading();
LayoutInflater layoutinflater = LayoutInflater.from(app);
final View textEntryView;
textEntryView = layoutinflater.inflate(R.layout.exitdialog, null);
new AlertDialog.Builder(app)
.setView(textEntryView)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Exit")
.setNegativeButton("CANCEL", null)
.show();
while (!checkConnectivity())
{
}
browser.loadUrl(url);
}
If I don't use from while (!checkConnectivity()) to browser.loadUrl(url); then AlertDialog shows properly.
If I don't use from LayoutInflater layoutinflater = LayoutInflater.from(app); to .show(); then the app loads the web page correctly on browser.
But if I use the whole code it looks like it enters the while (!checkConnectivity()) loop before it does the show as what happens when internet connection is restabilished is that the alert dialog is shown briefly and the the web page is loaded.
I find this pretty weird, as I'm not using, as far as I know, threads that could cause that one could be executed before other one, and this is not the case this thing doesn't fulfill one of the most basic things in programming, I mean if an instruction is before another one, the one that's before should be plenty executed logically (except for threads).
Hope someone has an idea about this and can help me.
Your while loop blocks the UI thread and the dialog has no chance to get displayed.
Busy-looping to poll for a condition is also a big red flag.
Consider waiting for a connectivity event, and use a cancellable progress dialog instead of an an alert dialog to disable other UI until the event is received.
I have LoginActivity that displays the Login Fragment initially . Now when the user fill the data and press login button I send the credentials to an IntentService . before the service hit the server it sends a local broad cast intent to the LoginActivity to display the Loading Fragment (replace the login fragment) . If the login process successfully terminated it send a broadcast intent to the LoginActivity to start the MainActivity , and if it fails it send a broadcast intent to the LoginActivity to display the Error Fragment .
Now I am doing things the right way ? what about having this error
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
? I thing this error will happened , now how can i handle the FragmentTransaction in the onReceive() method where i change Fragments in the Login Activity.
is there a better architecture to handle the login using Activity and IntentService?
Try to use commitAllowingStateLoss() instead of commit().
Edited:
The problem is that you call commit after the onSavedInstanceState method. You have to unregister the reciever when the activity is not in the front (in onPause())Check out this comment stackoverflow.com/a/18306939/1333170