I am getting an error when I set the counter to subtract and close the application. I get an error "cannot assign value to final variable counter". If the user logins in 3 times with no success quit the application.
final int counter = 3;
//Set the OKButton to accept onClick
OKButton.setOnClickListener(new View.OnClickListener() {
#Override
//once onClick is initalized it takes user to page menu
public void onClick(View v) {
//display text that was inputed for userText and passText
user = userText.getText().toString();
pass = passText.getText().toString();
//create if loop which checks if user and pass equals the credentials
if (user.equals("pshivam") && pass.equals("Bway.857661")) {
//display toast access welcome
String welcome = "Access Granted.";
//Create a Toast to display the welcome string in the MainActivity.
Toast.makeText(MainActivity.this, welcome, Toast.LENGTH_SHORT).show();
setContentView(R.layout.account_main);
}
//create else if loop which checks if user or pass does not equals the credentials
else if (!user.equals("pshivam") || !pass.equals("Bway.857661")){
//displays previous entry
userText.setText(user);
passText.setText(pass);
//allows user to re-enter credentials.
user = userText.getText().toString();
pass = passText.getText().toString();
//display toast access fail
String fail = "Access Denied! Please Try again.";
//Create a Toast to display the fail string in the MainActivity.
Toast.makeText(MainActivity.this, fail, Toast.LENGTH_SHORT).show();
counter--;
if(counter == 0){
finish();
}
}
}
});
}
}
Do something like this :
OKButton.setOnClickListener(new View.OnClickListener() {
int counter = 3;
#Override
//once onClick is initalized it takes user to page menu
public void onClick(View v) {
You can also call a function from inside onClick which will decrement the variable, or use a static field declared in your class
This How to increment a Counter inside an OnClick View Event and How do I use onClickListener to count the number of times a button is pressed? might help.
Edit:
What you are doing in else part doesn't make sense. You are setting text for userText and passText that you just got using getText() from these. Then you are storing these same values to user and pass. But you aren't using these variables anywhere and they get new values when onClick is called again. Why not keep it simple :
else {
//display toast access fail
String fail = "Access Denied! Please Try again.";
//Create a Toast to display the fail string in the MainActivity.
Toast.makeText(MainActivity.this, fail, Toast.LENGTH_SHORT).show();
counter--;
if(counter == 0){
finish();
}
}
Im starting to get crazy on my problem here.
I have a main activity that connects to a server on onCreate event, (the program must be connected to the server or else it shall not be working).
client_thread = new ServerCom(this);
Now I want to create a login view with (Username, Password and Login buttom with a user exist validation).
And when there is a login view there has to be some sort of registration view (with Username, Password, confim Password and a Registration button with a user exist validation).
I have create a Login and Registration Activity (for handeling some data with login and registration).
public ClassLogIn(MainActivity owner)
{
this.owner = owner;
}
public ClassLogIn()
{
}
public void onClick(View view) {
if(view == btnLogIn)
{
if(TextUtils.isEmpty(userName.getText()) == false) {
if (TextUtils.isEmpty(userPassword.getText()) == false) {
owner.LogIn(userName.getText(),userPassword.getText());
}
...
To start the activitys from my mainActivity I have done this
else if(id == R.id.action_login){
Intent myIntent = new Intent(MainActivity.this, ClassLogIn.class);
startActivity(myIntent);
}
else if(id == R.id.action_registera){
Intent myIntent = new Intent(MainActivity.this, ClassRegistera.class);
startActivity(myIntent);
}
else if(id == R.id.action_Logout)
{
client_thread.LogOut();
}
Now my problem is how can I get the userName value to my client_thread?
And also how can I call Owner.LogIn from my ClassLogIn activity?
public boolean LogIn(Editable UserName, Editable Password)
{
return client_thread.LogIn(UserName.toString(),Password.toString());
}
Or do I trying to make something that is impossible in Android?
From the top of my head set up some IntentServies to catch intents and make then
set up your variables.
And static variables are not an option ?
(Would add a comment but don't have enough reps)
The specific code to do the following can differ depending on your specifics.
But in general, the procedure we do is the following:
NOTE - We use the WorkingStorage API to save parameters directly into the HHU (Hand Held Unit)
When we initially launch we make an attempt to retrieve from within the HHU the login credentials which includes an Authorization ID.
If they are present, we utilize the Authorization ID for subsequent WebService calls as needed throughout the Activities.
If they are Not present, we launch a User Data Entry 'screen' and get Username & Password input.
Then we send that data to the Server via a WebService call for validation.
The WebService responds to the HHU with a Result.
That Result is either a Valid Authorization ID or an Error Message (such as 'Not Valid', etc.).
If it is a Valid Authorization ID, then all of the login credentials are saved to the HHU with the WorkingStorage API and are then available to be utilized for subsequent WebService calls.
In my app, I want users to be able to register themselves. If another user before them has already used that particular emailadress or username the app should say so and not let them upload data to the server.
Right now my problem is, that the main thread does not wait for the two background tasks that check if username or email already exist, but keeps going so every user object is sent to the server, even though they already exist.
Here is my code to check username and email:
public void checkEmailadress(String s){
ParseQuery<ParseObject> query = ParseQuery.getQuery("userLogin");
query.whereEqualTo("emailadress",s);
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> arg0, ParseException e) {
// TODO Auto-generated method stub
Iterator itr = arg0.iterator();
if(itr.hasNext()){
emailadressInUse = true;
}else{
emailadressInUse = false;
}
System.out.println(emailadressInUse);
finishSubmittingUser();
}
});
}
same goes for checking the username. This works fine. The problem is, boolean emailadressInUse does not change fast enough for the main thread to change action.
here is the method that initiates those two methods
public void submitNewUser(View view){
EditText edittext1 = (EditText) findViewById(R.id.chose_username);
EditText edittext2 = (EditText) findViewById(R.id.chose_realname);
EditText edittext3 = (EditText) findViewById(R.id.chose_emailadress);
EditText edittext4 = (EditText) findViewById(R.id.chose_password);
username = edittext1.getText().toString();
realname = edittext2.getText().toString();
emailadress = edittext3.getText().toString();
password = edittext4.getText().toString();
checkUsername(username);
checkEmailadress(emailadress);
}
this is called from inside checkEmail. The two booleans should have changed state by now. And according to System.out.println in checkEmail they did. So why is my method finishSubmittingUser not picking up on that change?
public void finishSubmittingUser(){
if((usernameInUse==false) && (emailadressInUse==false)){
saveDataChange("realname", realname);
ParseObject userLogin = new ParseObject("userLogin");
userLogin.put("username", username);
userLogin.put("emailadress", emailadress);
userLogin.put("password", password);
userLogin.saveInBackground();
Intent intent = new Intent(this, LogInUserActivity.class);
intent.putExtra(USERNAME, username);
startActivity(intent);
}
else{
if(usernameInUse==true){
Toast.makeText(getApplicationContext(),getString(R.string.username_in_use),Toast.LENGTH_SHORT).show();
}
if(emailadressInUse==true){
Toast.makeText(getApplicationContext(),getString(R.string.emailadress_in_use),Toast.LENGTH_SHORT).show();
}
}
}
There must be an easy way to do this that i´m not seeing right now.
Thanks for your help.
Make the main thread wait for backgroundtasks to finish?
As Emmanuel said, do not block the main application thread.
Right now my problem is, that the main thread does not wait for the two background tasks that check if username or email already exist, but keeps going so every user object is sent to the server, even though they already exist.
If "every user object is sent to the server" is something the user does, after registration, simply disable the UI for that (e.g., disable the action bar item) until your registration is confirmed.
If "every user object is sent to the server" is something that happens automatically after a successful registration, then you should not be executing that code until after a successful registration.
Update: Thank you all for attempting to help me solve this bug. I am still unsure as to the cause, I was able to roll back to a previous commit and continue development from there. This previous commit did show the same bug, however after I commented out button.performClick() it went away. Strangely, this does not work on the most recent commit.
I still do not understand this bug and would appreciate any more assistance in helping determine the root cause. My greatest fear would be to inadvertently re-introduce it.
I have the most crazy error I have ever seen.
The OnCreate method is being called over and over again, freezing my application and giving me a slight flicker. The only solution is then to exit to the home screen and force quit the application from the settings menu.
Here is what is happening in detail:
Application starts (Main Activity)
Main Activity calls the Second Activity
Second Activity calls onCreate, sets up as normal
Second Activity randomly decides to exit onCreate <-- I think this what's happening
Second Activity's onCreate gets called again. It doesn't ever return to the Main Activity.
I have run a debugger, it appears that the second activity successfully completes the onComplete/onResume sequence, then decides to exit and restart.
Has anybody ever heard of this behavior before?
I haven't noticed any exceptions being thrown. Also, in the course of debugging, I did go ahead and check those locations that you see as silent fail. (this is the older code before I littered it with print statements)
UPDATE: When attempting to stop the process, I must turn on airplane mode. This means it has something to do with this code block (Second Activity)
else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId())
{...}
With no internet, it will hit the else statement and does not display this behavior.
CODE:
onResume() of the Main Activity, where I call the Second Activity:
#Override
public void onResume()
{
super.onResume();
//Check If logged in, else go to login page
Login.setContext(getApplicationContext());
//Reset Notification Number
GCMIntentService.cancelNotifications();
/** GO TO LOGIN **/
if(!Login.isLoggedIn())
{
//If user is not logged in, open login page
System.out.println("RESUMING MAIN AND STARTING LOGIN INTENT");
Intent intent = new Intent(ActivityMain.this, ActivityLogin.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else
{
Login.setupStuffOnce();
Event.pullEvents(); //Get New Events
//Update ListView
updateMainFeed();
}
}
This is the Second Activity:
public class ActivityLogin extends Activity
{
private String postData;
//private Context c;
//final Timer timer = new Timer();
//Facebook Stuff
private Facebook facebook = new Facebook(Config.FBAPPID);
private AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);
//Layout Stuff
EditText username, password;
Button loginButton, signupButton;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Open Database
Login.setContext(getApplicationContext());
Database.open(getApplicationContext());
}
/*
* #Override public void onPause() { s }
*/
#Override
public void onResume()
{
super.onResume();
// shouldn't put here but oh well
init();
//If coming from ActivitySignup
if(Transfer.username != null)
{
username.setText(Transfer.username);
password.setText(Transfer.password);
Transfer.password = null;
Transfer.username = null;
loginButton.performClick();
}
}
public void init()
{
Login.getUserLoggedIn();
if (Login.isLoggedIn())
{
//Do Any Additional Setup
Login.setupStuffOnce();
// If user is logged in, open main
Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId())
{
// Else, Make User Login
// Inflate Login and Present Website
String clientid = Login.getClientId();
System.out.println("clientid:" + clientid);
//System.exit(0);
postData = "mobile=1&client_id="+Login.getClientId();
// Inflate the view
setContentView(R.layout.activitylogin3);
username = (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
//Inflate the Button
loginButton = (Button) findViewById(R.id.loginButton);
signupButton = (Button) findViewById(R.id.signupButton);
signupButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityLogin.this, ActivitySignup.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
});
loginButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int res = Login.sendLogin(username.getText().toString(), password.getText().toString());
if(res == 202)
{
//Login Successful
//Check if facebooked.
if(Login.isFacebooked())
{
//Just go to main
Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
//Are these flags necessary?
//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else
{
//Go to facebook login page
//Intent intent = new Intent(ActivityLogin.this, ActivityFBLogin.class);
//startActivity(intent);
//Login via Facebook
doFacebook();
}
} else
{
System.out.println("Login Failed: "+res);
if(res == 405)
{
Toast.makeText(getApplicationContext(), "Incorrect Username/Password", Toast.LENGTH_SHORT).show();
password.setText("");
}
else
Toast.makeText(getApplicationContext(), "Network Error", Toast.LENGTH_SHORT).show(); //Not entirely true in all cases i think
}
/*Login.getUserLoggedIn();
if(Login.isLoggedIn())
{
Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
Toast.makeText(getApplicationContext(), "Please Login Above", Toast.LENGTH_SHORT).show();
}*/
}
});
} else
{
// Not Logged In and No Internet Access
setContentView(R.layout.activitylogintext);
EditText text = (EditText) findViewById(R.id.text);
text.setText("No Internet Connection Detected\n requires internet to login");
Button button = (Button) findViewById(R.id.refreshButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
//Login.getUserLoggedIn();
if(Network.haveNetworkConnection(Login.getContext()))
{
Intent intent = new Intent(ActivityLogin.this, ActivityLogin.class);
//intent.setFlags();
startActivity(intent);
} else {
Toast.makeText(getApplicationContext(), "No Internet Access Detected", Toast.LENGTH_SHORT).show();
}
}
});
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
facebook.authorizeCallback(requestCode, resultCode, data);
}
public void doFacebook()
{
facebook.authorize(this, Config.facebookPermissions, new DialogListener() {
#Override
public void onComplete(Bundle values) {
/*SharedPreferences.Editor editor = state.edit();
editor.putString("access_token", facebook.getAccessToken());
editor.putLong("access_expires", facebook.getAccessExpires());
editor.commit();
*/
//Input into database
Login.saveAccessToken(facebook.getAccessToken());
Login.setFB(facebook.getAccessToken());
//Login.sendAccessToken(facebook.getAccessToken());
//Intent into Main Activity
Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
#Override
public void onFacebookError(FacebookError error) {
Toast.makeText(getApplicationContext(), "Error: "+error.getErrorType(), Toast.LENGTH_SHORT).show();
}
#Override
public void onError(DialogError e) {
Toast.makeText(getApplicationContext(), "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onCancel() {}
});
}
public boolean checkForUserID(Context c)
{
try{
String res = Network.getUrl("www.website.com/mobile.php?got_user=1&client_id="+Login.getClientId());
JSONObject json = JSON.constructObject(res);
if(JSON.handleCode(json))
{
if(json.getString("type").equals("userid"))
{
Login.setLogin(json.getString("data"));
return true;
}
}
} catch(Exception e)
{
//Silent Fail
}
return false;
}
}
I believe that the problem will be resolved if you finish your MainActivity after you call SecondActivity. The problem probably is that the onResume event is immediatelly fired when you resume your MainActivity. That is because the MainActivity was probably destroyed and recreated while it was in background. Another solution would be to save your Activity's state with onSaveInstanceState. See here for more information.
Check this code in your activity:
Button button = (Button) findViewById(R.id.refreshButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(Network.haveNetworkConnection(Login.getContext()))
{
Intent intent = new Intent(ActivityLogin.this, ActivityLogin.class);
//intent.setFlags();
startActivity(intent);
} else {
Toast.makeText(getApplicationContext(), "No Internet Access Detected", Toast.LENGTH_SHORT).show();
}
}
});
Here you are calling ActivityLogin itself.
That's why the onCreate() is being called again and again.
I had a similar problem once. The problem occurred because I made configuration changes without declaring them in the android:configChanges attribute of the <activity> tag (and hence it recreates itself the whole time).
For example, if you change the locale manually you need to add locale to android:configChanges!
It seems to me there is a good chance for endless cycling here if Login is not properly shared between the activities, causing Login.isLoggedIn() to return true in ActivityLogin but false in ActivityMain.
A few critical factors are where your Login object is located, is it static, how is it referenced between Activities? It is entirely possible that ActivityMain is being destroyed while ActivityLogin is active; storing the Login data in SharedPreferences or a database, or otherwise persisting it is important. How does isLoggedIn() resolve (determine its return value?)
Suggestion 1: Consider making use of the Singleton pattern (if you haven't already.)
Suggestion 2: While discouraged, you could store Login at the Application level.
Suggestion 3: You can try using Intent.FLAG_ACTIVITY_SINGLE_TOP to reduce the likelyhood of a new ActivityMain being created - which might not have access to Login, again depending on how you have it stored.
ActivityMain
onResume() {
if(!Login.isLoggedIn()) {
/* Not logged in, launch ActivityLogin! */
Intent intent = new Intent(ActivityMain.this, ActivityLogin.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
ActivityLogin
onResume() { /* ... */ init(); }
init() {
Login.getUserLoggedIn();
if (Login.isLoggedIn()) {
/* Internet - launch ActivityMain! */
Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // <--- suggested addition
startActivity(intent);
else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId()) {
/* No internet, the user was unable to login. */
}
I think your main problem is with you onResume function as it gets called each time it comes back into view (eg: you start second activity, finish it, main activity onResume is called again. If you finish your second activity (or it quietly crashes for some reason) you will go back to your mainActivity and call onResume (which will start the cycle all over again).
Now i dont know if you are finishing activity 2 somehow but I would check that.
EDIT:
ALso I would put some logcats here
if (Login.isLoggedIn())
{
//Do Any Additional Setup
Login.setupStuffOnce();
// If user is logged in, open main
Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
Log.i("Some Tag", "Starting Main Activity From Activity 2");
startActivity(intent);
}
The above adding of the log.i will allow you to know if this is where the error happens, and you can go from there.
I had similar problem where the activity would be recreated all the time. Re-installing the app wouldn't help, but restarting the phone did the job.
I want to make that when the user click the button below and the String on EditText is empty, it shows a dialog.
So I made this method, but unfortunately rather than showing a Dialog Box, the app crashed. There's no problem with the Dialog box method, the problem is the IF function doesn't read what I requested properly.
Anybody has the solution for this?
Here's my method:
public void onClick(View v) {
if(v == launchSimplePayment) {
String amount = paymentAmount.getText().toString();
System.out.println(amount);
if (amount == "")
{
errorDialog();
}
else
{
System.out.println(amount);
// Use our helper function to create the simple payment.
PayPalPayment payment = exampleSimplePayment();
// Use checkout to create our Intent.
Intent checkoutIntent = PayPal.getInstance().checkout(payment, this, new ResultDelegate());
// Use the android's startActivityForResult() and pass in our Intent. This will start the library.
startActivityForResult(checkoutIntent, request);
}
}
Change this
if (amount == "")
with this
if (amount.equals(""))
Remember that the operator == compares references, not the content!
You should rewrite the condition like this:
if (amount.trim().equals(""))
Since a blank space like this " " would pass over your validation check.