I have been able to successfully implement the Facebook login button. My only problem now is I'm having trouble checking if the user already logged in.
This is code for when the user clicks the login button:
loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
GraphRequest request = GraphRequest.newMeRequest(loginResult.getAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
getFacebookData(object);
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "name, email, picture");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException error) {
}
});
getFacebookData has this code:
private void getFacebookData(JSONObject object) {
try {
Intent intent = new Intent(MainActivity.this, Profile.class);
String fb_name = object.getString("name");
String fb_email = object.getString("email");
URL profile_picture = new URL("http://graph.facebook.com/" + object.getString("id") + "/picture?type=large");
intent.putExtra("name", fb_name);
intent.putExtra("email", fb_email);
intent.putExtra("profile_picture", profile_picture.toString());
intent.putExtra("userOption", 2);
startActivityForResult(intent, 1);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
Basically, when the user logs in successfully, it sends the user's name, email, and profile picture data to the Profile activity.
Now, what I have in my onCreate method inside my MainActivity class is:
AccessToken accessToken = AccessToken.getCurrentAccessToken();
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();
if (isLoggedIn) {
}
This above code checks to see if the user has already logged in with their Facebook account. What I want to put inside the if statement is getFacebookData() because this will send data to the Profile activity and start the Profile activity immediately instead of going to the MainActivity. My problem is, I have to pass in a JSONObject.
What should I do to fix this as I don't know what JSONObject to pass into the getFacebookData() function?
First, you can store the user name, email and id permanently in you application (e.g. shared preferences).
To insert:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("fbId", fbId);
editor.putString("fbEmail", fbEmail);
editor.putString("fbName", fbName);
editor.commit();
To retrieve:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
String fbId= sharedPref.getString("fbId");
String fbEmail = sharedPref.getString("fbEmail");
String fbName= sharedPref.getString("fbName");
If you really want to request those again, you can use following method:
AccessToken accessToken = AccessToken.getCurrentAccessToken();
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();
if (isLoggedIn) {
GraphRequest request = GraphRequest.newMeRequest(loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
getFacebookData(object);
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "name, email, picture");
request.setParameters(parameters);
request.executeAsync();
}
Related
So I was trying to implement a feature on my android app where users can register and login to the app. I made it where the user credentials are stored to an external and can be validated with the Django REST API I made.
So before I can let my app access that API page, I have to make sure it goes with OAuth2 rules. However, it requires me to login to an /accounts/login page. Do I need to make that page or can I change the url if don't want that path or maybe not login as admin at all?
It keeps me wanting to login before I can authorize my app.
login.java
public class Login extends AppCompatActivity {
Button LoginButton, RegButton;
EditText uUserName, uPassWord;
WSAdapter.SendAPIRequests AuthHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//SetupHomeBtn = (ImageButton) findViewById(R.id.SetupHomeBtn);
LoginButton = (Button) findViewById(R.id.LoginButton);
RegButton = (Button) findViewById(R.id.LoginRegister);
uUserName = (EditText) findViewById(R.id.LoginUserBox);
uPassWord = (EditText) findViewById(R.id.LoginPassBox);
//AuthHelper = new WSAdapter().new SendDeviceDetails();
// Moves user to the main page after validation
LoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// gets the username and password from the EditText
String strUserName = uUserName.getText().toString();
String strPassWord = uPassWord.getText().toString();
//startActivity(new Intent(Login.this, Posts.class));
// To authorize oauth for requesting access token
OAuthClientRequest request = null;
try {
// sends authorization request with credentials to the server
request = OAuthClientRequest
.authorizationLocation("http://192.168.0.18:8000/auth/authorize")
.setClientId("mNUNXI4MinYyVvsRi1VPiv7ltrZWBOzr3OfnHJa1").setRedirectURI("http://oauthresponse")
.buildQueryMessage();
} catch (OAuthSystemException e) {
Log.d("TAG", "OAuth request failed", e);
}
// authentication service requires &reponse_type=code
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(request.getLocationUri() + "&response_type=code"));
startActivity(intent);
// API url duh
String APIUrl = "http://192.168.0.18:8000/token-auth/";
// If the user is authenticated, then transfer to the MainActivity page
if (APIAuthentication(strUserName, strPassWord, APIUrl)){
startActivity(new Intent(Login.this, Posts.class));
}
}
});
RegButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// gets the username and password from the EditText
startActivity(new Intent(Login.this, Register.class));
}
});
}
// to handle authorization for the redirect_url
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
Uri uri = intent.getData();
if (uri != null && uri.toString()
.startsWith("http://oauthresponse"))
{
String code = uri.getQueryParameter("code");
}
}
private boolean APIAuthentication(String un, String pw, String url){
// when it wasn't static -> AuthHelper = new WSAdapter().new SendAPIRequests();
AuthHelper = new WSAdapter.SendAPIRequests();
JSONObject postData = new JSONObject();
try {
// Attempt to input info to the Django API
postData.put("username", un);
postData.put("password", pw);
// Putting the data to be posted in the Django API
//AuthHelper.execute(url, postData.toString());
return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
}
I made an app that requires the user to register. The first time user opens the app - login screen opens. They need to click on the "go to register" button to go to register activity. After they register, they are automatically logged in.
Now here is the issue - when the user first registers he is sent to MainActivity. He should press back and the app should close. But when he tries to exit the app he presses the back button and instead of app closing it goes back to login screen.
The next time I try to sign in, I have no problem - it goes straight to the MainActivity.
This is how my activities look like:
LoginActivity:
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private static final int REQUEST_REGISTER = 0;
#InjectView(R.id.input_email) EditText _emailText;
#InjectView(R.id.input_password) EditText _passwordText;
#InjectView(R.id.btn_login) Button _loginButton;
#InjectView(R.id.link_register) TextView _registerLink;
CheckBox checkBoxShowPassword;
private SessionManager session;
private SQLiteHandler db;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.inject(this);
// SQLite database handler
db = new SQLiteHandler(getApplicationContext());
// Session manager
session = new SessionManager(getApplicationContext());
// Check if user is already logged in or not
if (session.isLoggedIn()) {
// User is already logged in. Take him to main activity
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
_loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String email = _emailText.getText().toString().trim();
String password = _passwordText.getText().toString().trim();
if (!email.isEmpty() && !password.isEmpty()) {
// login user
login(email, password);
} else {
// Prompt user to enter credentials
Toast.makeText(getApplicationContext(),
"Please enter the credentials!", Toast.LENGTH_LONG)
.show();
}
}
});
// Go to register screen
_registerLink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Start the Register activity
Intent intent = new Intent(getApplicationContext(), RegisterActivity.class);
startActivityForResult(intent, REQUEST_REGISTER);
}
});
// Password checkbox
checkBoxShowPassword = (CheckBox) findViewById(R.id.checkBoxShowPassword);
checkBoxShowPassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// checkbox status is changed from uncheck to checked.
if (!isChecked) {
// show password
_passwordText.setTransformationMethod(PasswordTransformationMethod.getInstance());
} else {
// hide password
_passwordText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
}
}
});
}
// Login
public void login(final String email, final String password) {
Log.d(TAG, "Login");
if (!validate()) {
onLoginFailed();
return;
}
// Change to false for disabling after error
_loginButton.setEnabled(true);
String tag_string_req = "req_login";
final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
// TODO: Implementing authentication logic
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL_LOGIN, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response.toString());
progressDialog.dismiss();
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
// user successfully logged in
// Create login session
session.setLogin(true);
// Now store the user in SQLite
String uid = jObj.getString("uid");
JSONObject user = jObj.getJSONObject("user");
String name = user.getString("name");
String email = user.getString("email");
String created_at = user
.getString("created_at");
// Inserting row in users table
db.addUser(name, email, uid, created_at);
// Launch main activity
Intent intent = new Intent(LoginActivity.this,
MainActivity.class);
startActivity(intent);
finish();
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast toast = Toast.makeText(getApplicationContext(),
"Registration failed due to connectivity issues", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
// _loginButton.setEnabled(true);
progressDialog.dismiss();
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting parameters to login url
Map<String, String> params = new HashMap<String, String>();
params.put("email", email);
params.put("password", password);
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
#Override
public void onBackPressed() {
// disable going back to the MainActivity
moveTaskToBack(true);
}
public void onLoginSuccess() {
_loginButton.setEnabled(true);
finish();
}
public void onLoginFailed() {
Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show();
_loginButton.setEnabled(true);
}
// Validation
public boolean validate() {
boolean valid = true;
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
_emailText.setError("Enter a valid email address");
valid = false;
} else {
_emailText.setError(null);
}
if (password.isEmpty() || password.length() < 4 || password.length() > 20) {
_passwordText.setError("Enter between 4 and 20 alphanumeric characters");
valid = false;
} else {
_passwordText.setError(null);
}
return valid;
}
}
RegisterActivity
public class RegisterActivity extends AppCompatActivity {
private static final String TAG = "RegisterActivity";
#InjectView(R.id.input_name) EditText _nameText;
#InjectView(R.id.input_email) EditText _emailText;
#InjectView(R.id.input_password) EditText _passwordText;
#InjectView(R.id.btn_register) Button _registerButton;
#InjectView(R.id.link_login) TextView _loginLink;
CheckBox checkBoxShowPassword;
private SessionManager session;
private SQLiteHandler db;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
ButterKnife.inject(this);
// Session manager
session = new SessionManager(getApplicationContext());
// SQLite database handler
db = new SQLiteHandler(getApplicationContext());
// Check if user is already logged in or not
if (session.isLoggedIn()) {
// User is already logged in. Take him to main activity
Intent intent = new Intent(RegisterActivity.this,
MainActivity.class);
startActivity(intent);
finish();
}
// Register button
_registerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name = _nameText.getText().toString().trim();
String email = _emailText.getText().toString().trim();
String password = _passwordText.getText().toString().trim();
String phone = getMyPhoneNumber();
if (!name.isEmpty() && !email.isEmpty() && !password.isEmpty()) {
register(name, email, password, phone);
} else {
Toast.makeText(getApplicationContext(),
"Please enter your details!", Toast.LENGTH_LONG)
.show();
}
}
});
// Go to login screen
_loginLink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Finish the registration screen and return to the Login activity
finish();
}
});
// Password checkbox
checkBoxShowPassword = (CheckBox) findViewById(R.id.checkBoxShowPassword);
checkBoxShowPassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// checkbox status is changed from uncheck to checked.
if (!isChecked) {
// show password
_passwordText.setTransformationMethod(PasswordTransformationMethod.getInstance());
} else {
// hide password
_passwordText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
}
}
});
}
// Register
public void register(final String name, final String email, final String password, final String phone) {
Log.d(TAG, "Register");
if (!validate()) {
onRegisterFailed();
return;
}
_registerButton.setEnabled(false);
String tag_string_req = "req_register";
final ProgressDialog progressDialog = new ProgressDialog(RegisterActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Creating Account...");
progressDialog.show();
// TODO: Implementing register logic
StringRequest strReq = new StringRequest(Request.Method.POST,
AppConfig.URL_REGISTER, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Register Response: " + response.toString());
progressDialog.dismiss();
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
if (!error) {
// User successfully stored in MySQL
// Now store the user in sqlite
String uid = jObj.getString("uid");
JSONObject user = jObj.getJSONObject("user");
String name = user.getString("name");
String email = user.getString("email");
String created_at = user
.getString("created_at");
// Inserting row in users table
db.addUser(name, email, uid, created_at);
//TODO: insert contacts to local db
String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
while (phones.moveToNext()) {
if (phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER) != -1)
{
String username = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
db.addContact(username, phoneNumber);
}
}
phones.close();
Toast.makeText(getApplicationContext(), "Registration successful!", Toast.LENGTH_LONG).show();
// Auto login
session.setLogin(true);
// Launch login activity
Intent intent = new Intent(
RegisterActivity.this,
MainActivity.class);
startActivity(intent);
finish();
} else {
// Error occurred in registration. Get the error
// message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Registration Error: " + error.getMessage());
Toast toast = Toast.makeText(getApplicationContext(),
"Registration failed due to connectivity issues", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
_registerButton.setEnabled(true);
progressDialog.dismiss();
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting params to register url
Map<String, String> params = new HashMap<String, String>();
params.put("name", name);
params.put("email", email);
params.put("password", password);
params.put("phone", phone);
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
public void onRegisterSuccess() {
_registerButton.setEnabled(true);
setResult(RESULT_OK, null);
finish();
}
public void onRegisterFailed() {
Toast.makeText(getBaseContext(), "Registration failed", Toast.LENGTH_LONG).show();
_registerButton.setEnabled(true);
}
// Validation
public boolean validate() {
boolean valid = true;
String name = _nameText.getText().toString();
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
if (name.isEmpty() || name.length() < 3) {
_nameText.setError("Enter at least 3 characters");
valid = false;
} else {
_nameText.setError(null);
}
if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
_emailText.setError("Enter a valid email address");
valid = false;
} else {
_emailText.setError(null);
}
if (password.isEmpty() || password.length() < 4 || password.length() > 20) {
_passwordText.setError("Enter between 4 and 20 alphanumeric characters");
valid = false;
} else {
_passwordText.setError(null);
}
return valid;
}
// Get users phone number
private String getMyPhoneNumber() {
TelephonyManager tMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String MyPhoneNumber = "0000000000";
try
{
MyPhoneNumber =tMgr.getLine1Number();
}
catch(NullPointerException ex)
{
}
if(MyPhoneNumber.equals("")){
MyPhoneNumber = tMgr.getSubscriberId();
}
return MyPhoneNumber;
}
private String getMy10DigitPhoneNumber() {
String s = getMyPhoneNumber();
return s.substring(2);
}
}
As per my idea you just do one thing that when you are passing from login activity to register_activity just finish the login_activity like this
// Go to register screen
_registerLink.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Start the Register activity
Intent intent = new Intent(getApplicationContext(), RegisterActivity.class);
startActivityForResult(intent, REQUEST_REGISTER);
LoginActivity.this.finish();
}
});
If you still facing the same problem then when you are opens the login_activity first then create a variable of that class and assign the value to that variable like this
public static LoginActivity mLogin_activity;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLogin_activity=LoginActivity.this;
Then check this value is null or not in onBackPressed() method in Main_Activity if that value is null then finish that main_activity otherwise finish that login_activity too; Something like this:
#Override
public void onBackPressed() {
super.onBackPressed();
if (LoginActivity.mLogin_activity!=null) {
LoginActivity.mLogin_activity.finish();
MainActivity.this.finish();
}else {
MainActivity.this.finish();
}
}
Hope i had answered your question...
when you write
Intent intent = new Intent(getApplicationContext(), RegisterActivity.class);
startActivityForResult(intent, REQUEST_REGISTER);
This must need to override onActivityResult method to handle that result.
In that code you just write
Intent intent = new Intent(getApplicationContext(), RegisterActivity.class);
startActivity(intent);
finish();
I hope this could be help you.
For me, I found out that I was calling a variable from another activity which was on my Register.xml (the progressbarBtn) instead of the progressbar that I inserted on Login.Java which was ProgressbarBtn3
thats why it is taking me back to the register page
I have a login screen with email and password fields. Once the user is validated, an access token is given to the user and updated appropriately.
However, when the app crashes and is restarted, the token is invalidated because the email and password are lost.
How can I recover the email and password in an onResume()?
private class UserLoginTask extends AsyncTask<Void, Void, String> {
private final String lurl;
private final String mEmail;
private final String mPassword;
UserLoginTask(String url, String email, String password) {
lurl = url;
mEmail = email;
mPassword = password;
}
#Override
protected String doInBackground(Void... params) {
try {
WebConnection conn = new WebConnection(lurl, getApplicationContext());
conn.addValuePair("username", mEmail);
Log.v("mEmail", mEmail);
conn.addValuePair("password", mPassword);
Log.v("mPassword", mPassword);
String response = conn.connect();
return response;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final String response) {
mAuthTask = null;
showProgress(false);
if(response != null) {
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putString("email", mEmail);
editor.putString("password", mPassword);
editor.apply();
}
//NEED TO GET RESPONSE FROM SERVER IF LOGIN BASED ON PREFS WAS SUCCESSFUL
if (success) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} else {
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
#Override
protected void onResume() {
super.onResume();
Context context = getApplicationContext();
SharedPreferences prefs;
prefs = context.getSharedPreferences("preferences", Context.MODE_PRIVATE);
String token = prefs.getString("token", null);
//NEED TO GET mEmail and mPassword values from other activity
if (mEmail == null) //Check if it isn't already set
mEmail = prefs.getString("email", null);
if (mPassword == null)
mPassword = prefs.getString("password", null);
if(token == null || token.isEmpty()){
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
}
Store it in SharedPreferences in your onPostExecute:
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putString("email", mEmail);
editor.putString("password", mPassword);
editor.apply();
Read it in your onResume:
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
if (mEmail == null) //Check if it isn't already set
mEmail = prefs.getString("email", null);
if (mPassword == null)
mPassword = prefs.getString("password", null);
//Do your stuff here, but check if the Strings are null before
The better way is of course to get rid of the crashes. It's not a good sign if you're sure that your app will crash, especially on the first screen.
If your application go crashed then all the data will be lost , but if you still want to persist you can either use sqlite or shared preferences with proper encryption scheme, since username and password sensitive data.
One way is to save the username and password in some SharedPreferences, before a login-try is made. Please see the documentation here: Google Devs. A simple saving would be:
SharedPreferences prefs = getSharedPreferences("MY_PREFERENCES", MODE_PRIVATE);
prefs.edit().putString("USERNAME", theUsername).commit();
prefs.edit().putString("PASSWORD", thePassword).commit();
This is my first attempt to create a login system in Android Studio and already got myself into trouble with my code.
My PHP script always returns something as JSON and I'm trying to parse that JSON in my LoginActivity, inside the login -method, but I'm getting
the following error after creditentials were forwarded to the server and the login button was clicked:
I/qtaguid﹕ Failed write_ctrl(u 43) res=-1 errno=22
I/qtaguid﹕ Untagging socket 43 failed errno=-22
W/NetworkManagementSocketTagger﹕ untagSocket(43) failed with errno -22
It did work earlier, when I was doing a stringRequest instead of jsonRequest, so everything should be fine on the server side. Since I'm very new to Android development, I'm unable to figure this one out by myself and need desperately your help.
Here's my LoginActivity without the imports:
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
// Define Views
private EditText editTextEmail, editTextPassword;
private Button buttonLogin;
private ProgressBar progress;
private UserLocalStore userLocalStore;
private boolean loggedIn = false;
private final String TAG = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide(); // Hides the Action Bar for Login Activity
setContentView(R.layout.activity_login); // Sets the Content View
// Initializing Views
// EditText fields
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);
// Buttons
buttonLogin = (Button) findViewById(R.id.buttonLogin);
// Other
progress = (ProgressBar) findViewById(R.id.progressBar);
// This method will set watcher for the EditTextFields
// The method will watch the value set to the EditTextFields.
// If there is nothing inputted in the EditTextField, "Login" button is disabled.
// Correspondingly, if there are text in the field, "Login" button is enabled.
watcher(editTextEmail, editTextPassword, buttonLogin);
// On-Click listeners
buttonLogin.setOnClickListener(this);
}
// Watcher method to check the value of EditText field
public void watcher(final EditText editText, final EditText editPassword, final Button button)
{
editText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
if (editText.length() == 0 && editPassword.length() == 0) // If length of the text field is equal to 0
button.setEnabled(false); // Disable the "Send" button
else
button.setEnabled(true); // Otherwise enable
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
if(editText.length() == 0 && editPassword.length() == 0)
button.setEnabled(false); //disable at app start
}
#Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences = getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
loggedIn = sharedPreferences.getBoolean(Config.LOGGEDIN_SHARED_PREF, false);
// If the value of loggedIn variable is true
if(!loggedIn) {
// We will start the Courses activity
Intent intent = new Intent(LoginActivity.this, CourseActivity.class);
startActivity(intent);
}
}
private void login() {
// Get the values from the edit texts
final String email = editTextEmail.getText().toString().trim();
final String password = editTextPassword.getText().toString().trim();
// Creating a JSON Object request
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, Config.LOGIN_URL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG, response.toString());
// This line will not print out
System.out.println(response);
try {
String json_status = response.getString("status");
String message = response.getString("message");
if(json_status.equalsIgnoreCase(Config.LOGIN_SUCCESS)) {
System.out.println(message);
}
} catch (JSONException e) {
Toast.makeText(getApplicationContext(), "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// You can handle the error here if you want
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
// Adding parameters to request
params.put(Config.KEY_EMAIL, email);
params.put(Config.KEY_PASSWORD, password);
// Return parameters
return params;
}
};
// Adding the string request to the queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonObjectRequest);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
// If button Login was clicked
case R.id.buttonLogin:
login(); // Start login method after "Login" button is clicked
// startActivity(new Intent(this, MainActivity.class));
break;
}
}
}
And here's my PHP:
<?php
require_once("dbconnect.php");
// POST Variables
$post_email = $_POST['email'];
$post_password = $_POST['password'];
// Prepare the SQL query
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(array(
':email' => $post_email,
));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($stmt->rowCount() > 0 && password_verify($post_password, $row['password']) && $row['role'] != 'staff') {
$user = array(); // Create an array for the user information
$user['id'] = $row['id'];
$user['name'] = $row['name'];
$user['email'] = $row['email'];
$user['password'] = $row['password'];
$user['role'] = $row['role'];
// echo json_encode(["message" => "success"]);
echo json_encode(["status" => "success", "message" => "Successfully logged in"]); // Format the array to JSON
} else {
echo json_encode(["status" => "error", "message" => "Incorrect creditentials"]);
}
You might not be passing the params, I usually use this syntax:
// Get the values from the edit texts
final String email = editTextEmail.getText().toString().trim();
final String password = editTextPassword.getText().toString().trim();
Map<String, Object> params = new ArrayMap<>(2);
// Adding parameters to request
params.put(Config.KEY_EMAIL, email);
params.put(Config.KEY_PASSWORD, password);
// Creating a JSON Object request
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, new JSONObject(params),
new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response)
{
Log.d(TAG, response.toString());
// other stuff ...
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
// You can handle the error here if you want
}
});
// Adding the string request to the queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonObjectRequest);
Also, you might want to handle all the volley requests in a Singleton class, have a look at this SO question.
Hope this helps in any way :)
as the title suggest i want my app to stay logged in even after the user close it ; i dont know how to achieve this
this is my code :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
callbackManager = CallbackManager.Factory.create();
setContentView(R.layout.activity_main);
prfpic = (ImageView) findViewById(R.id.profpic) ;
wel = (TextView) findViewById(R.id.WELCOME);
Info = (TextView) findViewById(R.id.info);
Info.setText("You Must Login To Use All The Features!");
loginButton = (LoginButton) findViewById(R.id.login_button);
List<String> permission=new ArrayList<String>();
permission.add("user_likes");
permission.add("user_videos") ;
permission.add("user_posts") ;
AfterSTRING = "" ;
loginButton.setReadPermissions(permission);
loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
actk = loginResult.getAccessToken();
GraphRequest request = GraphRequest.newMeRequest(
actk,
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
// Insert your code here
try {
wel.setVisibility(View.VISIBLE);
prfpic.setVisibility(View.VISIBLE);
wel.setText("Welcome " + object.getString("name"));
Picasso.with(getApplicationContext())
.load(object.getJSONObject("picture").getJSONObject("data").getString("url")).into(prfpic);
Info.setText("Hello");
}catch(Exception e) {
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "name,picture.type(large){url}");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
Toast.makeText(MainActivity.this, "Login Cancelled!!", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(FacebookException e) {
Toast.makeText(MainActivity.this, "Error! Please Ary Again!!", Toast.LENGTH_SHORT).show();
}
});
}
now the question is how to add preferences so the user will stay logged in until he logout
Here is my code to do that :
I made a class SessionManagerFacebook :
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import com.uigtc.crazyapp.Activities.LoginActivity;
import com.uigtc.crazyapp.Activities.MainActivity;
import java.util.HashMap;
public class SessionManagerFacebook {
// Shared Preferences
SharedPreferences pref;
// Editor for Shared preferences
Editor editor;
// Context
Context _context;
// Shared pref mode
int PRIVATE_MODE = 0;
// Sharedpref file name
private static final String PREF_NAME = "AppFacebook";
// All Shared Preferences Keys
private static final String IS_LOGIN = "IsLoggedIn";
public static final String KEY_LANG = "lang";
// Email address (make variable public to access from outside)
public static final String KEY_EMAIL = "email";
// Constructor
public SessionManagerFacebook(Context context) {
this._context = context;
pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
editor = pref.edit();
}
/**
* Create login session
*/
public void createLoginSession(String email, String lang) {
// Storing login value as TRUE
editor.putBoolean(IS_LOGIN, true);
editor.putString(KEY_LANG, lang);
editor.putString(KEY_EMAIL, email);
// commit changes
editor.commit();
}
public void changeLang(String lang) {
editor = pref.edit();
pref.getString(KEY_LANG, lang);
editor.apply();
}
/**
* Check login method wil check user login status
* If false it will redirect user to login page
* Else won't do anything
*/
public void checkLogin() {
// Check login status
if (!this.isLoggedIn()) {
// user is not logged in redirect him to Login Activity
Intent i = new Intent(_context, LoginActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Add new Flag to start new Activity
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Staring Login Activity
_context.startActivity(i);
}
}
/**
* Get stored session data
*/
public HashMap<String, String> getUserDetails() {
HashMap<String, String> user = new HashMap<String, String>();
user.put(KEY_EMAIL, pref.getString(KEY_EMAIL, null));
user.put(KEY_LANG, pref.getString(KEY_LANG, null));
// return user
return user;
}
/**
* Clear session details
*/
public void logoutUser() {
// Clearing all data from Shared Preferences
editor.clear();
editor.commit();
// After logout redirect user to Loing Activity
Intent i = new Intent(_context, MainActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Add new Flag to start new Activity
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Staring Login Activity
_context.startActivity(i);
}
/**
* Quick check for login
**/
// Get Login State
public boolean isLoggedIn() {
return pref.getBoolean(IS_LOGIN, false);
}
}
you can customize it as you want
Then on onCompleted method add these lines :
if (!sessionManagerFacebook.isLoggedIn()) {
sessionManagerFacebook.createLoginSession(object.getString("email"), getResources().getConfiguration().locale.toString());
//startActivity(new Intent(getActivity(), MainActivity.class));
} else {
user = sessionManagerFacebook.getUserDetails();
startActivity(new Intent(getActivity(), MainActivity.class));
}
now you have to check once App is open if user has logged in or not, example :
public class SplashScreen extends AppCompatActivity {
SessionManagerFacebook sessionManagerFacebook = new SessionManagerFacebook(this);
if (sessionManagerFacebook.isLoggedIn()) {
startActivity(new Intent(SplashScreen.this, MainActivity.class));
}
}