Parse.com Only one device session for a user. Android - android

I'm currently building an app that has Parse at its backend. I've realized that a user can log in to his account in multiple devices. Is there a way I could restrict this to only one device at one time? If so can you kindly explain the method.
Thanks in advance.

you need to monitor the application will your web environment (webservice for example) As soon as someone you login you must disconnect the other devices connected to the same user.
You can analyze it by IMEI who made the last login request and send a command to the other devices of the same user to remove access.

I came here looking for a solution and didn't find one. Through trial and error, I have solved it. I am a novice developer and do not know if this is the best practice, but it works. When the user attempts to log in execute the following.
public void login(View v) {
// Create string variables for data.
String username = et_username.getText().toString().toLowerCase().trim();
String password = et_password.getText().toString();
// If a user is already on this device, log them out.
// this will happen when the force log out happens, the device will
// simply catch the invalid session, but still have that user data, just unavailable
user = ParseUser.getCurrentUser();
if (user != null)
user.logOutInBackground();
ParseUser.logInInBackground(username, password, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException e) {
final ParseQuery<ParseObject> query = new ParseQuery<>("_Session");
query.include("user");
query.whereEqualTo("user", ParseUser.getCurrentUser()); // Only get sessions for the specific user.
query.addAscendingOrder("createdAt"); // Place them in chronological order, with the oldest at the top.
query.countInBackground(new CountCallback() {
#Override
public void done(int count, ParseException e) {
if (count > 1) {
try {
query.getFirst().deleteInBackground();
} catch (ParseException e1) {
Toast.makeText(LoginActivity.this, e1.toString(), Toast.LENGTH_LONG).show();
}
}
}
});
if (user != null) {
emailVerified = user.getBoolean("emailVerified");
if (emailVerified) {
// Update the database to track their log in.
user.put("loggedIn", true);
user.saveInBackground();
if (!deliquent) {
// Launch the MainActivity.
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
}
else {
Intent intent = new Intent(LoginActivity.this, CardActivity.class);
startActivity(intent);
}
}
else {
Toast.makeText(LoginActivity.this, getResources().getString(R.string.verify), Toast.LENGTH_SHORT).show();
}
}
else {
Toast.makeText(LoginActivity.this, "From LoginActivity line:213\n" + e.toString(), Toast.LENGTH_SHORT).show();
}
}
});
}

Related

Android: Web Services, Offline Capability

I am posting this question because I couldn't find any satisfactory answers online.
I am developing an Android App in which the data is fetched from the external server(in my case it's localhost MySQL server now) and displayed on the screen.
However, the constraint with this is that the person should always be connected to the internet to get all the data which can be viewed on the phone.
Now, what I would like to achieve is, once the data has been retrieved from the external server it should be stored on the device so that even though the user opens up the app without being connected to the internet, the previously fetched data should be showed to him.
In other words, I would like to have the offline capability.
How can I achieve this?
I have implemented the same for my app. Have a look at the code and you will understand how to do it. I have used Retrofit for the same. I have checked if the nursejson which is in sharedpreference is null. if it is null then continue further to hit API if not then load data from that sharedpreference.
To refresh the list, just check if you have internet connectivity and then delete that sharedpreference and call getnurse method again.
//After Oncreate
pref = getApplicationContext().getSharedPreferences("CachedResponse", 0);
editor = pref.edit();
editor.apply();
// Call getNurses method
getNurses();
//Method to get Nurses
public void getNurses() {
nurseJson = pref.getString("nurseJson", null);
if (nurseJson != null) {
progressBar.setVisibility(View.INVISIBLE);
gson = new Gson();
nurse = gson.fromJson(nurseJson, Nurse.class);
nurseList = nurse.getNurse();
namesArrayList.clear();
for (String nurses : nurseList) {
namesArrayList.add(nurses);
}
namesAdapter.notifyDataSetChanged();
} else {
Call<Nurse> call = apiInterface.getNursesList();
call.enqueue(new Callback<Nurse>() {
#Override
public void onResponse(Call<Nurse> call, Response<Nurse> response) {
progressBar.setVisibility(View.INVISIBLE);
onItemsLoadComplete();
if (response.isSuccessful()) {
nurse = response.body();
nurseJson = new Gson().toJson(nurse);
editor.putString("nurseJson", nurseJson);
editor.commit();
nurseList = nurse.getNurse();
namesArrayList.clear();
for (String nurses : nurseList) {
namesArrayList.add(nurses);
}
namesAdapter.notifyDataSetChanged();
} else {
utility.createSnackbar(coordinatorLayout, "Error Occurred, Please Try Again Later!");
}
}
#Override
public void onFailure(Call<Nurse> call, Throwable t) {
progressBar.setVisibility(View.INVISIBLE);
onItemsLoadComplete();
if (t.getLocalizedMessage() != null) {
if (t.getLocalizedMessage().contains("Unable to resolve host")) {
utility.createSnackbar(coordinatorLayout, "Please Check Internet Connection!");
} else {
utility.createSnackbar(coordinatorLayout, "Error Occurred, Please Try Again Later!");
}
} else {
utility.createSnackbar(coordinatorLayout, "Error Occurred, Please Try Again Later!");
}
}
});
}
}

Attach a user to an existing Parse role in Android

I have a user signup method that looks like this:
user.signUpInBackground(new SignUpCallback() {
public void done(ParseException e) {
if (e == null) {
// Link user to the 'User' role
ParseQuery<ParseRole> roleQuery = ParseRole.getQuery();
roleQuery.whereEqualTo("name", "User");
roleQuery.getFirstInBackground(new GetCallback<ParseRole>() {
#Override
public void done(ParseRole parseRole, ParseException e) {
if (e == null) {
//final ParseRole tempParseRl = parseRole;
ParseRelation<ParseUser> tempRel = parseRole.getUsers();
Log.i("ParseRole: ", parseRole.getName().toString());
parseRole.getUsers().add(user);
//TODO: 4. Delete reg key used for this user
}
// Error on Role ACL
else {
dMenuVerData.dismiss();
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
//1. Hide the progress bar
dataVerPBar.setVisibility(View.GONE);
//2. Show okBtn & successTxt
okBtn.setVisibility(View.VISIBLE);
userSuccessTxt.setVisibility(View.VISIBLE);
dataVerTitle.setText("Congratulations!");
//ParseRelation<ParseUser> tempRel = new ParseRelation<ParseUser>();
//tempParseRl.put("users");
} else {
// Dismiss dialog, show Parse error
dMenuVerData.dismiss();
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
On Parse I have two roles created on the data-browser.
After executing the line:
<role>.getUsers().add(user);
I'm expecting to be able to see the recently signed-up user under the "users , instead this table is empty:
What am I missing? Is the
<role>.getUsers().add(user);
working properly? Thanks.
The solution resides in using <role>.saveInBackground(); method after adding a new user to the ParseRelation, so after the signup succeeded I added:
...
parseRole.getUsers().add(user);
parseRole.saveInBackground();
...
I hope this helps.
you are not saving the role after you changed the users relation
what can i see that you added the user to (the local list you get from parseRole.getUsers() but you didn't saved it (to sync the changes with the remote version)

App Crahes in different devices

So, My app crashes on 3 other devices but it works fine on the device I have been using since the beginning of the development process. When I checked the LogCat, I got this error :
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.......MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method
java.lang.String
com.parse.ParseUser.getUsername() on a null object reference
I assume it is because of this code:
//get current user
ParseUser currentUser = ParseUser.getCurrentUser();
//get current user username and turn it to string
final String currentUserUsername = currentUser.getUsername();
//identify if current user is logged in
if (currentUser != null) {
// bring user to homepage and do stuff with the user
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("My");
query.orderByDescending("createdAt");
query.whereEqualTo("user", currentUserUsername);
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> personObject, ParseException e) {
if(e == null){
//success
Toast.makeText(MainActivity.this, "Welcome Back, " + currentUserUsername + "!", Toast.LENGTH_SHORT).show();
mPerson = peopleObject;
MyPeopleAdapter adapter = new MyPeopleAdapter(getListView().getContext(), mPerson);
setListAdapter(adapter);
} else {
//problem
Toast.makeText(MainActivity.this, "There is a problem. Please try again later.", Toast.LENGTH_SHORT).show();
}
}
});
} else {
// show the signup or login screen
Intent SignIn = new Intent(this, SignInActivity.class);
startActivity(SignIn);
}
But, how can this be a problem? I have been logging in and out of the app with the first device over and over again without any problem. And why is it causing problem with the other devices?
UPDATE:
I just found out if I remove the code, the app works just fine. But it doesn't work when I have the code.
You can avoid the crash by remove the problematic line from outside the Null checking and insert it to the if loop::
//identify if current user is logged in
if (currentUser != null) {
//get current user username and turn it to string
final String currentUserUsername = currentUser.getUsername(); //this line was outside earlier
//rest of code
}

Change password of parse user using parse SDK in Android

I am developing android application and using parse.com as back end storage. But I got stuck on change password. I am able to send the reset password mail using parse.com sdk to particular email. but I want to change the password using application as well without log enter code herein using old password.
Function to send mail:-
public void resetPassword() {
CustomProgressDialog.show(LoginActivity.this, "", getResources()
.getString(R.string.please_wait));
ParseUser.requestPasswordResetInBackground("test#gmail.com",
new RequestPasswordResetCallback() {
public void done(ParseException e) {
CustomProgressDialog.dismissMe();
if (e == null) {
// An email was successfully sent with reset
// instructions.
Toast.makeText(getApplicationContext(), getResources().getString(R.string.reset_password_sent), Toast.LENGTH_LONG).show();
} else {
// Something went wrong. Look at the ParseException
// to see what's up.
Toast.makeText(getApplicationContext(), getResources().getString(R.string.reset_password_fail), Toast.LENGTH_LONG).show();
}
}
}
);
}
And also able to launch the application from mail using declaring the permission in AndroidManifest.xml.
You can use for that next method ParseUser.setPassword().
Idea is next, if user is logged in then you don't need to check old password, because it was already entered and applied by Parse.com. So you will have 2 fields New Password and Confirm New Password. Users enters them and application changes it on server.
ParseUser parseUser = ParseUser.getCurrentUser();
parseUser.setPassword(password);
parseUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (null == e) {
// report about success
} else {
// report about error
}
}
});

Firebase: How to keep an Android user logged in?

I'm using Firebase SimpleLogin to enable Email / Password authentication. Creation of users and subsequent login is all working fine. However, whenever I leave the app (even if only for a few seconds) the user is never logged in on my return i.e...
authClient.checkAuthStatus(new SimpleLoginAuthenticatedHandler())...
Always returns a null user.
I am not logging out the user via the API. Also I have set the number of days the user is logged in to 21 in the Firebase console.
I have seen mention of a remember-me param in the JS docs, but I can't see any equivalent for Android / Java.
Wondering if I'm missing anything in the docs or if it's not possible for Android?
Thanks for your help,
Neil.
Edit: Added code sample.
User creation....
public void registerUserForChat(final MyApplication application, String email, String password) {
Firebase ref = new Firebase(FIREBASE_URL);
SimpleLogin authClient = new SimpleLogin(ref);
authClient.createUser(email, password, new SimpleLoginAuthenticatedHandler() {
#Override
public void authenticated(com.firebase.simplelogin.enums.Error error, User user) {
if(error != null) {
Log.e(TAG, "Error attempting to create new Firebase User: " + error);
}
else {
Log.d(TAG, "User successfully registered for Firebase");
application.setLoggedIntoChat(true);
}
}
});
}
User login....
public void loginUserForChat(final MyApplication application, String email, String password) {
Log.d(TAG, "Attempting to login Firebase user...");
Firebase ref = new Firebase(FirebaseService.FIREBASE_URL);
final SimpleLogin authClient = new SimpleLogin(ref);
authClient.checkAuthStatus(new SimpleLoginAuthenticatedHandler() {
#Override
public void authenticated(com.firebase.simplelogin.enums.Error error, User user) {
if (error != null) {
Log.d(TAG, "error performing check: " + error);
} else if (user == null) {
Log.d(TAG, "no user logged in. Will login...");
authClient.loginWithEmail(email, password, new SimpleLoginAuthenticatedHandler() {
#Override
public void authenticated(com.firebase.simplelogin.enums.Error error, User user) {
if(error != null) {
if(com.firebase.simplelogin.enums.Error.UserDoesNotExist == error) {
Log.e(TAG, "UserDoesNotExist!");
} else {
Log.e(TAG, "Error attempting to login Firebase User: " + error);
}
}
else {
Log.d(TAG, "User successfully logged into Firebase");
application.setLoggedIntoChat(true);
}
}
});
} else {
Log.d(TAG, "user is logged in");
}
}
});
}
So loginUserForChat method first checks to see if there is a logged in user and, if not, performs the login. Note that every time I start the app, the logging I see is....
Attempting to login Firebase user...
no user logged in. Will login...
User successfully logged into Firebase
If I exit the app, even for a few seconds, and return - I see the same logging.
One thing I noticed is that the call to checkAuthStatus does not take any user credentials - I assume it just checks for any locally logged in user?
Much appreciated.
Another way - try this code in your onCreate:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
Intent i = new Intent(LoginActivity.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
This will keep the user logged in by taking the user to the Main activity directly without stopping at registration activity. so the user will be logged in unless the user click on signout.
[Engineer at Firebase] In order to transparently handle persistent sessions in the Firebase Simple Login Java client, you need to use the two-argument constructor which accepts an Android context, i.e. SimpleLogin(com.firebase.client.Firebase ref, android.content.Context context) every time you instantiate the Simple Login Java client.
See https://www.firebase.com/docs/java-simple-login-api/javadoc/com/firebase/simplelogin/SimpleLogin.html for the full API reference.
The proper way to do it is to use oAuth authentication:
1. The user logs in.
2. You generate an access token(oAuth2).
3. Android app saves the token locally.
4. Each time the comes back to the auth, he can use the token to to log in, unless the token has been revoked by you, or he changed his
password.
Luckily, firebase has an out of the box support for that, docs:
https://www.firebase.com/docs/security/custom-login.html
https://www.firebase.com/docs/security/authentication.html
You can do this by Using this Approach to escape logi page if User already logged in.
private FirebaseAuth auth;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() != null) {
startActivity(new Intent(Login_Activity.this, Home.class));
finish();
}
setContentView(R.layout.activity_login_);
for those using Kotlin, to keep the user logged in just add in the onCreate function
if (auth.currentUser != null)
{
startActivity(Intent(this#Login, SellingPageHolderActivity::class.java))
finish()
}

Categories

Resources