I am new to android. I want to show progress dialog when user click on login button. I tried this but the dialog is not showing
btn_logIn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
getUserCredentials();
}
}); //end of anonymous class
private void showProgressDialog() {
if (dialog == null) {
dialog = new ProgressDialog(this);
}
dialog.setMessage("Please Wait. Your authentication is in progress");
dialog.setButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which)
dialog.dismiss();
}
}); //end of anonymous class
dialog.show();
} //end of showProgressDialog()
private void getUserCredentials() {
EditText txt_userName = (EditText) findViewById(R.id.txt_userName);
String userName = txt_userName.getText().toString();
EditText txt_password = (EditText) findViewById(R.id.txt_password);
String password = txt_password.getText().toString();
if (userName != null && !userName.trim().equals("") && password != null && !password.trim().equals("")) {
showProgressDialog();
callWebService(userName, password);
}
} //end of getUserCredentials()
private void callWebService(String userName, String password) {
try {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("userName", userName);
....
Object result = envelope.getResponse();
if (result.equals("true")) {
dialog.dismiss();
Toast.makeText(this, result.toString(), Toast.LENGTH_SHORT).show();
} else {
dialog.dismiss();
Toast.makeText(this, result.toString(), Toast.LENGTH_SHORT).show();
}
} catch (SocketTimeoutException e) {
dialog.dismiss();
Toast.makeText(this, "Service is not connected, Please make sure your server is running", Toast.LENGTH_LONG).show();
} catch(Exception e) {
e.printStackTrace();
dialog.dismiss();
Toast.makeText(this, "Unable to connect, please try again later. Thank you", Toast.LENGTH_LONG).show();
}
} //end of callWebServide()
Am i doing anything wrong. When i click on login button and service is not running then it shows message that Service is not connected, Please make sure your server is running", but the dialog isn't showing...Why? My logic is when user click on login button and fields have values then start showing progress dialog and if anything happens like when result come or server is not running or if any exception happen , then i remove the dialog and show the appropriate message, but dialog isn't showing...Why? What i am doing wrong? Please help..
Thanks
Try this,
Change your getUserCredentials() like this,
private void getUserCredentials() {
EditText txt_userName = (EditText) findViewById(R.id.txt_userName);
String userName = txt_userName.getText().toString();
EditText txt_password = (EditText) findViewById(R.id.txt_password);
String password = txt_password.getText().toString();
if (userName != null && !userName.trim().equals("") && password != null && !password.trim().equals("")) {
showProgressDialog();
Thread t=new Thread(new Runnable() {
public void run() {
callWebService(userName, password);
}
}); t.start();
}
}
And your callWebService method like this,
private void callWebService(String userName, String password) {
try {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("userName", userName);
....
Object result = envelope.getResponse();
if (result.equals("true")) {
dialog.dismiss();
Toast.makeText(this, result.toString(), Toast.LENGTH_SHORT).show();
} else {
ActivityName.this.runOnUiThread(new Runnable() {
public void run() {
dialog.dismiss();
Toast.makeText(this, result.toString(), Toast.LENGTH_SHORT).show();
}
});
}
} catch (SocketTimeoutException e) {
ActivityName.this.runOnUiThread(new Runnable() {
public void run() {
dialog.dismiss();
Toast.makeText(this, "Service is not connected, Please make sure your server is running", Toast.LENGTH_LONG).show();
}
});
} catch(Exception e) {
e.printStackTrace();
ActivityName.this.runOnUiThread(new Runnable() {
public void run() {
dialog.dismiss();
Toast.makeText(this, "Unable to connect, please try again later. Thank you", Toast.LENGTH_LONG).show();
}
});
}
}
Update 1
To answer your questions from your comments,
1)Yes Async Task is more efficient. It has its own methods to do the same task what I have described here.
AsyncTask has the following methods,
i)onPreExecute()-which can be used to start your Dialog
ii)doInBackground()-which acts as the background thread.
iii)onPostExecute()-which gets called at the end where you can dismiss the dialog.
The reason why I didn't mention is that, there are possibilities that you might have to change your working code's structure to adapt to Async task.
2)runonUiThread- as the name indicates, anything inside this will be considered as it is running in the main UI thread. So basically to update the screen you have to use this. There are also other methods available, like Handlers which can also do the same task.
Use AsyncTask for it when ever task started at that time initialise your widget and then call your webservice from run method and close your progress bar on stop method.
Related
I have several buttons that can be clicked on a fragment. After clicking each button I show a Toast message that is exactly the same for each button. Thus if you press 5 different buttons one after another you will layer up 5 toast messages which will end up showing the same message for a long time. What I want to do is show a Toast if there is no Toast currently running.
The method that I use to show the Toast message
public void showToastFromBackground(final String message) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
}
});
}
When a button is pressed I simply call showToastFromBackground("Text to show");.
What I actually want is something like
public void showToastFromBackground(final String message) {
if(toastIsNotAlreadyRunning)
{
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
}
});
}
}
Use:
toast.getView().isShown();
Or:
if (toast == null || toast.getView().getWindowVisibility() != View.VISIBLE) {
// Show a new toast...
}
EDIT:
Toast lastToast = null; // Class member variable
public void showToastFromBackground(final String message) {
if(isToastNotRunning()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
lastToast = Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG);
lastToast.show();
}
});
}
}
boolean isToastNotRunning() {
return (lastToast == null || lastToast.getView().getWindowVisibility() != View.VISIBLE);
}
Try isShown(). It returns a fatal error if no toast is shown. So you can use try and catch the error.
//"Toast toast" is declared in the class
public void showAToast (String st){
try{
toast.getView().isShown(); // true if visible
toast.setText(st);
} catch (Exception e) { // invisible if exception
toast = Toast.makeText(theContext, st, toastDuration);
}
toast.show(); //finally display it
}
From here.
This does not wait if there is toast already, then show. But it does change active toast's text and show new one immediately without toasts overlapping each other.
I have this android code:
private class myTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try {
client = new Socket("192.168.1.2", 4444);
oos = new ObjectOutputStream(client.getOutputStream());
ois = new ObjectInputStream(client.getInputStream());
oos.writeUTF("LOGIN");
oos.flush();
String emailText = email.getText().toString();
oos.writeUTF(emailText);
oos.flush();
String passwordText = password.getText().toString();
oos.writeUTF(passwordText);
oos.flush();
string = ois.readUTF();
}catch (ConnectException e){
return "Host not found";
}catch (IOException e) {
return "Exception Caught";
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if ("Host not found".equalsIgnoreCase(result)){
Toast.makeText(getApplicationContext(), "Host not found" ,Toast.LENGTH_LONG).show();
}else if("Exception Caught".equalsIgnoreCase(result)){
Toast.makeText(getApplicationContext(), "Connection error" ,Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Connection established" ,Toast.LENGTH_LONG).show();
}
Toast.makeText(getApplicationContext(), string ,Toast.LENGTH_LONG).show();
if(string.equals("Login successfully Done!")){
startActivity(new Intent(Login.this, User.class));
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
register = (TextView)findViewById(R.id.register);
login = (Button)findViewById(R.id.login);
email = (EditText)findViewById(R.id.email);
password = (EditText)findViewById(R.id.password);
connection = (TextView)findViewById(R.id.connection);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
register.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View arg0) {
startActivity(new Intent(Login.this, Register.class));
}
});
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new myTask().execute();
}
});
}
but my connection create everytime i click on login button. I want my app connect to server at start and then when i press login button it sends request to server..How i need to change my code?
thanks
I think the easiest way to do that would be to move away from AsyncTasks and move to Threads. Create a new Thread in your onCreate function that creates the socket and connects it, then have it wait for a notification from the UI thread (easiest way to do this is to wait on a semaphore or message queue). Then have the onClick of the button notify the socket thread that it needs to login. With this design, you'll have it connect at startup but not login until you request it.
Your biggest worry here is if your server times out your connection for inactivity. But I assume you have control of the server to prevent that.
The problem here is that you're creating the socket in your doInBackground() method. This means that every time you execute an instance of AsyncTask that socket will be recreated. What you probably want to do is subclass Application or some sort of singleton and initialize your socket in there. Then make your AsyncTask do something like:
doInBackground(Object... params) {
// do stuff
Socket socket = Application.getSocket();
// do stuff with the socket
}
This introduces a bit of complexity as you need to handle properly opening/closing your socket at the proper points in your application lifecycle, but it is the cleanest solution that comes to mind.
I need to finish the execution of an async task before I make some checks for my login.
This is my async task
#Override
protected void onPostExecute(JSONArray jsonArray)
{
JSONObject json_data = null;
for (int i = 0; i < jsonArray.length(); i++) {
try {
json_data = jsonArray.getJSONObject(i);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
for (int j=0; j<jsonArray.length(); j++){
/*allMatrics.add(json_data.getString("matricNos"));
allPasswords.add(json_data.getString("password"));*/
if (user.equals(json_data.get("matricNos")) && pass.equals(json_data.get("password")))
{
ok = true;
System.out.println("hi i am ok");
break;
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Checking ok = "+ ok);
}
I need to finish this async task before I Check its status and then go on for my login authentication. It is supposed to be executed on the onclick of the login button
login.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
user = uedit.getText().toString();
pass = pedit.getText().toString();
if (user.equals(""))
{
Toast error = Toast.makeText(LogInScreen.this, "Enter Details", Toast.LENGTH_SHORT);error.show();
}
else
{
final GetMatricNos mat = new GetMatricNos();
mat.execute(new ServerConnector());
// have to finish task before enter user, have to implement logout as well
if ((mat.getStatus().equals(AsyncTask.Status.RUNNING))) - This has to be Status.FINISHED
{
System.out.println(ok);
/* if ((allMatrics.contains(user) && (allPasswords.contains(pass)))) */
if (ok)
{
Intent homescreen = new Intent(LogInScreen.this, HomeScreen.class);
homescreen.putExtra("username", user);
startActivity(homescreen);
}
else
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(LogInScreen.this);
alertDialogBuilder.setTitle(Html.fromHtml("<font color='#D41E46'>Invalid Login Details</font>"));
alertDialogBuilder
.setMessage("The login credentials you have entered are invalid. Please try again.")
.setIcon(R.drawable.alert)
.setCancelable(false)
.setPositiveButton("OK",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
}
}
});
ActionBar actionBar = getActionBar();
actionBar.hide(); // To hide the actionBar on LoginScreen
}
Now If I don't finish the task before checking it, it won't let me check the credentials that I am getting from the edit boxes, however first time if I login it doesn't make the check because the task runs when the login button is pressed, but for the second time if I login it goes through...?
Any help would be much appreciated, I tried task.cancel(true) before the check but that doesnt help...
If your task needs to finish executing before you do anything else then you must put the code that must wait in your onPostExecute which gets called when the task is finished
i have created one simple login application which takes user name and password from sqlserver..it works fine...
i want during login process one progeress bar should be displayed using asyntask...
but i am unaware to use parameters in asyntask...if some one plzz tell me how to put my method in doInbackground of asyntask and what param should i use....
my code is;.....
public void save(){
initilize();
ResultSet rs = null;
String mylog=id.getText().toString();
String mypass=pass.getText().toString();
try{
Statement statement=connect.createStatement();
rs=statement.executeQuery("LOGIN '"+mylog+"', '"+mypass+"'");
}catch(Exception e){
e.printStackTrace();
}
if(mylog.equals("")||mypass.equals("")){
Toast.makeText(getApplicationContext(), "empty fields", Toast.LENGTH_SHORT).show();
} else
try {
if(rs.next()){
Intent i=new Intent(getApplicationContext(),Act2.class);
startActivity(i);
}
else if(rs.next()==false){
Toast.makeText(getApplicationContext(), "incorrect login", Toast.LENGTH_SHORT).show();
id.setText("");
pass.setText("");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if it is possible that same method save() be kept inside doInbackground() of asyntask...
making a fast refactorization (note that this as it stand it's really bad practice and coding, you MUST refactor this code to be more maintanable and to avoid duplication):
public class MyAsyncTask extends AsyncTask<> {
private Activity activity;
boolean result;
private String myLog;
private String myPass;
private Connection connect;
public MyAsyncTask(Activity activity, Connection connect) {
this.activity = activity;
this.connect = connect;
}
#Override
protected void onPreExecute() {
//show your progress dialog
}
#Override
protected Object doInBackground(Object[] objects) {
ResultSet rs = null;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
initilize();
mylog=id.getText().toString();
mypass=pass.getText().toString();
}
});
try{
Statement statement=connect.createStatement();
rs=statement.executeQuery("LOGIN '"+mylog+"', '"+mypass+"'");
}catch(Exception e){
e.printStackTrace();
}
if(mylog.equals("")||mypass.equals("")){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(activity.getApplicationContext(), "empty fields", Toast.LENGTH_SHORT).show();
}
});
} else
try {
if(rs.next()){
result = true;
}
else if(rs.next()==false){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(activity.getApplicationContext(), "incorrect login", Toast.LENGTH_SHORT).show();
id.setText("");
pass.setText("");
}
});
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object o) {
//hide your progress dialog
if(result == Boolean.TRUE){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Intent i=new Intent(activity.getApplicationContext(),Act2.class);
activity.startActivity(i);
}
});
}
}
}
then in your Activity you do this:
MyAsyncTask a = new MyAsyncTask(this, connect); //im guessing "connect" is your Connection object
a.execute();
As i said i made this fast refactoring for the code to work but best practice and good implementation is not in consideration here.
Maybe, you could use a timer, to check if your
login is ready. As long as it is not, you Show your progress Bar. If its ready, you can close the Bar and start a new activity or anything. timers run can run on u UI thread.
regards :)
Here is my code segment I am trying to dismiss dialog but it is not getting dismissed and also i don't get any error on logcat.Please correct me where i am wrong ?
All the Log.v statement get executed.Even log.v statement after pd.dismiss() (Log.v("TAG","progress dismiss");) gets printed.
Please point my mistake or suggest some alternative way to dismiss the progressdialog.
btnSave.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//do something
} else {
Log.v("TAG","above progressDialog");
final ProgressDialog pd = new ProgressDialog(ChangePassword.this);
ProgressDialog.show(ChangePassword.this, "", "Loading...", false, true);
new Thread() {
public void run() {
try {
sleep(2000);
Log.v("TAG","in try block");
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
// dismiss the progress dialog
pd.dismiss();
// Log.v("TAG","progress dismiss");
}
}.start();
Log.v("TAG","after start");
public void run()
{
try{
if (!(txtOldPass.getText().toString())
.equals(SetGetValues.getPassword())) {
Toast.makeText(ChangePassword.this,
"Invalid Old Password", Toast.LENGTH_SHORT)
.show();
txtOldPass.setText("");
txtNewPass.setText("");
txtCnfPass.setText("");
} else {
if (!(txtNewPass.getText().toString())
.equals(txtCnfPass.getText().toString())) {
Toast.makeText(ChangePassword.this,
"Re-Enter New Password",
Toast.LENGTH_SHORT).show();
txtOldPass.setText("");
txtNewPass.setText("");
txtCnfPass.setText("");
} else {
try {
handler = new Handler();
handler.postDelayed(new Thread (new Runnable(){
JSONStringer loginuser = new JSONStringer()
.object()
.key("userid")
.value(SetGetValues.getUserid()
.trim())
.key("password")
.value(txtCnfPass.getText()
.toString().trim())
.key("oldpassword")
.value(txtOldPass.getText()
.toString().trim())
.endObject();
StringEntity entity = new StringEntity(
loginuser.toString());
JSONObject results = bc
.returnJSONObject(loginuser,
"url");
String message = results
.getString("message");
String isvalid = results
.getString("isvalid");
if (isvalid.contains("FALSE")) {
} else {
//pd.dismiss();
Toast.makeText(
ChangePassword.this,
"Password changed successfully",
Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
//TODO: handle exception
e.printStackTrace();
}
}
}
}catch(Exception e)
{
e.printStackTrace();
}
}
}), 1000);
}
}
});
You are not dismissing the same ProgressDialog that you are showing. Replace this:
final ProgressDialog pd = new ProgressDialog(ChangePassword.this);
ProgressDialog.show(ChangePassword.this, "", "Loading...", false, true);
with this:
final ProgressDialog pd = ProgressDialog.show(ChangePassword.this, "", "Loading...", false, true);
if (pd.isShowing()) {
pd.dismiss();
}
Instead of using thread Use Async Task
usage
You problem probably is, that you're trying to modify the UI (dismiss the dialog) from another thread. I'm surprised that you don't get an error message. Try dismissing the dialog from the UI thread, for example by using .runOnUIThread().
Because you are trying to use element of UI Thread progressDialog in a non UI thread .
This will be allowed through AsyncTask , handler or RunOnUIThread(runnable) only .
read more about them and use any one .